Translate (gradually - with animate) an svg element after a delay using jQuery - javascript

I have this cubes which I want to translate to a different X and Y point after a delay of say 3000. I am not able to understand how to do this with the help of jQuery. Here is a JS Fiddle. Below is the code.
JS
// code for fade in one by one
console.log("game begins");
allSVGs = $("g");
fadeIn(0);
setTimeout(function () {
$("#cubeTop").animate({
svgTransform: "translate(0, -160)"
});
}, 3000);
function fadeIn(svgIndex) {
console.log(svgIndex);
allSVGs.eq(svgIndex).css({
"display": "block",
"opacity": "0"
});
allSVGs.eq(svgIndex).animate({
"opacity": "1"
}, {
complete: function () {
svgIndex++;
if (svgIndex < allSVGs.length) //Making sure we don't exceed the maximum available SVG elements
fadeIn(svgIndex); //Recursively calling the next elements animation (hide) from the completed one.
},
duration: 400
});
}
Thanks in advance.
PS: Sorry for not being clear. I just made an edit to the question.

Well it is possible. I just made some changes to your setTimeOut. Check if this is what you want:
setTimeout(function () {
$("#cubeTop")
.animate(
{"min-height": -140},
{duration: 1000,
step: function( top ){
this.setAttribute("transform", "translate(0,"+top+")");
}
});
}, 3000);
Here is the DEMO

You can try something like this
$("#cubeTop").attr({
transform:'translate(0,-140)'
})
// code for fade in one by one
console.log("game begins");
allSVGs = $("g");
fadeIn(0);
setTimeout(function () {
$("#cubeTop").attr({
transform:'translate(0,-140)'
})
}, 3000);
function fadeIn(svgIndex) {
console.log(svgIndex);
allSVGs.eq(svgIndex).css({
"display": "block",
"opacity": "0"
});
allSVGs.eq(svgIndex).animate({
"opacity": "1"
}, {
complete: function () {
svgIndex++;
if (svgIndex < allSVGs.length) //Making sure we don't exceed the maximum available SVG elements
fadeIn(svgIndex); //Recursively calling the next elements animation (hide) from the completed one.
},
duration: 400
});
}
svg {
position: absolute;
left: 0;
top: 0;
}
#cube {
fill: none;
stroke: black;
cursor: pointer;
display: none;
}
#cubeTop {
fill: none;
stroke: black;
cursor: pointer;
display: none;
}
#cubeTopRight {
fill: none;
stroke: red;
cursor: pointer;
display: none;
}
#cubeTopRightDown {
fill: none;
stroke: black;
cursor: pointer;
display: none;
}
#cubeDown {
fill: none;
stroke: red;
cursor: pointer;
display: none;
}
#cubeLeftDown {
fill: none;
stroke: black;
cursor: pointer;
display: none;
}
#cubeLeft {
fill: none;
stroke: red;
cursor: pointer;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<svg height="100%" version="1.1" width="100%" xmlns="http://www.w3.org/2000/svg">
<g id="cube">
<path id="f1" d="M190,200L260,160L330,200L260,240L190,200"></path>
<path id="f2" d="M260,240L330,200L330,280L260,320L260,240"></path>
<path id="f3" d="M260,240L260,320L190,280L190,200L260,240"></path>
</g>
<g id="cubeTop" transform="translate(0, -80)">
<path id="t1" d="M190,200L260,160L330,200L260,240L190,200"></path>
<path id="t2" d="M260,240L330,200L330,280L260,320L260,240"></path>
<path id="t3" d="M260,240L260,320L190,280L190,200L260,240"></path>
</g>
<g id="cubeTopRight" transform="translate(70, -40)">
<path id="r1" d="M190,200L260,160L330,200L260,240L190,200"></path>
<path id="r2" d="M260,240L330,200L330,280L260,320L260,240"></path>
<path id="r3" d="M260,240L260,320L190,280L190,200L260,240"></path>
</g>
<g id="cubeTopRightDown" transform="translate(70, 40)">
<path id="rd1" d="M190,200L260,160L330,200L260,240L190,200"></path>
<path id="rd2" d="M260,240L330,200L330,280L260,320L260,240"></path>
<path id="rd3" d="M260,240L260,320L190,280L190,200L260,240"></path>
</g>
<g id="cubeDown" transform="translate(0, 80)">
<path id="cd1" d="M190,200L260,160L330,200L260,240L190,200"></path>
<path id="cd2" d="M260,240L330,200L330,280L260,320L260,240"></path>
<path id="cd3" d="M260,240L260,320L190,280L190,200L260,240"></path>
</g>
<g id="cubeLeftDown" transform="translate(-70, 40)">
<path id="ld1" d="M190,200L260,160L330,200L260,240L190,200"></path>
<path id="ld2" d="M260,240L330,200L330,280L260,320L260,240"></path>
<path id="ld3" d="M260,240L260,320L190,280L190,200L260,240"></path>
</g>
<g id="cubeLeft" transform="translate(-70, -40)">
<path id="l1" d="M190,200L260,160L330,200L260,240L190,200"></path>
<path id="l2" d="M260,240L330,200L330,280L260,320L260,240"></path>
<path id="l3" d="M260,240L260,320L190,280L190,200L260,240"></path>
</g>
</svg>

Add all the stuff in setTimeout function and try.
// code for fade in one by one
setTimeout(function() {
console.log("game begins");
allSVGs = $("g");
fadeIn(0);
$("#cubeTop").animate({
svgTransform: "translate(0, -160)"
});
function fadeIn(svgIndex) {
console.log(svgIndex);
allSVGs.eq(svgIndex).css({
"display": "block",
"opacity": "0"
});
allSVGs.eq(svgIndex).animate({
"opacity": "1"
}, {
complete: function() {
svgIndex++;
if (svgIndex < allSVGs.length) //Making sure we don't exceed the maximum available SVG elements
fadeIn(svgIndex); //Recursively calling the next elements animation (hide) from the completed one.
},
duration: 400
});
}
}, 3000);

