SVG image not show when set display none - javascript

I code a web app, in this have some images tag and I set it display to none. Like example code . My issue is when I run on some device image cannot load. When i set image show only blank display.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg>
<g id="gimg">
<image id="img" display="none" xlink:href="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" x="0" y="0" height="50px" width="50px"/>
</g>
<rect id="myrect" x="100" y="100" width="20" height="20"></rect>
</svg>
<script>
$("#myrect").on("click",function(){
$("#img").show();
});
</script>

If the problem is in phones try this:
$("#myrect").on("click",function(){
$("#img").show();
return false;
});

Can you add style=display: none to your image element
<image id="img" style="display:none" xlink:href="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" x="0" y="0" height="50px" width="50px"/>.
This should load the image

Have you tried this way?
<svg>
<defs>
<symbol id="my-icon" viewBox="0 0 30 30">
<rect id="myrect" x="25" y="25" width="20" height="20" />
</defs>
</symbol>
<image id="img" display="none" xlink:href="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" x="0" y="0" height="50px" width="50px" />
</svg>
$("#myrect").on("click", function() {
$("#img").show();
});
Just change the viewBox, etc to your requirements.
I hope this helps.

Related

Satisfying Chrome deprecation of # in url but breaking svg mask

svg {
width: 500px;
height: 500px;
}
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ev="http://www.w3.org/2001/xml-events" version="1.1"
viewBox="0 0 100 100"
>
<!-- MASK DEFINITION -->
<defs>
<mask id="mask" x="0" y="0" width="100" height="100">
<rect x="0" y="0" width="100" height="100" fill="#fff"/>
<rect class="rect"
x="10"
y="10"
width="20"
height="20"
>
</rect>
</mask>
</defs>
<!-- MASK DEF -->
<rect x="0" y="0" width="100" height="100" mask="url(%23mask)"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ev="http://www.w3.org/2001/xml-events" version="1.1"
viewBox="0 0 100 100"
>
<!-- MASK DEFINITION -->
<defs>
<mask id="mask" x="0" y="0" width="100" height="100">
<rect x="0" y="0" width="100" height="100" fill="#fff"/>
<rect class="rect"
x="10"
y="10"
width="20"
height="20"
>
</rect>
</mask>
</defs>
<!-- MASK DEF -->
<rect x="0" y="0" width="100" height="100" mask="url(#mask)"/>
</svg>
I have an svg with a mask. Another element uses the mask as such:
mask="url(#mask)"
While trying to satisfy this: Treat '#' as ending data URI body content
I changed my svg mask to "url(%23mask)", but that totally breaks the mask.
Does anyone know a solution to this issue? Is there a way to satisfy both chrome and the mask?
Code snippet below contains two identical svg's; the only difference is that one uses a # and the other uses %23 when defining their urls.

Can I add a mask to an svg-element without using an id?

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>

Include a png/svg inside a polygon?

I'm trying to think of the best way to include an image inside an SVG polygon element, like the below:
<svg id="graph" width="100%" height="400px">
<!-- pattern -->
<defs>
<pattern id="image" x="0%" y="0%" height="100%" width="100%"
viewBox="0 0 64 64">
<image x="0%" y="0%" width="64" height="64" xlink:href="https://cdn4.iconfinder.com/data/icons/imod/512/Software/labo.png"></image>
</pattern>
</defs>
<polygon stroke="red" stroke-width="2px" fill="url(#image)" points="300,150 225,280 75,280 0,150 75,20 225,20"></polygon>
</svg>
However, i also want to fill the polygon with a background colour fill, but as this is using the above pattern i'm not sure of the right approach.
Move your polygon into your defs, but take the fill out. Then make two copies with the use tag, the back one filled with your color and the front one filled with your image. You can also make multiple copies by including more images, changing the coordinates, etc.
<svg id="graph" width="100%" height="400px">
<!-- pattern -->
<defs>
<pattern id="image1" x="0%" y="0%" height="100%" width="100%" viewBox="0 0 64 64">
<image x="0%" y="0%" width="64" height="64" xlink:href="https://cdn4.iconfinder.com/data/icons/imod/512/Software/labo.png"></image>
</pattern>
<pattern id="image2" x="0%" y="0%" height="100%" width="100%" viewBox="0 0 64 64">
<image x="0%" y="0%" width="64" height="64" xlink:href="https://cdn4.iconfinder.com/data/icons/imod/512/Software/iPhoto.png"></image>
</pattern>
<polygon id="myShape" stroke="red" stroke-width="2px" points="300,150 225,280 75,280 0,150 75,20 225,20"></polygon>
</defs>
<use xlink:href="#myShape" fill="yellow"/>
<use xlink:href="#myShape" fill="url(#image1)"/>
<use xlink:href="#myShape" fill="orange" x="400"/>
<use xlink:href="#myShape" fill="url(#image2)" x="400"/>
</svg>

Changing SVG colors

