I am creating a donut chart with svg, and I would like to have tooltips on hover of the donut rings. I am building the donut like this:
.container {
display: flex;
flex-flow: row wrap;
}
.card {
width: 20em;
height: 20em;
padding: 2em;
background-color: white;
margin: 2em;
box-shadow: 0 0 5px #222;
}
.pie-center {
background: transparent;
border-radius: 50%;
transform: rotate(-90deg);
}
.circle1 {
fill: transparent;
stroke: teal;
stroke-width: 7;
stroke-dasharray: 30 70;
}
.circle2 {
fill: transparent;
stroke: orangered;
stroke-width: 7;
stroke-dasharray: 45 55;
stroke-dashoffset: -30;
}
.circle3 {
fill: transparent;
stroke: orchid;
stroke-width: 7;
stroke-dasharray: 20 80;
stroke-dashoffset: -75;
}
.circle4 {
fill: transparent;
stroke: yellowgreen;
stroke-width: 7;
stroke-dasharray: 5 95;
stroke-dashoffset: -95;
}
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="container">
<div class="card">
<svg class="pie-center" viewBox="0 0 32 32">
<circle class="circle1" r="15.915494309" cx="16" cy="16" />
<circle class="circle2" r="15.915494309" cx="16" cy="16" />
<circle class="circle3" r="15.915494309" cx="16" cy="16" />
<circle class="circle4" r="15.915494309" cx="16" cy="16" />
</svg>
</div>
</div>
</body>
</html>
I know that I can use the <set /> tag to capture mouse events, and I can use those to create a tooltip. The problem is each section of the donut ring is actually a circle, and the stroke property on the circle is the part I actually want to capture the hover event for.
Therefore, when I try to add hover actions to my circles I don't get desired results.
This is what I have tried (just turning the donut section red on hover to simulate capturing the event for adding a tooltip):
.container {
display: flex;
flex-flow: row wrap;
}
.card {
width: 20em;
height: 20em;
padding: 2em;
background-color: white;
margin: 2em;
box-shadow: 0 0 5px #222;
}
.pie-center {
background: transparent;
border-radius: 50%;
transform: rotate(-90deg);
}
.circle1 {
fill: transparent;
stroke: teal;
stroke-width: 7;
stroke-dasharray: 30 70;
}
.circle2 {
fill: transparent;
stroke: orangered;
stroke-width: 7;
stroke-dasharray: 45 55;
animation: dash3 1s ease 0s 1 forwards;
stroke-dashoffset: -30;
}
.circle3 {
fill: transparent;
stroke: orchid;
stroke-width: 7;
stroke-dasharray: 20 80;
animation: dash2 1s ease 0s 1 forwards;
stroke-dashoffset: -75;
}
.circle4 {
fill: transparent;
stroke: yellowgreen;
stroke-width: 7;
stroke-dasharray: 5 95;
animation: dash 1s ease 0s 1 forwards;
stroke-dashoffset: -95;
}
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="container">
<div class="card new">
<svg class="pie-center" viewBox="0 0 32 32">
<circle class="circle1" r="15.915494309" cx="16" cy="16" >
<set attributeName='stroke' from='teal' to='red' begin='mouseover' end='mouseout' />
</circle>
<circle class="circle2" r="15.915494309" cx="16" cy="16" >
<set attributeName='stroke' from='orangered' to='red' begin='mouseover' end='mouseout' />
</circle>
<circle class="circle3" r="15.915494309" cx="16" cy="16" >
<set attributeName='stroke' from='orchid' to='red' begin='mouseover' end='mouseout' />
</circle>
<circle class="circle4" r="15.915494309" cx="16" cy="16" >
<set attributeName='stroke' from='yellowgreen' to='red' begin='mouseover' end='mouseout' />
</circle>
</svg>
</div>
</body>
</html>
My question is: Is there any way to capture hover events on the circle strokes? Or is there another way to create a donut chart, using say <path /> or some other svg element that will better support the hover events?
I would like to not use third party libraries if possible (no D3, or chart.js).
Use fill: none rather than fill: transparent so that the fill does not react. In fact there's really no good reason to use fill: transparent ever.
.container {
display: flex;
flex-flow: row wrap;
}
.card {
width: 20em;
height: 20em;
padding: 2em;
background-color: white;
margin: 2em;
box-shadow: 0 0 5px #222;
}
.pie-center {
background: none;
border-radius: 50%;
transform: rotate(-90deg);
}
.circle1 {
fill: none;
stroke: teal;
stroke-width: 7;
stroke-dasharray: 30 70;
}
.circle2 {
fill: none;
stroke: orangered;
stroke-width: 7;
stroke-dasharray: 45 55;
animation: dash3 1s ease 0s 1 forwards;
stroke-dashoffset: -30;
}
.circle3 {
fill: none;
stroke: orchid;
stroke-width: 7;
stroke-dasharray: 20 80;
animation: dash2 1s ease 0s 1 forwards;
stroke-dashoffset: -75;
}
.circle4 {
fill: none;
stroke: yellowgreen;
stroke-width: 7;
stroke-dasharray: 5 95;
animation: dash 1s ease 0s 1 forwards;
stroke-dashoffset: -95;
}
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="container">
<div class="card new">
<svg class="pie-center" viewBox="0 0 32 32">
<circle class="circle1" r="15.915494309" cx="16" cy="16" >
<set attributeName='stroke' from='teal' to='red' begin='mouseover' end='mouseout' />
</circle>
<circle class="circle2" r="15.915494309" cx="16" cy="16" >
<set attributeName='stroke' from='orangered' to='red' begin='mouseover' end='mouseout' />
</circle>
<circle class="circle3" r="15.915494309" cx="16" cy="16" >
<set attributeName='stroke' from='orchid' to='red' begin='mouseover' end='mouseout' />
</circle>
<circle class="circle4" r="15.915494309" cx="16" cy="16" >
<set attributeName='stroke' from='yellowgreen' to='red' begin='mouseover' end='mouseout' />
</circle>
</svg>
</div>
</body>
</html>
Related
I am trying to create a scale with radial lines and numbers with range 0-100.
Here is my code:
<!DOCTYPE html>
<html>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<head>
<title>SVG Gauge</title>
</head>
<style>
#wrapper {
position: relative;
margin: auto;
}
#meter {
width: 100%;
height: 100%;
transform: rotateX(180deg);
}
.circle {
fill: none;
}
#mask {
stroke: #404040;
stroke-width: 60;
}
.blackie {
fill:none;
stroke: #000000;
stroke-width: 30;
}
.range {
stroke-width: 60;
}
.scale {
stroke: #cccccc;
}
#slider, #lbl {
position: absolute;
}
#slider {
cursor: pointer;
left: 0;
margin: auto;
right: 0;
top: 58%;
width: 94%;
}
#lbl {
background-color: #4B4C51;
border-radius: 2px;
color: white;
font-family: 'courier new';
font-size: 15pt;
font-weight: bold;
padding: 4px 4px 2px 4px;
right: -48px;
top: 57%;
}
#meter_needle {
height: 40%;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 10%;
transform-origin: bottom center;
transform: rotate(270deg);
}
</style>
<body>
<div id="wrapper">
<svg id="meter">
<g class="scale">
<defs>
<linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:rgb(102, 102, 255);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(204, 204, 255);stop-opacity:1" />
</linearGradient>
</defs>
<circle id="high" class="circle range" cx="50%" cy="50%" stroke="url(#grad)">
</circle>
<circle id="mask" class="circle" cx="50%" cy="50%">
</circle>
<circle id="low" class="blackie" cx="50%" cy="50%" r="360">
</circle>
<circle id="outline_ends" class="circle outline" cx="50%" cy="50%">
</circle>
</g>
</svg>
<img id="meter_needle" src="gauge-needle.svg" alt="">
<input id="slider" type="range" min="0" max="100" value="0" />
<label id="lbl" id="value" for="">0%</label>
</div>
<script>
var r = 400;
var circles = document.querySelectorAll('.circle');
var total_circles = circles.length;
for (var i = 0; i < total_circles; i++) {
circles[i].setAttribute('r', r);
}
var meter_dimension = (r * 2) + 100;
var wrapper = document.querySelector('#wrapper');
wrapper.style.width = meter_dimension + 'px';
wrapper.style.height = meter_dimension + 'px';
var cf = 2 * Math.PI * r;
var semi_cf = cf / 2;
var z = 40 * Math.PI;
document.querySelector('#outline_ends')
.setAttribute('stroke-dasharray', 2 + ',' + (semi_cf - 2));
document.querySelector('#high')
.setAttribute('stroke-dasharray', semi_cf + ',' + cf);
document.querySelector('#mask')
.setAttribute('stroke-dasharray', semi_cf + ',' + cf);
document.querySelector('#low')
.setAttribute('stroke-dasharray', semi_cf - z + ',' + cf);
var slider = document.querySelector('#slider');
var lbl = document.querySelector("#lbl");
var svg = document.querySelector('#meter');
var high = document.querySelector('#high');
var mask = document.querySelector('#mask');
var low = document.querySelector('#low');
var meter_needle = document.querySelector('#meter_needle');
function range_change_event() {
var percent = slider.value;
var meter_value = semi_cf - ((percent * semi_cf) / 100);
mask.setAttribute('stroke-dasharray', meter_value + ',' + cf);
meter_needle.style.transform = 'rotate(' + (270 + ((percent * 180) / 100)) + 'deg)';
lbl.textContent = percent + '%';
}
slider.addEventListener('input', range_change_event);
</script>
</body>
</html>
I have found on the web plenty of good examples with HTML canvas and D3js but nothing based on SVG..
I am thinking to create an element "line" and add it across the black arc.
What is the simplest way to create the numeric scale?
Here you go:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-250 -250 500 500" width="500" height="500" id="svg">
<defs>
<style>
line {
stroke: black;
stroke-width: 1px;
}
text {
fill: red;
text-anchor: middle;
font-size: 16px;
font-family: sans-serif;
}
rect {
fill: transparent;
}
#id {
display: none;
}
.origin {
fill: green;
}
.outer {
fill: none;
stroke: black;
}
</style>
</defs>
<circle r="5" cx="0" cy="0" class="origin"/>
<path d="M-180,0 a1,1 0 0,1 360,0" class="outer"/>
<g id="gauge" transform="rotate(-90)">
<g id="noon">
<rect x="-10" y="-220" width="20" height="100"/>
<line x1="0" y1="-190" x2="0" y2="-180"/>
<text x="0" y="-200"></text>
</g>
</g>
</svg>
<script>
for (i=0; i<=180; i = i + 18) {
var new_tick = noon.cloneNode(true);
new_tick.getElementsByTagName('text')[0].textContent = i/180 * 100;
new_tick.removeAttribute("id");
new_tick.setAttribute("transform", "rotate(" + i + " 0 0)");
gauge.appendChild(new_tick);
}
</script>
I think this is fairly self-explanatory. (For example the RECT is just a guide which you can turn on - by changing the fill - if you want to better visualize what's going in inside each G.)
Let me know if you have any follow on questions.
Here's a Codepen, if it helps: https://codepen.io/MSCAU/pen/OoQMdV
What is the simplest way to create the numeric scale?
The easiest way to animate the scaling of the svg circle is to animate its radius
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="400" height="400" viewBox="0 0 400 400" >
<circle cx="200" cy="200" r="10" fill="none" stroke-width="2" stroke="purple" >
<animate attributeName="r" values="1;100;1" dur="4s" repeatCount="indefinite" />
</circle>
</svg>
I am not aware of alternatives to adding width: 1em to the SVG in order to fix the IE11 issue (please see comment in the code). Play with the code in the codepen. Appreciate any help! Thanks :)
https://codepen.io/ambrwlsn90/pen/zjZYpb
<div class="box">
<span class="handle--draggable">
<svg class="handle--icon" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 10 32">
<circle cx="2" cy="2" r="2" />
<circle cx="8" cy="2" r="2" />
<circle cx="2" cy="9" r="2" />
<circle cx="8" cy="9" r="2" />
<circle cx="2" cy="16" r="2" />
<circle cx="8" cy="16" r="2" />
<circle cx="2" cy="23" r="2" />
<circle cx="8" cy="23" r="2" />
<circle cx="2" cy="30" r="2" />
<circle cx="8" cy="30" r="2" />
</svg>
</span>
</div>
.box {
position: relative;
width: 400px;
height: 100px;
border: 3px solid black;
background-color: white;
top: 50px;
left: 100px;
padding: 15px;
line-height: 1.5em;
}
.handle--draggable {
position: absolute;
cursor: move;
left: -26px;
top: -3.5px;
}
/**
* 1. Magic number added to fix visual bug in IE: 11
*/
.handle--icon {
fill: black;
background-color: grey;
padding: 3.5px;
height: 37px;
width: 1em; /* 1. */
position: relative;
&:hover {
left: -5px;
border-right: 5px solid grey;
}
}
The SVG tag needs some basic attributes in order to be rendered as expected. If you read the W3C documentation according the outermost svg tag you will find the answer:
For embedded ‘svg’ elements, the width of the rectangular region into which the ‘svg’ element is placed.
A negative value is an error (see Error processing). A value of zero disables rendering of the element.
If the attribute is not specified, the effect is as if a value of '100%' were specified.
So you will need to specify the width and height attributes of the SVG tag, or it will be rendered at 100% width.
The opening svg tag should look like this:
<svg class="handle--icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 32" width=“10” height=“32”>
Then the SVG will look the same crossbrowser.
Having the width and height attributes defined on your svg element you can discard the ugly Internet Explorer 11 hack.
This is my first time using SVG and I want to know if it is possible to create an animated line graph with an arrow. I have found multiple examples of animated line graphs without arrows, non-animated line graphs with arrows, and animated straight lines with arrows, but not exactly what I am looking for. I have attached some codepen examples I've been playing around with below. Does anyone know if this is possible/have a solution? It would be greatly appreciated!
Animated line missing arrow (needs arrow):
http://codepen.io/alexandraleigh/pen/jVaObd
# HTML
<div class="graph__wrapper">
<svg width="315px" height="107px" viewBox="0 0 315 107" version="1.1">
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<path d="M2.10546875,95.75 L40.5546875,68.3476562 L55.2109375,81.1796875 L65.2148437,76.3945312 L96.1835937,86.8320312 L131.023438,19.9414062 L142.15625,23.7226562 L183.605469,2.1953125 L211.007812,22.3320312 L234.320312,71.5664062 L234.667969,83.0039062 L244.019531,83.0039062 L247.105469,88.8320312 L312.695312,104.839844" id="Path-1" stroke="white" stroke-width="4" sketch:type="MSShapeGroup" class="path"></path>
</g>
</svg>
</div>
# CSS(Less)
#import "lesshat";
#darkgrey: #303030;
*{
box-sizing: border-box;
}
body{
background: #darkgrey;
}
.graph__wrapper{
width: 400px;
margin: 30px auto;
position: relative;
svg{
position: absolute;
margin: 36px 0px 0px 15px;
}
}
.path {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: dash 3s ease-in forwards;
animation-iteration-count: 1;
animation-delay: 1s;
}
#keyframes dash {
to {
stroke-dashoffset: 0;
}
}
.description{
font-family: "Roboto";
color:lighten(#darkgrey, 50%);
text-align: center;
margin: 40px 0px;
}
Animated straight line with arrow (needs to stop at multiple points on path):
http://codepen.io/alexandraleigh/pen/yVPYrY
I tried adding the path descriptions from #1 to #2 and it has the desired final graph, just no animations:
http://codepen.io/alexandraleigh/pen/pNdgWR
I also tried adding the arrow marker from #2 to #1, but the arrow doesn't animate:
http://codepen.io/alexandraleigh/pen/aBVdVY
I'm also open to using a plugin such as http://snapsvg.io/, but haven't seen any working examples that help my situation.
you can do this with offset-motion(old syntax: motion-path).
Be aware that this is a heighly experimental feature. it currently only works in Chrome. More to the point i use the "old" syntax here as that is what currently works in chrome, but it will soon switch to the new systax...
* {
box-sizing: border-box;
}
body {
background: #303030;
}
.graph__wrapper {
width: 400px;
margin: 30px auto;
position: relative;
svg {
position: absolute;
margin: 36px 0px 0px 15px;
}
}
.path {
stroke-dasharray: 428;
stroke-dashoffset: 428;
animation: dash 3s ease-in forwards;
animation-iteration-count: 1;
animation-delay: 1s;
}
#keyframes dash {
to {
stroke-dashoffset: 0;
}
}
#keyframes pm {
from {
motion-offset: 0%;
}
to {
motion-offset: 100%
}
}
#arrow {
animation: pm 3s ease-in forwards;
animation-iteration-count: 1;
animation-delay: 1s;
motion-path: path('M2.10546875,95.75 L40.5546875,68.3476562 L55.2109375,81.1796875 L65.2148437,76.3945312 L96.1835937,86.8320312 L131.023438,19.9414062 L142.15625,23.7226562 L183.605469,2.1953125 L211.007812,22.3320312 L234.320312,71.5664062 L234.667969,83.0039062 L244.019531,83.0039062 L247.105469,88.8320312 L312.695312,104.839844');
motion-rotation: auto;
motion-anchor: center;
}
.description {
font-family: "Roboto";
color: lighten(#darkgrey, 50%);
text-align: center;
margin: 40px 0px;
}
<div class="graph__wrapper">
<svg width="315px" height="107px" viewBox="0 0 315 107" version="1.1" style="overflow:visible">
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<path d="M2.10546875,95.75 L40.5546875,68.3476562 L55.2109375,81.1796875 L65.2148437,76.3945312 L96.1835937,86.8320312 L131.023438,19.9414062 L142.15625,23.7226562 L183.605469,2.1953125 L211.007812,22.3320312 L234.320312,71.5664062 L234.667969,83.0039062 L244.019531,83.0039062 L247.105469,88.8320312 L312.695312,104.839844"
id="Path-1" stroke="white" stroke-width="4" sketch:type="MSShapeGroup" class="path"></path>
<polyline id="arrow" points="0,-5 10,0 0,5 1,0" fill="white" />
</g>
</svg>
</div>
you can also do this with animateMotion, but svg animations are soon to be depricted. You will have to rewrite your code in any way sooner or later :-(
* {
box-sizing: border-box;
}
body {
background: #303030;
}
.graph__wrapper {
width: 400px;
margin: 30px auto;
position: relative;
svg {
position: absolute;
margin: 36px 0px 0px 15px;
}
}
.path {
stroke-dasharray: 428;
stroke-dashoffset: 428;
animation: dash 3s linear forwards;
animation-iteration-count: 1;
animation-delay: 1s;
}
#keyframes dash {
to {
stroke-dashoffset: 0;
}
}
.description {
font-family: "Roboto";
color: lighten(#darkgrey, 50%);
text-align: center;
margin: 40px 0px;
}
<div class="graph__wrapper">
<svg width="315px" height="107px" viewBox="0 0 315 107" version="1.1" style="overflow:visible">
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<path d="M2.10546875,95.75 L40.5546875,68.3476562 L55.2109375,81.1796875 L65.2148437,76.3945312 L96.1835937,86.8320312 L131.023438,19.9414062 L142.15625,23.7226562 L183.605469,2.1953125 L211.007812,22.3320312 L234.320312,71.5664062 L234.667969,83.0039062 L244.019531,83.0039062 L247.105469,88.8320312 L312.695312,104.839844"
id="Path-1" stroke="white" stroke-width="4" sketch:type="MSShapeGroup" class="path"></path>
<polyline id="arrow" points="0,-5 10,0 0,5 1,0" fill="white">
<animateMotion rotate="auto" begin="1s" dur="3s" repeatCount="1" fill="freeze">
<mpath xlink:href="#Path-1" />
</animateMotion>
</polyline>
</g>
</svg>
</div>
hi guys i need some help i need to create a tooltip with an image inside it however this is for an svg map so i cant use divs like in css and html.I have managed to create an image tooltip .However only one image can appear when i hover on all elements how can i make different images appear for different svg elements ? this is the code i have used for my tooltip:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="init(evt)" width="380" height="100">
<style>
.caption{
font-size: 14px;
font-family: Georgia, serif;
}
.tooltip{
font-size: 12px;
}
.tooltip_bg{
fill: white;
stroke: black;
stroke-width: 1;
opacity: 0.85;
}
</style>
<script type="text/ecmascript">
<![CDATA[
function init(evt)
{
if ( window.svgDocument == null )
{
svgDocument = evt.target.ownerDocument;
}
tooltip = svgDocument.getElementById('tooltip');
tooltip_bg = svgDocument.getElementById('tooltip_bg');
}
function ShowTooltip(evt, mouseovertext)
{
tooltip.setAttributeNS(null,"x",evt.clientX+11);
tooltip.setAttributeNS(null,"y",evt.clientY+27);
tooltip.setAttributeNS(null,"visibility","visible");
length = tooltip.getComputedTextLength();
tooltip_bg.setAttributeNS(null,"width",length+8);
tooltip_bg.setAttributeNS(null,"x",evt.clientX+8);
tooltip_bg.setAttributeNS(null,"y",evt.clientY+14);
tooltip_bg.setAttributeNS(null,"visibility","visibile");
}
function HideTooltip(evt)
{
tooltip.setAttributeNS(null,"visibility","hidden");
tooltip_bg.setAttributeNS(null,"visibility","hidden");
}
]]>
</script>
<text class="caption" x="10" y="35">Mouseover a square</text>
<text class="caption" x="10" y="50">to display a tooltip</text>
<rect id="rect1" x="160" y="10" width="60" height="60" fill="blue"
onmousemove="ShowTooltip(evt)"
onmouseout="HideTooltip(evt)"/>
<rect id="rect2" x="240" y="10" width="60" height="60" fill="green"
onmousemove="ShowTooltip(evt)"
onmouseout="HideTooltip(evt)"/>
<rect class="tooltip_bg" id="tooltip_bg"
x="0" y="0" rx="4" ry="4"
width="55" height="17" visibility="hidden"/>
<image xlink:href="Blooper-icon.png" class="tooltip" id="tooltip"x="0" y="0"height="50px"width="50px"visibility="hidden"/>
</svg>
in HTML
<div class="svgTooltip"></div>
<svg>
<path class="tempClass" .......>
</path>
</svg>
in CSS
.svgTooltip {
pointer-events: none;
position: absolute;
font-size: 15px;
text-align: center;
background: white;
padding-bottom: 5px;
padding-left: 5px;
padding-right: 5px;
z-index: 5;
height: 30px;
line-height: 30px;
margin: 0 auto;
color: #21669e;
border-radius: 5px;
box-shadow: 0 0 0 1px rgb(122, 92, 92);
display: none;
}
.svgTooltip::after {
content: "";
position: absolute;
left: 50%;
top: 100%;
width: 0;
height: 0;
margin-left: -10px;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid rgb(122, 92, 92);
}
.active {
display: block;
}
in JS
$(function() {
$tooltip = $(".svgTooltip");
$(".tempClass").hover(
function() {
$tooltip.addClass("active");
$tooltip.html($(this).attr("title"));
},
function() {
$tooltip.removeClass("active");
}
);
});
$(document).on("mousemove", function(e) {
$tooltip.css({
left: e.pageX - 30,
top: e.pageY - 70
});
});
I have a SVG hamburger menu icon that is animated when clicked. The goal is to transform it in to a "close" button when you activate the side-push menu. I need some help achieving that:
http://jsfiddle.net/a6ysa9zk/
HTML:
<div class="toggle-menu menu-right push-body">
<svg class="inline-svg" width="42px" height="42px" viewBox="0 0 42 42" enable-background="new 0 0 32 22.5" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.0.4 (8054) - http://www.bohemiancoding.com/sketch -->
<title>Group</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g class="svg-menu-toggle" sketch:type="MSLayerGroup">
<circle class="round" fill="#3B3B41" sketch:type="MSShapeGroup" cx="21" cy="21" r="21"></circle>
<rect class="bar" fill="#F2F2F2" sketch:type="MSShapeGroup" x="12" y="26" width="18" height="4"></rect>
<rect class="bar" fill="#F2F2F2" sketch:type="MSShapeGroup" x="12" y="19" width="18" height="4"></rect>
<rect class="bar" fill="#F2F2F2" sketch:type="MSShapeGroup" x="12" y="12" width="18" height="4"></rect>
</g>
</svg>
</div>
CSS:
.svg-menu-toggle {
fill: #fff;
pointer-events: all;
cursor: pointer;
}
.svg-menu-toggle .round {
transition: fill .4s ease-in-out;
}
.svg-menu-toggle .bar {
-webkit-transform: rotate(0) translateY(0) translateX(0);
transform: rotate(0) translateY(0) translateX(0);
opacity: 1;
-webkit-transform-origin: 20px 10px;
transform-origin: 20px 10px;
-webkit-transition: -webkit-transform 0.4s ease-in-out, opacity 0.2s ease-in-out, fill .4s ease-in-out;
transition: transform 0.4s ease-in-out, opacity 0.2s ease-in-out, fill .4s ease-in-out;
}
.svg-menu-toggle .bar:nth-of-type(1) {
-webkit-transform-origin: 20px 10px;
transform-origin: 20px 10px;
}
.svg-menu-toggle .bar:nth-of-type(3) {
-webkit-transform-origin: 20px 20px;
transform-origin: 20px 20px;
}
.svg-menu-toggle:active .bar:nth-of-type(1) {
-webkit-transform: rotate(-45deg) translateY(-10px) translateX(-8px);
transform: rotate(-45deg) translateY(-10px) translateX(-8px);
fill: #3B3B41;
}
.svg-menu-toggle:active .bar:nth-of-type(2) {
opacity: 0;
}
.svg-menu-toggle:active .bar:nth-of-type(3) {
-webkit-transform: rotate(45deg) translateY(6px) translateX(0px);
transform: rotate(45deg) translateY(6px) translateX(0px);
fill: #3B3B41;
}
.svg-menu-toggle:active .round {
fill: #F2F2F2;
}
Javascript for menu toggle:
jQuery(document).ready(function ($) {
$('.toggle-menu').jPushMenu();
});
Instead of using the :active pseudo-element, its easier to add a class to the group (.svg-menu-toggle).
Unfortunately it isn't possible to use toggleClass from jQuery.
// CSS
.svg-menu-toggle:active become .svg-menu-toggle.active
// JS
$('.toggle-menu').on('click', function(e) {
var $toggle = $(this).find('.svg-menu-toggle');
// toggleClass with addClass & removeClass
});