Related

how to make svg curve at one end

im using svg for circular progress bar , i want to make one end curve not the both end . how is this possible ?
how can i implement one end curve in svg?
svg {
height: 80vh;
margin: 10vh auto;
border: 1px solid red;
display: block;
transform: rotate(-90deg);
}
svg circle {
stroke-width: 10;
fill: transparent;
}
#outer {
stroke: lightgrey;
}
#inner {
stroke: blue;
animation: value 2.5s linear forwards;
stroke-linecap: round;
}
#keyframes value {
0% {
stroke-dasharray: 0 100;
}
100% {
stroke-dasharray: 90 100;
}
}
<svg viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle id="outer" cx="50" cy="50" r="40" />
<circle id="inner" pathLength="100" cx="50" cy="50" r="40" />
</svg>
The easiest way would be to mask the starting point of the blue circle.
For this you will need a <mask> like so:
<mask id="m">
<rect width="100" height="100" fill="white"/>
<rect x="85" y="40" width="10" height="10" />
</mask>
Please observe that the first rectangle is white and it covers the whole chart. (Everything under a white pixel will be visible). The smaller rectangle is black and covers the starting point of the blue circle. Everything under a black pixel will be invisible.
svg {
height: 80vh;
margin: 10vh auto;
border: 1px solid red;
display: block;
transform: rotate(-90deg);
}
svg circle {
stroke-width: 10;
fill: transparent;
}
#outer {
stroke: lightgrey;
}
#inner {
stroke: blue;
animation: value 2.5s linear forwards;
stroke-linecap: round;
}
#keyframes value {
0% {
stroke-dasharray: 0 100;
}
100% {
stroke-dasharray: 90 100;
}
}
<svg viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<mask id="m">
<rect width="100" height="100" fill="white"/>
<rect x="85" y="40" width="10" height="10" />
</mask>
<circle id="outer" cx="50" cy="50" r="40" />
<circle id="inner" pathLength="100" cx="50" cy="50" r="40" mask="url(#m)" />
</svg>
Try this code:
svg {
height: 80vh;
margin: 10vh auto;
border: 1px solid red;
display: block;
transform: rotate(-90deg);
border-top-right-radius: 20px;
}
svg circle {
stroke-width: 10;
fill: transparent;
}
#outer {
stroke: lightgrey;
}
#inner {
stroke: blue;
animation: value 2.5s linear forwards;
stroke-linecap: round;
}
#keyframes value {
0% {
stroke-dasharray: 0 100;
}
100% {
stroke-dasharray: 90 100;
}
}
<svg viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle id="outer" cx="50" cy="50" r="40" />
<circle id="inner" pathLength="100" cx="50" cy="50" r="40" />
</svg>
I came up with an alternative solution than enxaneta suggested. The problem with using a mask is that when your value goes over 96% or so, the circle isn't completely filled and the mask is revealed.
Instead, you can set a rounded progress line on top of another progress line that has flat endcaps. By rotating the rounded progress line by roughly 5 degrees, the flat end is revealed.
Here's how to do that in React Native with react-native-svg:
const radius = 60;
let myPercentage = 40;
const circleCircumference = 2 * Math.PI * radius;
const valueOffset = circleCircumference -
(circleCircumference * myPercentage * 0.98) / 100;
<Svg height={radius * 2 + 30} width={radius * 2 + 30}>
<G rotation={-90} originX={radius + 15} originY={radius + 15}>
// Background gray circle
<Circle
cx="50%"
cy="50%"
r={radius}
stroke="rgb(60, 60, 60)"
fill="transparent"
strokeWidth="10"
strokeDasharray={circleCircumference}
strokeLinecap="butt"
/>
// Background progress circle with flat ends
<Circle
cx="50%"
cy="50%"
r={radius}
stroke={"rgb(0, 51, 204)"}
fill="transparent"
strokeWidth="10"
strokeDasharray={circleCircumference}
strokeDashoffset={valueOffset}
strokeLinecap="butt"
/>
// Progress circle with round ends rotated by 5 degrees
<Circle
cx="50%"
cy="50%"
r={radius}
stroke={rgb(0, 51, 204)}
fill="transparent"
rotation={5}
originX={radius + 15}
originY={radius + 15}
strokeWidth="10"
strokeDasharray={circleCircumference}
strokeDashoffset={valueOffset}
strokeLinecap="round"
/>
</G>
</Svg>

Mousemove and Hover Jquery effect to Pure Javascript or VueJS event