I'm starting to learn JS and i have this (probably very easy) task that I'm having problems with.
So the main task is to make the lower green triangle change it's color depending on which color i click on upper object.
I made something like this:
<!DOCTYPE html>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>SVG, JavaScript</title>
<script type="text/javascript">
function changeColor("triangle"){
document.getElementById("group").getAttributeNS("fill");
evt.target.setAttributeNS("fill");
}
</script>
</head>
<body>
<svg height="500" width="500">
<g id="group">
<rect x="0" y="0" width="200" height="200" style="fill:gray;stroke:none;stroke-width:0"/>
<rect id="red_triangle" x="0" y="0" width="100" height="100" style="fill:red;stroke:none;stroke-width:0"/>
<rect id="yellow_triangle"x="100" y="0" width="100" height="100" style="fill:yellow;stroke:none;stroke-width:0"/>
<rect id="blue_triangle"x="0" y="100" width="100" height="100" style="fill:blue;stroke:none;stroke-width:0v"/>
<rect id="green_triangle"x="100" y="100" width="100" height="100" style="fill:lime;stroke:none;stroke-width:0"/>
<ellipse cx="100" cy="100" rx="100" ry="100" style="fill:gray;stroke:none;stroke-width:0"/>
<polygon id="triangle" points="100,225 150,300 50,300" style="fill:lime;stroke:none;stroke-width:0" onclick="changeColor("triangle")"/>
</g>
</svg>
</body>
</html>
but obviously it's not working. Could somebody help me with some suggestion?
// the string instead of argument name raises Error: unexpected string
function changeColor("triangle"){
// you get the attribute but don't do anything with it.
// and the group doesn't even have a fill attribute
document.getElementById("group").getAttributeNS("fill");
// here you try to set an attribute but setAttributeNS requires 3 arguments: namespace, attribute and value
// simpler setAttribute would be enough, but the value would still be overwriten by style="fill:whatever"
// and evt.target is undefined, there's no evt object
evt.target.setAttributeNS("fill");
}
then in your SVG:
// the quotes are broken,
// and here you pass a string which I'd assume to be the ID of an element you want to change
onclick="changeColor("triangle")"
So, all in all:
The onclick should be on the source rectangles, not the target triangle: <rect onclick="changeColor('triangle', this)" /> where 'triangle' is the ID of element you want to change, and this is a reference to the clicked rectangle.
SVG:
<svg height="500" width="500">
<g id="group">
<rect x="0" y="0" width="200" height="200" style="fill:gray;stroke:none;stroke-width:0"/>
<rect id="red_triangle" x="0" y="0" width="100" height="100" style="fill:red;stroke:none;stroke-width:0" onclick="changeColor('triangle', this)"/>
<rect id="yellow_triangle"x="100" y="0" width="100" height="100" style="fill:yellow;stroke:none;stroke-width:0" onclick="changeColor('triangle', this)"/>
<rect id="blue_triangle"x="0" y="100" width="100" height="100" style="fill:blue;stroke:none;stroke-width:0v" onclick="changeColor('triangle', this)"/>
<rect id="green_triangle"x="100" y="100" width="100" height="100" style="fill:lime;stroke:none;stroke-width:0" onclick="changeColor('triangle', this)"/>
<ellipse cx="100" cy="100" rx="100" ry="100" style="fill:gray;stroke:none;stroke-width:0"/>
<polygon id="triangle" points="100,225 150,300 50,300" style="fill:lime;stroke:none;stroke-width:0" />
</g>
</svg>
JS:
function changeColor( target, source ){
var color = source.style.fill;
document.getElementById( target ).style["fill"] = color;
}
Fiddle: http://jsfiddle.net/harg5kyz/1/

Can't change SVG rect properties in three containers

After several tries, and code changes, I am unable to make rectangle inside SVG to change his position - don't even ask for animating. Obviously using jQuery SVG plugin plus animation extension.
The problem: A SVGs wrapped inside three <div>, an inside y have a rectangle that need to be at y:0 after the document loads. And this is the code:
var rect = jQuery('div.post-image').children('svg').svg().svg('get');
jQuery(rect).each(function(){
jQuery(this).change('.b1', {y:0});
});
Well, nothing happens with the rectangle, it keeps the original coordinate. Chrome console doesn't says anything either.
Added: the HTML in question
<a href="#" class="post-image" title="title">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="250" height="140" viewBox="0,0,250,140" overflow="hidden">
<switch>
<g>
<defs>
<filter id="innershadow">
<feOffset dx="0" dy="0"></feOffset>
<feGaussianBlur stdDeviation="7" result="offset-blur"></feGaussianBlur>
<feComposite operator="out" in="SourceGraphic" in2="offset-blur" result="inverse"></feComposite>
<feFlood flood-color="#000" flood-opacity="0.3" result="color"></feFlood>
<feComposite operator="in" in="color" in2="inverse" result="shadow"></feComposite>
<feComposite operator="over" in="shadow" in2="SourceGraphic"></feComposite>
</filter>
<pattern xmlns="http://www.w3.org/2000/svg" id="image-771" patternUnits="userSpaceOnUse" width="250" height="202">
<image href="example-310x250.jpg" xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="250" height="202"></image>
</pattern>
<clipPath id="clip">
<polygon points="0,0 235,0 250,70 235,140 0,140 15,70"></polygon>
</clipPath>
</defs>
<polygon points="0,0 235,0 250,70 235,140 0,140 15,70" style="fill: url(#image-771); filter:url(#innershadow);"></polygon>
<rect class="b1" width="100%" height="100%" style="fill:rgb(0,92,148); opacity: 0.9;" clip-path="url(#clip)" x="0" y="98"></rect>
<rect class="b2" width="60" height="25" style="fill:rgb(0,92,148); opacity: 0.9;" clip-path="url(#clip)" x="190" y="0"></rect>
<rect class="b3" width="100" height="25" style="fill:rgb(0,0,0); opacity: 0.75;" clip-path="url(#clip)" x="0" y="0"></rect>
</g>
<foreignObject width="250" height="140">
<img width="250" height="125" src="example-fallback.jpg" alt="example" title="title"> </foreignObject>
</switch>
</svg>
</a>
I'm willing to use <canvas> for this, but I don't know what are the outcomes.
Found out what wast the problem:
var rect = jQuery('a.post-image').children('svg').find('.b2, .b3');
jQuery(rect).each(function(){
jQuery(this).attr('y','-25');
});
Done, and without a plugin. Okey, not the best way (find instead of most direct selector), but it will cut it.

Categories