I have a simple *.svg file with some javascript code inside.
There are 6 circles and they partially overlay each other.
When a mousover event occurs for one of the circle, this circle should appear at the top.
This works just fine. Here is my code:
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
width="400" height="300">
<script>
function mouseOver(evt) {
var parent = evt.target.parentNode;
parent.removeChild(evt.target);
parent.appendChild(evt.target);
}
function click(evt) {
alert("CLICKED");
}
</script>
<g id="myCircles" stroke="none" onclick="click(evt)" onmouseover="mouseOver(evt)">
<circle id="circ1" cx="150" cy="100" r="50" fill="red"/>
<circle id="circ2" cx="100" cy="60" r="30" fill="yellow"/>
<circle id="circ3" cx="200" cy="150" r="80" fill="blue"/>
<circle id="circ4" cx="160" cy="190" r="70" fill="green"/>
<circle id="circ5" cx="100" cy="220" r="10" fill="gray"/>
<circle id="circ6" cx="80" cy="90" r="20" fill="black"/>
</g>
</svg>
However if I use this mouseOver function the onclick event doesn't work anymore. I guess this has something to do with the removing and appinding of the Element inside the DOM structure.
If i uncomment the code in mouseOver(evt), the onclick event gets fired.
Anyone knows how to solve this?
EDIT: Interestingly, when I am using onmousedown instead of onclick event, everything works fine! Can anybody explain why?
You could use the z-index property to bring the selected circle to the top. If you use a .css file, add the z-index and set the initial value to the same value (say, '1')
z-index:1;
on the mouseover event, change the z-index to a higher value (say, '5') to pop it to the top of the circle stack. on the mouseout event, reset z-index to 1 and, finally, use the mousedown event to produce your alert, "Clicked."
Related
My html tree looks as follows:
<svg id="floating-button-svg" style={{fill: `${floatingButton.backgroundColor}`}}>
<use id="use-tag" href="
<svg>
<circle id="semi-circle" class="cls-1" cx="500" cy="500" r="50"/>
</svg>"
/>
</svg>
Afer compilation the href dissolves to data:image/svg+xml;base64,PCEtLSA8P3htbCB2ZXJzaW9uPSIxLjAiIGVuY29kaW5nPSJ1dGYtOCI/Pgo8c3ZnIHZlcnNpb249IjEuMCIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxMDAwIDUwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CjxjaXJjbGUgaWQ9InNlbWktY2lyY2xlIiBjeD0iNTAwIiBjeT0iNTAwIiByPSI1MDAiLz4KPC9zdmc+IC0tPgoKCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTAwMCIgaGVpZ2h0PSI1MDAiIHZpZXdCb3g9IjAgMCAxMDAwIDUwMCI+CiAgPGRlZnM+CiAgICA8c3R5bGU+CiAgICAgIC5jbHMtMSB7CiAgICAgICAgZmlsbDogIzAwMDsKICAgICAgfQogICAgPC9zdHlsZT4KICA8L2RlZnM+CiAgPGNpcmNsZSBpZD0ic2VtaS1jaXJjbGUiIGNsYXNzPSJjbHMtMSIgY3g9IjUwMCIgY3k9IjUwMCIgcj0iNTAiLz4KPC9zdmc+Cgo=#semi-circle
If anyone wants to test it, please replace the value in the href above with this link.
I am trying to change the radius of the circle through
document.getElementById('use-tag').setAttribute('r', '25')
but instead it only gives use an attribute of r=25. Is there any way I can change the radius of the circle? I have tried to fetch it using
getElementById
but it just gives me null (I'm assuming because it's wrapped in a shadow root).
edit: The gist of the problem here I believe is that I am trying to change the attributes of a closed shadow root which is impossible to achieve. So can someone please tell me why am I get a closed root instead of an open one? And how can I get an open one?
edit: Here is a demo of this situation: https://codesandbox.io/embed/smoosh-sun-nnevd?fontsize=14&hidenavigation=1&theme=dark
Since you have direct access to circle with id semi-circle, you can update it as the below snippet.
The snippet is running under a setTimeout to show the difference.
setTimeout(function() {
var circle = document.getElementById('semi-circle');
circle.setAttribute('r', 60)
}, 3000)
<svg id="floating-button-svg" height="100" width="100">
<circle id="semi-circle" class="cls-1" cx="50" cy="50" r="40" fill="red" />
</svg>
You can also do it in another way, check the snippet
setTimeout(function() {
var circle = document.getElementById('floating-button-svg');
circle.firstElementChild.setAttribute('r', 60)
}, 1500)
<svg id="floating-button-svg" height="400" width="400">
<circle id="semi-circle" class="cls-1" cx="80" cy="80" r="40" fill="red" />
</svg>
Here is pen
I want to apply drop shadow effect on rect, when rect is hidden using one of the following technique:
opacity:0 // or
fill:rgba(1,1,1,0) // or
fill-opacity:0 // or
display:none
when I trying to apply filter on such elements, shadow not appearing at all...
Is it possible to apply drop shadow on hidden Svg paths? How?
The simplest way is by using a mask.
In the demo below we have added a drop shadow to a circle. Then we construct the mask so that it hides the circle itself, but keeps the area outside the circle (ie the shadow). Revealing the red rectangle behind it.
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="shadow">
<feDropShadow dx="4" dy="8" stdDeviation="4"/>
</filter>
<mask id="invisible">
<rect width="100%" height="100%" fill="white"/>
<circle cx="50%" cy="50%" r="80" fill="black"/>
</mask>
</defs>
<rect x="40" y="60" width="150" height="80" fill="red"/>
<circle cx="50%" cy="50%" r="80"
style="fill:blue; filter:url(#shadow); mask: url(#invisible);"/>
</svg>
If you're just looking for a drop shadow with no rect, setting the fill to the background color will work:
.square{
fill:#fff;
width:100px;
height:100px;
filter:url('#drop-shadow');
}
If you've got multiple elements under the rect, you could try hiding just the filled in area with a clip-path or mask.
I have the following piece of code, that animates an SVG circle on click:
<circle id = "middle" cx="235" cy="235" r="100" stroke="yellow" stroke-width="0.5" fill="#ffcc00"> <animate begin="click" attributeName="fill" to="yellow" dur="1s"/>
It works fine when the user clicks inside the circle, but I would like to trigger the animation programmatically.
I tried $("#middle").click();, but the animation doesn't occur, even though the click event is issued. (I have also set $("#middle").click(function() {
audio.play();
}); and the sound is played all right).
Is there a way to animate the SVG by simulating the user click (on the SVG), without using an HTML button?
Call beginElement if you want to start an animation programatically.
<svg>
<circle id = "middle" cx="50" cy="50" r="25" stroke="yellow" stroke-width="0.5" fill="#ffcc00">
<animate id="a" begin="click" attributeName="fill" to="yellow" dur="1s"/>
</circle>
</svg>
<button onclick="document.getElementById('a').beginElement();">>Click Me!</button>
Good afternoon everyone,
I'm defining an SVG on my page with the following defs.
<svg width="0" height="0">
<defs>
<g id="stroke-hexagon">
<polygon fill="#002663" stroke="#FFFFFF" stroke-width="6" stroke-miterlimit="12" points="57.8,185 5.8,95 57.8,5 161.8,5 213.8,95 161.8,185 "/>
</g>
<g id="hexagon">
<polygon fill="#006890" points="52,180 0,90 52,0 156,0 208,90 156,180 "/>
</g>
</defs>
</svg>
...and implementing it later in the HTML using this:
<svg width="208px" height="180px" viewBox="0 0 208 180" >
<use xlink:href="#hexagon"></use>
<text class="faicon" x="50%" y="70px" fill="white" font-size="80px" text-anchor="middle"></text>
<text text-anchor="middle" x="50%" y="70%" fill="white">Logo Here</text>
</svg>
Works totally fine. I am also able to style the polygon's fill with simple CSS. Looks like this:
#hexagon:hover polygon {
fill:#990000;
}
The hover effect fails, however, whenever the mouse leaves the polygon and instead hovers over either of the 'text' elements within the svg. Is there a way to define a CSS rule that prevents this behavior. Or, would it be better (easier) to change the attribute using JS / jQuery?
Thanks!
Your texts are rendered on top of your polygon and are therefore intercepting mouse events. You should set up a css rule like
text {
pointer-events: none;
}
This will prevent the text from becoming a target of mouse events which should give you the desired hover effect for the polygon.
I have this SVG circle with an animation.
<circle cx="30" cy="50" r="15" fill="blue" stroke="black" stroke-width="1">
<animateMotion path="M 0 0 H 300 Z" dur="8s" repeatCount="indefinite" />
</circle>
It works fine. I want to make the exact same thing using javascript so if I click a button, it would create the same circle with the same animation.
here is my try:
var animateMotion = document.createElementNS("http://www.w3.org/2000/svg", "animateMotion");
animateMotion.setAttribute("dur","8s");
animateMotion.setAttribute("d", "M 0 0 H 300 Z");
animateMotion.setAttribute("repeatCount","indefinite");
//assuming that I already created my circle
myCircle.appendChild(animateMotion);
var animateMotion = document.createElementNS('http://www.w3.org/2000/svg','animateMotion');
animateMotion.setAttribute("dur","3s");
animateMotion.setAttribute("repeatCount","1");
var mpath = document.createElementNS('http://www.w3.org/2000/svg','mpath');
mpath.setAttributeNS("http://www.w3.org/1999/xlink", "href", "#YourPath");
animateMotion.appendChild(mpath);
Looks like animateMotion elements are bugged in Webkit, when dinamically created (see SVG elements will not Animate when added dynamically), and unsupported in IE. I think you're better off using pure javascript animation using a library like d3.
Maybe this is your problem:
In XML:
<animateMotion path= ... />
In JS:
animateMotion.setAttribute("d", ... ); //Should this be "path"?
Hope it helps,
regards m93a.
If just the click is important, it can be solved by using the begin attribute in your animateMotion:
<svg height="500" width="500" id="foo">
<circle cx="30" cy="50" r="15" fill="blue" stroke="black" stroke-width="1">
<animateMotion path="M 0 0 H 300 Z" dur="8s" repeatCount="indefinite" begin="foo.click"/>
</circle>
</svg>
Should work with a button as well, if the button has an identifier, e.g. id="startbutton", then it should be begin="startbutton.click
Another alternative with inline javascript can be found here: http://svg-whiz.com/svg/PausePlay.svg
cheers
if you want the animate as soon as <animateMotion> element append page,
set <animateMotion> 'begin' to 'indefinite' and begin the animate call its .beginElement();
var animateMotion = document.createElementNS(SVG_NS, 'animateMotion');
animateMotion.setAttribute('begin', 'indefinite');
//append animateMotion to the page
animateMotion.beginElement();
Here you can get number of examples regarding svg using javascript.
You can get help from there.