I have a VueJS component which is a svg map image of the united states. I previously used jquery to create hover effects to display the information bubble. I am trying to convert this to a pure Javascript solution. It seems a click event is the easiest to implement given vuejs mousemove seems to be less reliable. I have added the click event in method and I am trying to capture the SVG path location and steal the top and left position to enable the info box there. I have tried this.offsettop and this.offsetleft but they return undefined.
Jquery code I am trying to convert:
$("path, circle").hover(function(e) {
$('#info-box').css('display','block');
$('#info-box').html($(this).data('info'));
});
$("path, circle").mouseleave(function(e) {
$('#info-box').css('display','none');
});
$(document).mousemove(function(e) {
$('#info-box').css('top',e.pageY-$('#info-box').height()-30);
$('#info-box').css('left',e.pageX-($('#info-box').width())/2);
}).mouseover();
var ios = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
if(ios) {
$('a').on('click touchend', function() {
var link = $(this).attr('href');
window.open(link,'_blank');
return false;
});
}
VueJS Component
<template id="geomap-assignments">
<v-card class="pa-4 ma-3 rounded-lg" min-height="500px">
<div class="card-title-docs">
<h4 class="card-header">Assignments</h4>
<h5 class="card-sub-header"></h5>
</div>
<div class="map-container">
<div id="info-box"></div>
<?xml version="1.0" encoding="utf-8" ?>
<svg xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="us-map" preserveAspectRatio="xMinYMin meet" sodipodi:docname="Republican_Party_presidential_primaries_results,_2016.svg" inkscape:version="0.91 r13725" x="0px" y="0px" width="959px" height="593px" viewBox="174 100 959 593" enable-background="new 174 100 959 593" xml:space="preserve">
<sodipodi:namedview bordercolor="#666666" objecttolerance="10" pagecolor="#ffffff" borderopacity="1" gridtolerance="10" guidetolerance="10" inkscape:cx="509.19152" inkscape:cy="282.2353" inkscape:zoom="1.2137643" showgrid="false" id="namedview71" inkscape:current-layer="g5" inkscape:window-maximized="1" inkscape:window-y="-8" inkscape:window-x="-8" inkscape:pageopacity="0" inkscape:window-height="1017" inkscape:window-width="1920" inkscape:pageshadow="2">
</sodipodi:namedview>
<g id="g5">
<path id="HI" data-info="<div>State: Hawaii</div><div>Capital: Honolulu</div>" fill="#D3D3D3" d="M407.1,619.3l1.9-3.6l2.3-0.3l0.3,0.8l-2.1,3.1H407.1z M417.3,615.6l6.1,2.6l2.1-0.3l1.6-3.9 l-0.6-3.4l-4.2-0.5l-4,1.8L417.3,615.6z M448,625.6l3.7,5.5l2.4-0.3l1.1-0.5l1.5,1.3l3.7-0.2l1-1.5l-2.9-1.8l-1.9-3.7l-2.1-3.6 l-5.8,2.9L448,625.6z M468.2,634.5l1.3-1.9l4.7,1l0.6-0.5l6.1,0.6l-0.3,1.3l-2.6,1.5l-4.4-0.3L468.2,634.5z M473.5,639.7l1.9,3.9 l3.1-1.1l0.3-1.6l-1.6-2.1l-3.7-0.3V639.7z M480.5,638.5l2.3-2.9l4.7,2.4l4.4,1.1l4.4,2.7v1.9l-3.6,1.8l-4.8,1l-2.4-1.5 L480.5,638.5z M497.1,654.1l1.6-1.3l3.4,1.6l7.6,3.6l3.4,2.1l1.6,2.4l1.9,4.4l4,2.6l-0.3,1.3l-3.9,3.2l-4.2,1.5l-1.5-0.6l-3.1,1.8 l-2.4,3.2l-2.3,2.9l-1.8-0.2l-3.6-2.6l-0.3-4.5l0.6-2.4l-1.6-5.7l-2.1-1.8l-0.2-2.6l2.3-1l2.1-3.1l0.5-1l-1.6-1.8L497.1,654.1z" />
<path id="OK" data-info="<div>State: Oklahoma</div><div>Capital: Oklahoma City</div>" fill="#D3D3D3" d="M549.3,422.6l-10.7-0.5l-6.4-0.5l0.3,0.2l-0.7,10.4l22,1.4l32.1,1.3l-2.3,24.4l-0.5,17.8l0.2,1.6 l4.3,3.7l2.1,1.1l0.7-0.2l0.7-2.1l1.4,1.8h2.1v-1.4l2.7,1.4l-0.5,3.9l4.1,0.2l2.5,1.1l4.1,0.7l2.5,1.8l2.3-2.1l3.4,0.7l2.5,3.4h0.9 v2.3l2.3,0.7l2.3-2.3l1.8,0.7h2.5l0.9,2.5l4.8,1.8l1.4-0.7l1.8-4.1h1.1l1.1,2.1l4.1,0.7l3.7,1.4l3,0.9l1.8-0.9l0.7-2.5h4.3l2.1,0.9 l2.7-2.1h1.1l0.7,1.6h4.1l1.6-2.1l1.8,0.5l2.1,2.5l3.2,1.8l3.2,0.9l1.9,1.1l-0.4-37.2l-1.4-11l-0.2-8.9l-1.4-6.5l-0.8-7.2l-0.1-3.8 l-12.1,0.3l-46.4-0.5l-45-2.1L549.3,422.6z" />
<path id="KS" data-info="<div>State: Kansas</div><div>Capital: Topeka</div>" fill="#D3D3D3" d="M677.4,425.1l-12.6,0.2l-46.1-0.5l-44.6-2.1l-24.6-1.3l4.1-64.7l21.8,0.8l40.5,1.4l44.1,0.5h5.1 l3.2,3.2l2.8,0.2l0.9,1.1v2l-1.8,1.6l-0.5,2.6l2.2,3.6l2.5,3.1l2.5,2l1.1,11.2L677.4,425.1z" />
<path id="LA" data-info="<div>State: Louisiana</div><div>Capital: Baton Rouge</div>" fill="#D3D3D3" d="M776.2,573l-1-2.6l-1.1-3.1l-3.3-3.5l0.9-6.8l-0.1-1.1l-1.3,0.3l-8.2,0.9l-25,0.5l-0.7-2.4l0.9-8.5 l3.3-5.9l5-8.7l-0.6-2.4l1.3-0.7l0.5-2l-2.3-2.1l-0.1-1.9l-1.8-4.3l-0.5-5.9l-9.7,0.1l-19.2,0.9l-22.2,0l0,9.6l0.7,9.4l0.7,3.9 l2.5,4.1l0.9,5l4.3,5.5l0.2,3.2l0.7,0.7l-0.7,8.5l-3,5l1.6,2.1l-0.7,2.5l-0.7,7.3l-1.4,3.2l0.1,3.6l4.7-1.5l8.1-0.3l10.3,3.6 l6.5,1.1l3.7-1.5l3.2,1.1l3.2,1l0.8-2.1l-3.2-1.1l-2.6,0.5l-2.7-1.6c0,0,0.2-1.3,0.8-1.5c0.6-0.2,3.1-1,3.1-1l1.8,1.5l1.8-1 l3.2,0.6l1.5,2.4l0.3,2.3l4.5,0.3l1.8,1.8l-0.8,1.6l-1.3,0.8l1.6,1.6l8.4,3.6l3.6-1.3l1-2.4l2.6-0.6l1.8-1.5l1.3,1l0.8,2.9 l-2.3,0.8l0.6,0.6l3.4-1.3l2.3-3.4l0.8-0.5l-2.1-0.3l0.8-1.6l-0.2-1.5l2.1-0.5l1.1-1.3l0.6,0.8c0,0-0.2,3.1,0.6,3.1 c0.8,0,4.2,0.6,4.2,0.6l4,1.9l1,1.5h2.9l1.1,1l2.3-3.1v-1.5h-1.3l-3.4-2.7l-5.8-0.8l-3.2-2.3l1.1-2.7l2.3,0.3l0.2-0.6l-1.8-1v-0.5 h3.2l1.8-3.1l-1.3-1.9l-0.3-2.7l-1.5,0.2l-1.9,2.1l-0.6,2.6l-3.1-0.6l-1-1.8l1.8-1.9l2-1.8L776.2,573z" />
<path id="VA" data-info="<div>State: Virginia</div><div>Capital: Richmond</div>" fill="#D3D3D3" d="M1002.9,369.2l-0.1-1.9l6.5-2.5l-0.8,3.2l-2.9,3.8l-0.4,4.6l0.5,3.4l-1.8,5l-2.2,1.9l-1.5-4.6 l0.4-5.4l1.6-4.2L1002.9,369.2z M1005.2,397.5L947,410.1l-37.4,5.3l-6.7-0.4l-2.6,1.9l-7.3,0.2l-8.4,1l-8.9,1l8.5-4.9l0-2.1 l1.5-2.1l10.6-11.5l3.9,4.5l3.8,1l2.5-1.1l2.2-1.3l2.5,1.3l3.9-1.4l1.9-4.6l2.6,0.5l2.9-2.1l1.8,0.5l2.8-3.7l0.3-2.1l-1-1.3l1-1.9 l5.3-12.3l0.6-5.7l1.2-0.5l2.2,2.4l3.9-0.3l1.9-7.6l2.8-0.6l1-2.7l2.6-2.3l1.3-2.3l1.5-3.4l0.1-5.1l9.8,3.8 c0.7,0.3,0.7-4.8,0.7-4.8l4.1,1.4l-0.5,2.6l8.2,2.9l1.3,1.8l-0.9,3.7l-1.3,1.3l-0.5,1.7l0.5,2.4l2,1.3l3.9,1.4l2.9,1l4.9,0.9 l2.2,2.1l3.2,0.4l0.9,1.2l-0.4,4.7l1.4,1.1l-0.5,1.9l1.2,0.8l-0.2,1.4l-2.7-0.1l0.1,1.6l2.3,1.5l0.1,1.4l1.8,1.8l0.5,2.5l-2.6,1.4 l1.6,1.5l5.8-1.7L1005.2,397.5z" />
<g id="DC">
<path id="path58" fill="#D3D3D3" d="M975.8,353.8l-1.1-1.6l-1-0.8l1.1-1.6l2.2,1.5L975.8,353.8z" />
<circle id="circle60" data-info="<div>Washington DC</div>" fill="#D3D3D3" stroke="#FFFFFF" stroke-width="1.5" cx="975.3" cy="351.8" r="5" />
</g>
</g>
<path id="path67" fill="none" stroke="#A9A9A9" stroke-width="2" d="M385,593v55l36,45 M174,525h144l67,68h86l53,54v46" />
</svg>
</div>
</v-card>
</template>
<script>
Vue.component('geomap-assignments', {
template: '#geomap-assignments',
methods: {
activateCaption: function (event) {
// `event` is the native DOM event
if (event) {
const left = this.offsetTop
const top = this.offsetTop
alert("LEFT" + left + "RIGHT" + top);
}
}
},
data() {
return {
documents: [
]
}
}
})
</script>
<style scoped>
.card-title-docs {
margin: 20px 20px;
}
.card-header {
font-size: 1rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 1px;
color: #515151;
}
.card-sub-header {
font-size: .8rem;
font-weight: 500;
text-transform: uppercase;
letter-spacing: .7px;
color: #7f818d;
}
.map-container{
position:relative;
width: 100%;
height: 100%;
}
#us-map {
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
path:hover, circle:hover {
stroke: #002868 !important;
stroke-width: 2px;
stroke-linejoin: round;
fill: #002868 !important;
cursor: pointer;
}
#path67 {
fill: none !important;
stroke: #A9A9A9 !important;
cursor: default;
}
#info-box {
display: none;
position: absolute;
top: 0px;
left: 0px;
z-index: 1;
background-color: #ffffff;
border: 2px solid #BF0A30;
border-radius: 5px;
padding: 5px;
font-family: arial;
}
</style>
'''
The solution was found in the comments on the question.
In summary, the issue was understanding how to position the #info-box element. Using the getBoundingClientRect() function, we can get the position of any element relative to the entire document. To get the position of the clicked path element, simply subtract the top and left of the #us-map from the top and left of the path. This will give the position for the top left corner of the path, relative to the containing element. We can then use that to position the #info-box.

Isolate section of SVG when mouse is hovered

I am attempting to build an interactive map from scratch. I have an SVG of the map of Canada that has separate layers for each province. I'd like to highlight a specific province/territory when the mouse is hovered over it.
I have tried using a function that gets the live update of the mouse coordinates, but I am unsure as to how to figure out which section of the image it is on. I am unsure as to if this is the best method of doing it.
Through some of my research, I have found a method of gathering the pointer coordinates:
let x = 0;
let y = 0;
function showCoords() {
x = event.clientX;
y = event.clientY;
}
And I call it around the SVG using:
<div onmousemove="showCoords()">
...SVG HERE
</div>
I can select the different layers inside of the SVG, but the question is if I can find a way of checking which layer my mouse is currently over.
Thank you!
Edit:
I have reached a solution that accomplishes my goal, but I am unsure as to if it is efficient.
Using CSS, I fill each group upon hover:
#canada {
fill: hsl(0, 0%, 29%);
}
#canada g {
transition: .3s;
}
#canada g:hover {
fill: hsl(189, 88%, 59%);
}
I am also using the onClick option on each group to pull up their dialogue.
Maybe something like this? Just keep "data-name" attribute on each <g> inside svg code.
let x = 0;
let y = 0;
let svgCountry = document.querySelector("#states svg");
let svgStates = svgCountry.querySelectorAll("[data-name]");
let resContainer = document.getElementById("state-hovered-is");
// init tooltip
function showCoords(event) {
let x = event.clientX;
let y = event.clientY;
resContainer.setAttribute("style", "left:" + (x + 15) + "px;" + "top:" + (y - 50) + "px;");
}
// close tooltip
function clearCoor() {
resContainer.innerHTML = "";
}
// clear everything
function clearAllOn() {
svgStates.forEach(function(el) {
el.classList.remove("hover");
resContainer.innerHTML = "";
console.clear();
});
}
// display current state in div
function displayState(el) {
var res = el.getAttribute("data-name");
el.classList.add("hover");
resContainer.innerHTML = "<p>You're at" + " " + res + "</p>";
console.log(res);
}
svgStates.forEach(function(el) {
// mouse events
el.addEventListener("mouseenter", function() {
displayState(el);
});
el.addEventListener("mouseleave", function() {
clearAllOn();
});
// touch events
el.addEventListener("touchstart", function() {
clearAllOn();
displayState(el);
});
});
body {
background-color: #fff;
font-family: Arial, Helvetica, sans-serif;
color: #333;
}
g.hover {
opacity: 0.5;
}
#states {
margin: 0 auto;
width: 600px;
max-width: 100%;
position: relative;
}
#state-hovered-is {
text-align: center;
min-height: 50px;
position: fixed;
pointer-events: none;
background-color: rgba(0, 0, 0, 0.76);
border-radius: 6px;
}
#state-hovered-is p {
color: #fff;
margin: 0;
padding: 15px;
width: 180px;
}
<div id="states" onmousemove="showCoords(event)" onmouseout="clearCoor()">
<!-- State name here -->
<div id="state-hovered-is"></div>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 961.38 830.7">
<defs>
<style>
.cls-1 { fill: #fff;}
.cls-2 {fill: #b8c4e6;}
.cls-3 {fill: #ce8080;}
.cls-4 {fill: #e99bd2;}
.cls-5 {fill: #acac90;}
.cls-6 {fill: #e6c0c0;}
.cls-7 {fill: #4d6ac1;}
.cls-8 {fill: #c9e6b8;}
.cls-9 {fill: #f3f3db;}
.cls-10 {fill: #cece71;}
.cls-11 {fill: #7188ce;}
.cls-12 {fill: #daa0a0;}
.cls-13 {fill: #91916b;}
.cls-14 {fill: #dada94;}
.cls-15 {fill: #916b86;}
</style>
</defs>
<title>Canada</title>
<g id="Layer_1">
<ellipse class="cls-1" cx="480.69" cy="415.35" rx="679.8" ry="587.39" />
<path class="cls-1" d="M539.84,220.75c-2.45,5-6.57,8.18-10.72,11.7l2-9.56C534.53,224.17,537,221.84,539.84,220.75Z" transform="translate(-0.06 -0.26)" />
<path class="cls-1" d="M53,543.56c-1.09,2.13-2.18,4.23-3.52,6.84l-.51-10.68.56-.25Z" transform="translate(-0.06 -0.26)" />
<path class="cls-1" d="M771.19,558.14c-.32-2.18-.77-4.36-.89-6.56a3.15,3.15,0,0,1,1.31-2.05,1.76,1.76,0,0,1,1.64.49,4.19,4.19,0,0,1,.17,2.5c-.48,1.84-1.18,3.62-1.79,5.43Z" transform="translate(-0.06 -0.26)" />
<path class="cls-1" d="M40.77,527.77l-7-8.41.35-.18A76,76,0,0,1,40.4,524c.77.71.87,2.14,1.27,3.25Z" transform="translate(-0.06 -0.26)" />
<path class="cls-1" d="M493.56,95.47l3.41,6L485.7,105a30.91,30.91,0,0,1,2.81-2.42C491.7,100.51,493.64,100.2,493.56,95.47Z" transform="translate(-0.06 -0.26)" />
</g>
<g id="Yukon" data-name="Yukon">
<path class="cls-3" d="M174.12,185.61c.91,1.61.88,2.8-.63,4.31-4.21,4.21-8.16,8.68-12.2,13.07-.34.38-.78,1-.72,1.39.58,3.9-2,6.08-4.31,8.53a6.48,6.48,0,0,0-1.84,3.83,5.33,5.33,0,0,0,1.79,3.5c1.85,1.68,4.07,2.94,6,4.53,3.45,2.83,3.47,5.7.33,9.15-2.19,2.39-4.41,4.77-6.37,7.34-1.76,2.3-1.12,4.05,1.42,5.49,1.4.81,2.66,1.88,4.19,3-2.18,1.51-3.35,2.81-2.33,5.22.45,1.05,0,2.31-1.73,2.4a17.09,17.09,0,0,0-3.62.83c-4.36,1.21-5.4,4.72-5.53,8.56a57.14,57.14,0,0,0,.5,10c.23,1.57,1.5,3,2.39,4.63-2.26,2.84-2.38,6.32-1.6,10.12a46.41,46.41,0,0,1,.52,7.56,1.6,1.6,0,0,1-.82,1.17c-2.55,1.24-3,3.61-3.48,6a9.38,9.38,0,0,1-1.27,3.48,10.68,10.68,0,0,0-1.7,8.87,2.39,2.39,0,0,1-.44,1.48c-.6,1-1.32,2-2,2.93-1.42,2.18-1.43,4,.77,5.24,3.32,1.83,3.1,4.7,2.57,7.41-.72,3.66-.45,6.87,2,9.78,1.47,1.77,1.39,3.3-.37,4.95a7.72,7.72,0,0,0-1.45,3.08c-.28.81-.27,1.71-.5,2.53-1.52,5.43,1,6.26,4.74,7.61,1.41.5,2.57,1.66,3.93,2.34a26.86,26.86,0,0,0,4.63,1.87c1.72.5,3.51.73,5.24,1.06.05.25.15.5.1.53-3,2.14-3,5.28-2.81,8.48.09,2,0,4,0,6.25A575.11,575.11,0,0,1,48.14,298a7.87,7.87,0,0,1,.58-.75c3.2-3.33,3.13-5.09-.71-7.55a38.29,38.29,0,0,0-6.52-3.12c-2.14-.86-3.05-5-1.32-6.73q13.23-13,26.49-26c6.81-6.67,13.65-13.31,20.46-20q13.26-13,26.5-26,10.56-10.35,21.15-20.68,11.07-10.83,22.16-21.66c1.92-1.87,3.87-3.74,6-5.43a2.44,2.44,0,0,1,2.34-.08,12.63,12.63,0,0,1,4.51,7.68c.95,5.52,2.44,10.95,3.73,16.42A5.64,5.64,0,0,0,174.12,185.61Z" transform="translate(-0.06 -0.26)" />
</g>
<g id="British_Columiba" data-name="British Columiba">
<g>
<path class="cls-4" d="M190.26,405.28c.27.14.53.31,1.06.62-1,1.88-2,3.69-2.9,5.53-5.64,11.14-11.24,22.3-16.9,33.43-4.43,8.73-8.92,17.42-13.38,26.13l-19.37,37.93c-.21.42-.68.84-.65,1.24.17,2.7,0,5.24-2.52,6.95.78,2,1.25,4.14,2.45,5.8.82,1.15,1.83,1.89,1.89,3.54s.46,3.46,2.33,4.55c2.39,1.41,1.92,4.19,2.3,6.41.31,1.81-.17,3.77-.35,5.66s.8,3.35,2.22,4.62a2.72,2.72,0,0,1,.81,2.17,5.54,5.54,0,0,0,1.49,5.42c.88,1,1.18,2.44,1.69,3.71.82,2,1.6,4,2.38,6,1,2.51,2,5,2.9,7.55.32.88.14,2.18.72,2.67,3.23,2.74,2.75,6.63,3,10.1a15.41,15.41,0,0,0,3.74,8.9c3.16,3.57,2.61,7,1.68,10.73-.83,3.31-1.92,6.57-3,9.84s-.35,6.2,1.21,9.74c-5.31-2.27-10.13-4.28-14.9-6.38-10.53-4.64-21.08-9.23-31.54-14-8.14-3.72-16.25-7.52-24.19-11.65-8.81-4.6-17.41-9.61-26.09-14.47a2,2,0,0,1-1-1.12,65.21,65.21,0,0,1-1-7.47c-.16-3.6-1.05-5-4.37-5.94,0-1.19,0-2.34,0-3.5a3.82,3.82,0,0,0-2.71-3.76c-1.17-.5-3.27-.93-3.32-1.53a9.88,9.88,0,0,1,.91-5.44c3.08-5.49,3.08-7.06-1-11.44-2.29-2.47-4.78-4.79-6.82-7.46a9.16,9.16,0,0,1-1.44-4.76c-.2-2.61-1.08-4.69-3.49-5.72-3.27-1.39-4.67-4.2-5.48-7.23a5.27,5.27,0,0,1,1-4.36,5.48,5.48,0,0,0,1.59-5.2c-.48-3.26,1.93-4.89,4.78-5.55a19.58,19.58,0,0,0,3.83-1c2.43-1.12,2.65-3.06.7-4.87a7.78,7.78,0,0,1-2-9.22c1.46-3.4,1.33-5.05-1-6.15-1.19-.56-2.78-.29-4.19-.39-.47,0-.93-.05-1.65-.09,1.67-3,3-5.78,6.86-6.28a4.12,4.12,0,0,0,3.2-2.73c.72-1.68,2.44-2.95,3.74-4.38,1.14-1.23,1.82-2.81.52-4a5.8,5.8,0,0,0-4-1A30.06,30.06,0,0,0,44.62,459c-1.84-6.08-.47-11.9,1.17-17.65A3.74,3.74,0,0,1,48,439.05c7.2-1.55,10.53-7,13.68-12.85a30.35,30.35,0,0,1,3.83-4.91c1.69-2,2.72-4.14,1.8-6.84s-1.71-5.51-2.66-8.23A52.51,52.51,0,0,0,62,399.51c-1.34-2.62-.9-5.19-.39-7.83q2.15-11.08,4.26-22.15c1.08-5.61,2.21-11.21,3.21-16.84a9.48,9.48,0,0,0-.36-2.74c-.16-1.32-.33-2.65-.44-4-.14-1.58-.18-3.17-.36-4.74a11.92,11.92,0,0,1,1.16-7.34c1.92-3.53,1.66-7.9-.48-9.87l1.06-1.21c7.65,6.68,15.29,13.38,23.2,19.74,8.69,7,17.59,13.76,26.79,20,13.27,9,26.71,17.88,40.42,26.24C169.85,394.8,180.18,399.83,190.26,405.28Z" transform="translate(-0.06 -0.26)" />
<path class="cls-4" d="M67.71,323.4c-4.2-2.13-8.84-4.21-13.43-1.55-2.84,1.64-5.18.87-8.06.13,2.21-2.52,1.9-5.53,1.88-8.49s0-6.08,0-9.44a8.14,8.14,0,0,1,1.68.85c5.42,4.9,10.73,9.92,16.24,14.72l3.65,3.2L68.61,324A4,4,0,0,0,67.71,323.4Z" transform="translate(-0.06 -0.26)" />
<path class="cls-1" d="M52.34,580.17c.15,1.23-.68,2.57-1.25,4.47-2.23-1.77-4.17-2.89-5.53-4.5a75.63,75.63,0,0,1-5.85-8.23,3.32,3.32,0,0,1-.2-2.75c2.52-5.09,2.08-6.95-3.06-9.61-1.82-.94-2.5-1.94-2.32-4,.32-3.52.35-4.15-4.79-9.94,2-2.92,1.55-3.82-.24-7-1.32-2.35-1.69-5.31-2.07-8.06-.29-2.13-.63-4-2.58-5.25a2.26,2.26,0,0,1-.79-1.75c.24-3.45.6-6.89.93-10.33,2-.08,2.8,1.11,3.33,2.71A29.72,29.72,0,0,0,36,529,45.65,45.65,0,0,1,43,536.54c1.16,1.66,1.53,4.06,1.7,6.17a84.4,84.4,0,0,1,0,10.06c-.17,4.12,1.42,7.63,3.38,11.07a18,18,0,0,1,2.24,4.56A109.17,109.17,0,0,1,52.34,580.17Z" transform="translate(-0.06 -0.26)" />
<path class="cls-1" d="M17.57,426.81l6.17,8.48C16.39,441.78,11.81,449.73,11,459.7,10.41,448.18,12.87,437.39,17.57,426.81Z" transform="translate(-0.06 -0.26)" />
</g>
</g>
<g id="Alberta" data-name="Alberta">
<path class="cls-5" d="M194.56,407.63c27.17,14.46,55.83,25.35,85,35.57L214.1,643.67c-10.88-4-21.29-7.82-31.68-11.68-3.52-1.3-6.91-3-10.51-4s-5.08-3.41-6.18-6.74c-1.26-3.84-.43-7.18,1.12-10.59A26.88,26.88,0,0,0,169.13,597a4.52,4.52,0,0,0-1-2.58c-4.16-4.42-5.32-9.88-5.71-15.66-.07-1-.13-2.32-.75-2.88-2.84-2.56-2.45-6.26-3.65-9.38-.64-1.69-1.62-3.26-2.29-4.95-.84-2.14-1.52-4.35-2.27-6.53-.05-.15-.06-.35-.17-.44a6.25,6.25,0,0,1-2-7.07c.17-.6-1.07-1.75-1.85-2.43a2.33,2.33,0,0,1-1.08-2.43,28.92,28.92,0,0,0-.52-7.52c-.36-2.17,0-4.65-2.15-6.28-1.47-1.09-1.92-2.71-2.35-4.49-.35-1.45-1.6-2.69-2.47-4-.51-.77-1.07-1.51-1.72-2.42,2.55-1.41,2.87-3.59,2.69-6a5,5,0,0,1,.5-2.5q5-9.88,10-19.7c6.78-13.11,13.63-26.19,20.37-39.32,3.84-7.45,7.51-15,11.31-22.47C187.5,421.2,191,414.48,194.56,407.63Z" transform="translate(-0.06 -0.26)" />
</g>
</svg>
</div>
Here's how the full map looks: https://jsfiddle.net/darkosss/7umphzwn/

Javscript to dynamically build HTML/SVG for mobile view

I have a full screen SVG image/mask reveal; it works great on desktop but it doesn't scale/fit on mobile devices. So im guessing the best solution would be to dynamically build the SVG and SVG container depending on screen width and have a mobile & desktop build. So i'm looking for advice and the best solution and if someone could point me in the right direction or know of an example I can look at.
// DRAW SVG MASK /////////////////////////////
var svg = document.querySelector("#svg__bg");
var tl = new gsap.timeline({ onUpdate: onUpdate });
var pt = svg.createSVGPoint();
var ratio = 0.5625;
tl.to("#masker", {duration: 2, attr: {r: 2400}, ease: "power2.in" });
tl.reversed(true);
function mouseHandler() {
tl.reversed(!tl.reversed());
}
function getPoint(evt) {
pt.x = evt.clientX;
pt.y = evt.clientY;
return pt.matrixTransform(svg.getScreenCTM().inverse());
}
function mouseMove(evt) {
var newPoint = getPoint(evt);
gsap.set("#dot", { cx: newPoint.x, cy: newPoint.y });
gsap.to("#ring, #masker", {duration: 0.88, attr: { cx: newPoint.x, cy: newPoint.y }, ease: "power2.out" });
}
function onUpdate() {
var prog = (tl.progress() * 100);
}
function newSize() {
var w = window.innerWidth;
var h = window.innerHeight;
if (w > h * (16 / 9)) {
gsap.set("#svg__bg", { attr: { width: w, height: w * ratio } });
} else {
gsap.set("#svg__bg", {
attr: {
width: h / ratio,
height: h
}
});
}
var data = svg.getBoundingClientRect();
gsap.set("#svg__bg", {
x: w / 2 - data.width / 2
});
gsap.set("#svg__bg", {
y: h / 2 - data.height / 2
});
}
window.addEventListener("mousedown", mouseHandler);
window.addEventListener("mouseup", mouseHandler);
window.addEventListener("mousemove", mouseMove);
newSize();
window.addEventListener("resize", newSize);
#import url('https://fonts.googleapis.com/css?family=Montserrat:700&display=swap');
body {
min-height: 100vh;
background-color: #1F242D;
cursor: none;
overflow: hidden;
font-family: 'Montserrat', sans-serif;
}
.intro-svg {
position: relative;
padding: 0;
margin: 0;
width: 100%;
min-height: 100vh;
height: calc(var(--vh, 1vh) * 100);
overflow: hidden;
z-index: 1;
}
.svg__container {
height: 100%;
width: 100%;
position: relative;
overflow: hidden;
}
.svg__image {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
cursor: none;
}
.text-svg {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
cursor: none;
z-index:2;
}
.impact-text {
font-size: 7em;
line-height: 1.2;
text-transform: uppercase;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.6/gsap.min.js"></script>
<div class="intro-svg">
<div class="svg__container">
<svg id="svg__bg" class="svg__image" xmlns="http://www.w3.org/2000/svg" x="0" y="0" width="1600" height="900" viewBox="0 0 1600 900">
<defs>
<radialGradient id="mask-gradient">
<stop offset="80%" stop-color="#fff"/><stop offset="100%" stop-color="#000" />
</radialGradient>
<mask id="the-mask">
<circle id="masker" r="250" fill="url(#mask-gradient)" cx="800" cy="450">
</circle>
</mask>
<mask id="mask-text" width="100" height="100" x="0" y="0">
<text id="masker" class="impact-text row-1" fill="none" stroke="#fff" stroke-width="3" x="10.1%" y="42%">A</text>
<text id="masker" class="impact-text row-2" fill="white" x="10%" y="55%">Digital</text>
<text id="masker" class="impact-text row-3" fill="white" x="10%" y="68%">Designer</text>
</mask>
</defs>
<image id="lines" xlink:href="https://i.imgur.com/1TQRj56.jpg" x="0" y="0" width="1600" height="900" />
<g id="mask-reveal" mask="url(#the-mask)">
<image id="regular" xlink:href="https://i.imgur.com/7VtEKv3.jpg" x="0" y="0" width="1600" height="900" />
</g>
<g mask="url(#mask-text)">
<image id="text-before" xlink:href="https://i.imgur.com/7VtEKv3.jpg" x="0" y="0" width="1600" height="900" />
</g>
<circle id="ring" r="20" fill="none" stroke="#D74A53" stroke-width="2" cx="800" cy="450" />
<circle id="dot" r="4" fill="#D74A53" cx="800" cy="450"/>
</svg>
</div>
</div>
just add
#svg__bg {
width: 100%;
height:auto;
}
andchange them with media query
don't forget to change
<svg id="svg__bg" class="svg__image" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 1600 900">
without width="1600" height="900"

Can't get hamburger menu to animate on click

I targeted the SVG rect using :nth-chid(1), 2 and 3 and made a -> that I'm trying to trigger on click. Don't know what I'm doing wrong here. Any Help would be great thank you!
(function() {
var burger;
buger = document.getElementById('burger');
burger.addEventListener('click', function() {
console.log('you cliked the burger');
return burger.classList.toggle('st0-active');
});
}).call(this);
body {
max-width: 900px;
margin: 0 auto;
}
.st0-active:nth-child(1) {
-webkit-transform: rotate(27deg) translate(23px, -51px);
transform: rotate(27deg) translate(23px, -51px);
fill: #000;
}
.st0-active:nth-child(2) {
fill: #000;
}
.st0-active:nth-child(3) {
-webkit-transform: rotate(-21deg) translate(-48px, 15px);
transform: rotate(-21deg) translate(-48px, 15px);
fill: #000;
}
<body>
<svg class="mo-icon__svg" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve" id="burger">
<g id="icon_x5F_hamburger">
<rect x="0.11206" y="46.3329" class="st0" width="200" height="8"/>
<rect x="0.11206" y="96.22083" class="st0" width="200" height="8"/>
<rect x="0.11206" y="146.10876" class="st0" width="200" height="8"/>
</g>
</svg>
</body>
Here is a picture of my designed end goal
Which is the reason I'm using CSS Transforms and targeting the rect using nth-child Here is a link to the codepen that I'm currently working on
enter link description here
(function() {
var burger;
burger = document.getElementById('burger');
burger.addEventListener('click', function() {
console.log('you cliked the burger');
return burger.classList.toggle('st0-active');
});
}).call(this);
body {
max-width: 900px;
margin: 0 auto;
}
#burger > g > rect{
transition: transform 1s;
}
.st0-active > g > rect:nth-child(1) {
-webkit-transform: rotate(27deg) translate(23px, -51px);
transform: rotate(27deg) translate(23px, -51px);
fill: #000;
}
.st0-active > g > rect:nth-child(2) {
fill: #000;
}
.st0-active > g > rect:nth-child(3) {
-webkit-transform: rotate(-21deg) translate(-48px, 15px);
transform: rotate(-21deg) translate(-48px, 15px);
fill: #000;
}
<body>
<svg class="mo-icon__svg" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve" id="burger">
<g id="icon_x5F_hamburger">
<rect x="0.11206" y="46.3329" class="st0" width="200" height="8"/>
<rect x="0.11206" y="96.22083" class="st0" width="200" height="8"/>
<rect x="0.11206" y="146.10876" class="st0" width="200" height="8"/>
</g>
</svg>
</body>
Try to add this code.
#burger{
transition: transform 1s;
}
Additionally
CSS3 transitions allows you to change property values smoothly (from one value to another), over a given duration.

Categories