We've got a simply code, which works cross-browser:
<html>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="200" height="100">
<circle id="circ" cx="120" cy="40"
r="30" fill="green"/>
<rect id="rect" x="10" y="10"
width="60" height="60" fill="blue">
<set attributeName="fill-opacity" to="0.5"
begin="circ.mouseover" end="circ.mouseout"/>
</rect>
</svg>
When I try to use the elements in defs block I'm losing relation between two rectangles in Firefox browser.
<html>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="200" height="100">
<defs>
<circle id="circ" cx="120" cy="40"
r="30" fill="green"/>
<rect id="rect" x="10" y="10"
width="60" height="60" fill="blue">
<set attributeName="fill-opacity" to="0.5"
begin="circ.mouseover" end="circ.mouseout"/>
</rect>
</defs>
<use id="use_circ.rectangles" xlink:href="#circ" />
<use id="use_rect.rectangles" xlink:href="#rect" />
</svg>
I've read something about relation here http://www.petercollingridge.co.uk/data-visualisation/mouseover-effects-svgs? - actually this words
"Note that this effect does not work in Firefox Firefox 6 and earlier (I think), which is perhaps the biggest drawback of this method. "
I need to press the button to move(change) another element.
I also tried to make something like this, to set relation effect:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Button</title>
<script type="text/javascript" language="javascript">
function turn_right(button, miliSec)
{
document.getElementById("circ_left_position").setAttribute('visibility','hidden');
setTimeout(function() {
button.parentNode.setAttribute('xlink:href','#rect.right_position');
}, miliSec);
document.getElementById("circ_right_position").setAttribute('visibility','visible ');
}
function turn_left(button, miliSec)
{
document.getElementById("circ_right_position").setAttribute('visibility','hidden ');
setTimeout(function() {
button.parentNode.setAttribute('xlink:href','#rect.left_position');
}, miliSec);
document.getElementById("circ_left_position").setAttribute('visibility','visible ');
}
</script>
</head>
<body style="margin:0; border:0">
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="200" height="100">
<defs>
<g id="rect.left_position" onclick="turn_right(this,500)">
<rect x="10" y="10" width="60" height="60" fill="blue"/>
<circle id="circ_left_position" cx="120" cy="40" r="30" fill="green"/>
<animateTransform id="trigger1" begin="click"
attributeName="transform" type="rotate" additive="replace"
from="0 70 70" to="10 70 70" dur="0.5s" fill="freeze" />
</g>
<g id="rect.right_position" onclick="turn_left(this,500)">
<rect x="10" y="10" width="60" height="60" fill="blue" transform="rotate(10 70 70)"/>
<circle id="circ_right_position" cx="120" cy="40" r="30" fill="green"/>
<animateTransform id="trigger1" begin="click"
attributeName="transform" type="rotate" additive="replace"
from="0 70 70" to="-10 70 70" dur="0.5s" fill="freeze" />
</g>
</defs>
<use id="positions.rectangles" xlink:href="#rect.left_position" />
</svg>
</body>
In Chrome and FF we get different results. Farther, I don't understand difference in browsers. I'm sure, there exist a simple solution.
A use does not copy the animation this is not expected behavior in SVG 1.1 (this is not a firefox issue)
Smil in SVG 2 will address this.
What you can do is to use scripting to clone each animation and append them to the use tag. Perhaps on a onload event. However I believe this will not work for your specific code set because specify an id.
Related
I have two SVG tags in the first one I have wrapped the content (which means the code of the SVG image) in the symbol tag in order to make it invisible and it can be used in the tag. The use tag is working fine in the same SVG tag in which I have created the symbol tag. But when I am creating another SVG tag in the document and trying to use the tag it's not working (I think that might be due to the use of tag in another SVG tag I think So).
So Can anyone tell me is it possible to use the tag in another SVG tag (I think you are getting my point it will get more clear by the code)
Here is the code (I have commented over the issue)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<svg id="hero-svg" width="300" height="300" viewBox="0 50 630 630" fill="none" xmlns="http://www.w3.org/2000/svg">
<symbol id="theBee" viewBox="0 0 78 49">
<g id="complete_bee">
<path id="bee head" d="M11.553 35.5047C16.3904 38.8245 21.8681 37.8364 24.0023 36.4532V15.1115C22.9352 14.4397 19.5917 13.499 14.7542 15.1115C9.9168 16.724 8.37329 20.5655 7.99604 21.7512C6.88944 25.2291 6.71554 32.1848 11.553 35.5047Z" fill="#FFE818" stroke="black" />
<circle id="bee eye" cx="15.532" cy="21.6908" r="2.96412" fill="#313131" />
<path id="bee trunk" d="M65.8034 15.1697C45.3154 7.5816 30.1154 12.008 23.9501 15.1697V36.6299C37.3242 43.649 56.6739 38.0527 64.1435 34.3772C78.0156 27.5513 77.7785 19.6049 65.8034 15.1697Z" fill="#FFE818" stroke="black" />
<path id="trunk lines" d="M32.961 12.087C30.4711 16.1577 26.9142 26.5519 32.3682 39.3569L35.8065 39.8312C29.8309 27.5004 34.2652 15.5649 36.7551 11.4942L32.961 12.087Z" fill="#4E4E4E" stroke="black" />
<path id="trunk lines_2" d="M42.9204 39.8312C36.9447 27.5005 41.2605 15.0907 43.7503 11.02L47.7815 11.1385C45.2917 15.2092 40.5017 27.1448 46.4773 39.4755L42.9204 39.8312Z" fill="#313131" stroke="black" />
<path id="trunk lines_3" d="M53.947 38.0527C47.2667 27.313 51.8749 15.6325 54.6584 12.087L58.3339 12.7984C55.5504 16.3439 50.8236 26.246 57.504 36.9856L53.947 38.0527Z" fill="#313131" stroke="black" />
<path id="trunk lines_4" d="M63.7528 34.6143C56.6849 26.8661 61.298 16.5925 64.38 14.6955L67.5819 15.8811C65.3292 18.6081 61.4051 23.9435 66.3963 33.1916L63.7528 34.6143Z" fill="#313131" stroke="black" />
<path class="small-wing" d="M61.4166 1.06052C55.8203 0.206853 39.1659 8.60919 32.6053 12.0871C54.3264 11.3283 59.9938 9.00435 61.4166 8.05583C63.2303 6.8467 67.0128 1.91419 61.4166 1.06052Z" fill="#99CEFF" stroke="black" />
<path class="large-wing" d="M32.9609 11.9685C48.0977 7.26541 80.3166 -2.14073 74.6957 7.34446C68.7675 14.5769 44.3036 13.6679 32.9609 11.9685Z" fill="#81D1FE" stroke="black" />
<path id="bee sting" d="M70.4275 30.7017L73.273 27.7376L76 32.7173L70.4275 30.7017Z" fill="#313131" stroke="black" />
<path id="antenna" d="M13.1606 15.8811C13.4768 12.6008 12.1173 5.73197 4.14972 4.4989M10.3151 17.8967C9.36656 14.4583 6.09418 8.05584 0.592773 9.95288" stroke="black" />
<path id="bee legs" d="M30.3525 39.1198L26.2028 43.151L28.2184 46.2337M35.6879 39.9497L31.7753 44.5738L34.2652 48.605" stroke="black" />
<circle id="antenna ball" cx="4.38689" cy="4.38033" r="0.592824" fill="#FFE818" />
<circle id="antenna ball_2" cx="0.592824" cy="9.83431" r="0.592824" fill="#FFE818" />
<path id="bee behind legs" d="M49.2044 39.2384L45.6475 43.6253L47.6631 45.9965M55.4883 37.8156L50.8643 43.6253L55.4883 46.8265" stroke="black" />
</g>
</symbol>
<use xlink:href="#theBee" class="corr-p-3 bee" width="62.4" height="38.4" x="290" y="245" />
</svg>
<!-- But When I am using the use tag in blow svg tag its not working-->
<svg>
<use xlink:href="#theBee" class="corr-p-3 bee" width="62.4" height="38.4" x="350" y="245" />
</svg>
</body>
</html>
It is all about getting your viewBoxes and positioning right.
Your second bee is somewhere lost outside the canvas. You can hunt for it in F12
Give that second SVG a viewBox.. now defaults to.. the default I can never remember... but its certainly smaller than your 0 50 630 630
Proof use works and a too small viewBox 'cuts' off content:
<style>
svg{
position:absolute;
height:180px;
}
</style>
<svg viewBox="0 0 100 100">
<symbol id="theBee">
<circle cx="50" cy="50" r="20"/>
</symbol>
<use href="#theBee" fill="green"/>
</svg>
<svg viewBox="0 0 50 50">
<use href="#theBee" fill="red"/>
</svg>
viewBox, width and height
<style>
svg {
background: pink;
max-width:20vw;
}
</style>
<svg>
<ellipse cx="150" cy="75" rx="150" ry="75" fill="red" />
</svg>
<svg width="300" height="150">
<ellipse cx="150" cy="75" rx="150" ry="75" fill="red" />
</svg>
<svg viewBox="0 0 300 150">
<ellipse cx="150" cy="75" rx="150" ry="75" fill="red" />
</svg>
<svg viewBox="0 0 300 150" width="300" height="150">
<ellipse cx="150" cy="75" rx="150" ry="75" fill="red" />
</svg>
I need code to work just like on this page.
Play and pausing of an SVG. I went into inspect and pulled all the code I could, which seemed to be HTML. I could not see or find CSS or Javascript. Not sure if that is normal.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="80 0 1024 768" onload="t=setInterval(updateTimer, 100)">
<script>
var time = 0;
function updateTimer() {
//document.getElementById("t").textContent = document.documentElement.getCurrentTime().toFixed(0) + "s";
}
function pause() {
time = document.documentElement.getCurrentTime();
document.documentElement.pauseAnimations();
clearInterval(t);
}
function play() {
if(time > 0)
document.documentElement.setCurrentTime(time);
clearInterval(t);
t=setInterval(updateTimer, 100);
document.documentElement.unpauseAnimations();
}
function stop() {
time = 0;
clearInterval(t);
document.documentElement.setCurrentTime(0);
document.documentElement.pauseAnimations();
}
</script>
<linearGradient id="grad">
<stop stop-color="rgb(10%,80%,10%)" offset="0"/>
<stop stop-color="rgb(10%,40%,20%)" offset="0.4"/>
<stop stop-color="rgb(10%,90%,30%)" offset="0.7"/>
<stop stop-color="rgb(10%,50%,40%)" offset="1"/>
</linearGradient>
<rect fill="url(#grad)" width="0%" height="50" x="100" y="300" rx="5">
<animate attributeName="width" to="100%" begin="0s" dur="30s"/>
</rect>
<text id="t" style="font:24px Arial Black;fill:white;stroke:black" transform="translate(100 334)"/>
<animateTransform type="translate" attributeName="transform" xlink:href="#t" begin="1s" dur="29s" from="100 334" to="1024 334"/>
<g transform="translate(100 500)">
<!-- Play -->
<g onclick="play()">
<rect width="40" height="40" rx="10" stroke="black" fill-opacity="0.5"/>
<path id="play" d="M12 5l20 15l-20 15Z" fill="white" pointer-events="none"/>
</g>
<!-- Pause -->
<g transform="translate(50 0)">
<rect width="40" height="40" rx="10" stroke="black" fill-opacity="0.5" onclick="pause();"/>
<path id="pause" d="M14 10l0 20M26 10l0 20" stroke="white" fill="none" stroke-width="8" pointer-events="none"/>
</g>
<!-- Stop (rewind and pause) -->
<g transform="translate(100 0)">
<rect width="40" height="40" rx="10" stroke="black" fill-opacity="0.5" onclick="stop()"/>
<rect x="10" y="10" width="20" height="20" fill="white" pointer-events="none"/>
</g>
</g>
</svg>
When I attempt playback on Code pen, the SVG plays but buttons don't work. At all. I thought the "onclick" would do it...?
Is this because the JS isn't accessible/applied? I don't see any "DIV" or "DOM" so I assume its not a CSS thing...
I have a basic knowledge of HTML, less of CSS and know NOTHING about JavaScript
Short version: getCurrentTime & setCurrentTime must be called on the SVG node.
const mySvg = document.getElementById("mySvg")
function updateTimer() {
const t = `${mySvg.getCurrentTime().toFixed(0)}s`;
document.getElementById("t").textContent = t;
}
function setCurrentTime(t) {
mySvg.setCurrentTime(t)
}
function pause() {
mySvg.pauseAnimations()
}
function play() {
mySvg.unpauseAnimations()
}
function stop() {
clearInterval();
setCurrentTime(0);
mySvg.pauseAnimations()
updateTimer();
}
<svg id="mySvg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="80 0 1024 768" onload="t=setInterval(updateTimer, 100)">
<linearGradient id="grad">
<stop stop-color="rgb(10%,80%,10%)" offset="0"/>
<stop stop-color="rgb(10%,40%,20%)" offset="0.4"/>
<stop stop-color="rgb(10%,90%,30%)" offset="0.7"/>
<stop stop-color="rgb(10%,50%,40%)" offset="1"/>
</linearGradient>
<rect fill="url(#grad)" width="0%" height="50" x="100" y="300" rx="5">
<animate attributeName="width" to="100%" begin="0s" dur="30s"/>
</rect>
<text id="t" style="font:24px Arial Black;fill:white;stroke:black" transform="translate(100 334)"/>
<animateTransform type="translate" attributeName="transform" xlink:href="#t" begin="1s" dur="29s" from="100 334" to="1024 334"/>
<g transform="translate(100 500)">
<!-- Play -->
<g onclick="play()">
<rect width="40" height="40" rx="10" stroke="black" fill-opacity="0.5"/>
<path id="play" d="M12 5l20 15l-20 15Z" fill="white" pointer-events="none"/>
</g>
<!-- Pause -->
<g transform="translate(50 0)">
<rect width="40" height="40" rx="10" stroke="black" fill-opacity="0.5" onclick="pause();"/>
<path id="pause" d="M14 10l0 20M26 10l0 20" stroke="white" fill="none" stroke-width="8" pointer-events="none"/>
</g>
<!-- Stop (rewind and pause) -->
<g transform="translate(100 0)">
<rect width="40" height="40" rx="10" stroke="black" fill-opacity="0.5" onclick="stop()"/>
<rect x="10" y="10" width="20" height="20" fill="white" pointer-events="none"/>
</g>
</g>
</svg>
Long version: After all that, why wasn't it working in Codepen?
I can see that the link you posted is to an SVG document with it's own inline JavaScript (in the script tag).
The script calls some SVGElement methods on the SVG root element with document.documentElement.pauseAnimations();.
But what exactly is document element?
Document.documentElement returns the Element that is the root element of the document (for example, the element for HTML documents).
Because this code was called inside an SVG document, document.documentElement returns the SVG root node. However, because codepen is an HTML document, document.documentElement will return the HTML root node.
And you can't call methods like pauseAnimations() on an HTML root node because the HTML root node doesn't understand those methods.
So modern browsers can display SVG documents, HTML documents (and more) but here's the kicker: SVG documents can live inside of HTML documents.
You can see how document.documentElement could refer to two potential things depending on what type of document the JavaScript code was run from.
Is it possible to convert the following polygon svg to a rectangular shaped. The internal pattern should also be converted along too. Also since this is a cutout of a bigger pattern, I am using feMorphology filter to show where the clipPath and what shape the clipPath is in.
XML
<svg id="SvgjsSvg1008" width="550" height="650" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev/svgjs">
<defs id="SvgjsDefs1009">
<clipPath id="SvgjsClipPath1022">
<polygon id="SvgjsPolygon1015" points="131,55 131,218 90,280 5,235">
</polygon>
</clipPath>
<filter id="dilate_shape">
<feMorphology operator="dilate" in="SourceGraphic" radius="5" />
</filter>
</defs>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="550" height="650" viewBox="0 0 550 650" xml:space="preserve">
<g transform="matrix(1,0,0,1,0,0)" clip-path="url("#SvgjsClipPath1022")">
<g filter="url("#dilate_shape")">
<polygon points="131,55 131,218 90,280 5,235" fill="blue" fill-opacity="0.5" clip-path="url("#SvgjsClipPath1019")"></polygon>
</g>
<g transform="matrix(1,0,0,1,0,0)" clip-path="url("#SvgjsClipPath1022")">
<image xlink:href="https://www.dropbox.com/pri/get/3574%20%5BConverted%5D.svg?_subject_uid=360738345&raw=1&size=1280x960&size_mode=3&w=AADi5fkmMPJI2i6WvcO3faWWR_30_D8f5IdWsJhFarM2JA" x="-75" y="-75" width="150" height="150" transform="matrix(1,0,0,1,109,185)"></image>
</g>
</g>
</svg>
</svg>
I want to assign a svg-mask to a svg-image. I can make this work using an id on the mask like this:
<svg id="svg1" width="5cm" height="5cm" viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<mask id="mask">
<circle cx="100" cy="100" r="100" fill="white"></circle>
</mask>
</defs>
<rect x="0" y="0" width="200" height="200" fill="red" mask="url(#mask)"></rect>
</svg>
However I want to load this svg multiple times, with a different id in the svg-tag. Therefore I will generate duplicates of the '#mask'-id. Using multiple id's is invalid code. So I want to use a class to refer to the appropriate mask. That means I cannot use the mask=url()-technique.
<svg id="svg2" width="5cm" height="5cm" viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<mask class="mask">
<circle cx="100" cy="100" r="100" fill="white"></circle>
</mask>
</defs>
<rect x="0" y="0" width="200" height="200" fill="red" mask="url(can't use this)"></rect>
</svg>
Is there a way I can apply a mask to the rect element if the mask has a class instead of id? Maybe using javaScript or some other way I didn't think of.
The full story/context:
I am actually making an svg image slider-module for Joomla with php. This php generates a module containing javascript, css and an svg. I use the javascript to animate the mask.
I do actually have it working with unique id's. I was just wondering if there is a way to assign a mask to an element without referring to id's. I may want to do this because my code is getting a bit more confusing to read, because I have to use some php in my javascript/svg and css for each unique id.
No. You can only reference masks via an id. You cannot reference SVG masks any other way.
According to your description I understand you have a identical grafical entity you want to mask with different forms, multiple times. Write that down DRY:
<!-- start with an invisible svg that only contains mask definitions -->
<svg width="0" height="0"
xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- first, you have a circular mask -->
<mask id="circle-mask">
<circle cx="100" cy="100" r="80" fill="white" />
</mask>
<!-- then, you have a different mask, lets say a diamond -->
<mask id="diamond-mask">
<polygon points="100,20 180,100 100,180 20,100" fill="white" />
</mask>
</defs>
</svg>
<!-- further into your document, you want to mask a rectangle -->
<svg id="svg1" width="5cm" height="5cm" viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg">
<!-- reference the circle mask -->
<rect x="0" y="0" width="200" height="200" fill="red" mask="url(#circle-mask)" />
</svg>
<!-- with the circle again, as often as you want, nothing changes -->
<svg id="svg2" width="5cm" height="5cm" viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg">
<!-- the mask is the same, so no difference to above -->
<rect x="0" y="0" width="200" height="200" fill="red" mask="url(#circle-mask)" />
</svg>
<!-- and now with the diamond; that one is different -->
<svg id="svg3" width="5cm" height="5cm" viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg">
<!-- if the mask changes, you need to change the reference -->
<rect x="0" y="0" width="200" height="200" fill="red" mask="url(#diamond-mask)" />
</svg>
You could also reference the masks in a stylesheet and give your referencing elements a class according to the mask shape:
.masked.circular rect {
mask: url(#circle-mask);
}
.masked.diamond rect {
mask: url(#diamond-mask);
}
<svg width="0" height="0"
xmlns="http://www.w3.org/2000/svg">
<defs>
<mask id="circle-mask">
<circle cx="100" cy="100" r="80" fill="white" />
</mask>
<mask id="diamond-mask">
<polygon points="100,20 180,100 100,180 20,100" fill="white" />
</mask>
</defs>
</svg>
<svg id="svg1" class="masked circular" width="5cm" height="5cm" viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="200" height="200" fill="red" />
</svg>
<svg id="svg2" class="masked circular" width="5cm" height="5cm" viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="200" height="200" fill="red" />
</svg>
<svg id="svg1" class="masked diamond" width="5cm" height="5cm" viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="200" height="200" fill="red" />
</svg>
I'm trying to add some background image to SVG nodes "circle".
I have read a lot of stackoverflow answer and everybody is saying that we need to add a node into a to define our image.
I tried this but my image is not displaying at all.
Here is a fiddle of my code: https://jsfiddle.net/baapu6wz/ .
What did I miss ?
<svg baseProfile="full" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" height="390" width="1629">
<g transform="translate(40,0)">
<g>
<line y2="149.3060251652327" x2="819.8567597731511" y1="222.22245513917517" x1="854.7332277213098" style="stroke: #999;" stroke-width="5"></line>
<line y2="213.47136779636722" x2="768.9096407109324" y1="213.47136779636722" x1="768.9096407109324" style="stroke: #999;" stroke-width="5"></line>
<line y2="213.47136779636722" x2="768.9096407109324" y1="149.3060251652327" x1="819.8567597731511" style="stroke: #999;" stroke-width="5"></line>
</g>
<g>
<g transform="translate(854.7332277213098, 222.22245513917517)">
<circle fill="url(#image1);" fillOpacity="0.5" r="16"></circle>
<text x="20" dy="3">pagx</text>
</g>
<g transform="translate(768.9096407109324, 213.47136779636722)">
<circle fill="url(#image1);" fillOpacity="0.5" r="10"></circle>
<text x="20" dy="3">xzreds</text>
</g>
<g transform="translate(819.8567597731511, 149.3060251652327)">
<circle fill="url(#image1);" fillOpacity="0.5" r="14"></circle>
<text x="20" dy="3">jzkcwv</text>
</g>
</g>
</g>
<defs>
<pattern width="16" height="16" patternUnits="userSpaceOnUse" y="0" x="0" id="image1">
<image xlink:href="https://www.google.fr/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png" height="16" width="16" y="0" x="0"></image>
</pattern>
</defs>
You have a typo.
fill="url(#image1);"
should be
fill="url(#image1)"
Remove the semicolon.
https://jsfiddle.net/baapu6wz/1/