SVG clipPath not working in Firefox when defined dynamically - javascript

I have the following code:
<div class="blah" style="clip-path: url(#clippath)"></div>
<svg width="0" height="0"><defs><clipPath id="clippath">
<rect x="0" y="0" height="100" width="100"></rect>
</clipPath></defs></svg>
This correctly clips the blah div to 100x100 square. However, if I use JavaScript to add the svg to the DOM (rather than it being there from page load), it no longer works. Specifically, I'd like to create a dynamic clip path based on events happening in my app.
What am I doing wrong? This only needs to work in Firefox (which unfortunately doesn't support clip-path: polygon(...))

Make sure you are you using the namespace variant of createElement.
document.createElementNS("http://www.w3.org/2000/svg", "clipPath");
If you are just using createElement() then the element will be going into the default namespace (ie HTML) and won't be recognised by the SVG renderer.

Related

SVG fill="url(#foo)" disappears when SVGs are loaded dynamically

I am loading different SVGs dynamically within a web application built in AngularJS, I am also altering the opacity of layers within the SVGs. These SVGs have some paths with the fill pattern property as such
<defs>
<pattern id="glass-floral" patternUnits="userSpaceOnUse" width="184" height="272">
<image xlink:href="../img/glass-floral.png" x="0" y="0" width="184" height="272"/>
</pattern>
</defs>
<rect x="98.3" y="85.5" fill="url(#glass-floral)" width="365" height="318.8"/>
This all works great at first- however under some conditions these # fills simply disappear:
-
Condition 1:
If I were to switch to another SVG and back.
Result::
The # fill is still visible.
-
Condition 2:
If I were to alter the opacity of the element with the # fill.
Result::
The # fill is still visible.
-
Condition 3:
If I were to both switch to another SVG & alter the opacity of the element with the # fill.
Result::
The # fill becomes invisible.
-
This is to mean the styles all appear to still be applied normally in the code- but there is no actual visible fill to be seen. This behaviour exists as far as I can see in Chrome and slightly differently in Safari. Firefox seems to be immune.
I've tried manually flicking the element to another fill and back in the browser to see if perhaps something had cached, no luck. I still think this may somehow be the case, with how the # refers to an inline pattern defined in the <defs> which may not have been loaded yet by the AJAX but the cached CSS rule still floating around.
If it helps matters, both SVGs that I am switching between both have the same <defs> and CSS styling applied. Is perhaps the double case of the defined pattern causing an issue?
After some investigation this appears to be an issue with the browsers (Chrome/Safari possibly others) not being able to keep up with rendering fill: url(#) and opacity for the same element at the same time, at least in cases of multiple/dynamically loaded SVGs.
To solve this, apply your opacity css to a containing element around the element that has the fill: url(#), example below:
<defs>
<pattern id="glass-floral" patternUnits="userSpaceOnUse" width="184" height="272">
<image xlink:href="../img/glass-floral.png" x="0" y="0" width="184" height="272"/>
</pattern>
</defs>
<style>.opacity-class { opacity: 0.33; }</style>
<g class="opacity-class">
<rect x="98.3" y="85.5" fill="url(#glass-floral)" width="365" height="318.8"/>
</g>
This allows the browser to do both independently and not ruin your pretty pictures.
I had multiple svg elements and problem was the same ID of all pattern tags. So, using different id="" for the pattern tag of each svg element solved my problem with disappearing fill="url()" on dynamic reload...

D3 Multiple Visualizations Per Page Namespace IRI Conflicts [duplicate]

I've enbedded d3's force directed graph layout into extjs tabs so that each time a new tab gets added a new graph svg gets generated.
No Problemo so far.
Now I intended to turn the graph into a directed one (by adding a marker and tell the lines to use it)
Each generated svg elements is following this pattern:
<svg width="100%" height="100%">
<defs><marker id="end-arrow" viewBox="0 -5 10 10" refX="6" markerWidth="3" markerHeight="3" orient="auto"><path d="M0,-5L10,0L0,5" fill="#ccc"></path></marker>
</defs>
<g transform="translate(4,0) scale(1)"><line class="link" sig="30.84" style="stroke-width: 3;" x1="538" y1="347" x2="409" y2="467" marker-end="url(#end-arrow)"></line>
...
</g>
</svg>
With Crome everything works just fine.
So I arrived at the concusion that the structur and
the way I generate the svgs should be more or less correct.
But with Firefox the Markers will only show for the first svg. (the first tab)
All other svgs won't show any Arrowheads.
"Inspect Elements" tells me the Markers are there and that the lines are refering to them.
And this is where I'm running out of Ideas where or what to look for. :(
You have multiple non-distinct IDs within the same html or svg document. This is invalid, different UAs respond differently but as you're not allowed to do this, it doesn't really matter that they are inconsistent.

Javascript and SVG

I am trying to dynamically create SVG vectors with Javascript and I'm running into some problems.
I create the svg markup in javascript with document.createElement and append it to a div container. Then I do the same thing and create a rect and add it as a child to the svg id.
When I look at the DOM, I can see the elements being added, and their properties are such:
<svg id="gdc_container" xmlns="http://www.w3.org/2000/svg" version="1.1" width="500" height="300">
<rect id="gdc_background" width="500" height="300" style="rgb(0,0,255)"></rect>
</svg>
Everything looks fine, however the graphics are not showing up. When I use Chromes inspector, I can see the svg and rect elements, but the chrome tooltip shows their size as [ 0 x 0 ].
Anyone have any ideas?
Did you try using createElementNS? (developer.mozilla.org/en/DOM/document.createElementNS)
For some examples look at http://www.kevlindev.com/tutorials/basics/shapes/js_dom/index.htm.

Trying to create a re-usable text-box (text with a square background-colour) in SVG 1.1?

I'm trying to create (what I thought would be!) a simple re-usable bit of SVG to show three lines of text, with a background colour - to simulate a 'post-it' note.
I have found some useful code here to get the Bounds of the Text http://my.opera.com/MacDev_ed/blog/2009/01/21/getting-boundingbox-of-svg-elements which I am using.
So: I'm creating an group of text elements like this in the 'defs' section of my SVG:
<svg id="canvas" width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="post_it">
<text x="0" y="30" id="heading" class="heading">My Heading</text>
<text x="0" y="45" id="description" class="description">This will contain the description</text>
<text x="0" y="60" id="company" class="company">Very Big Company Ltd.</text>
</g>
And I'm displaying the text with a 'use' element like this:
<use id="12345" class="postit" xlink:href="#post_it" onclick="showId(this);"/>
I'm using the onclick to trigger a call to the following javascript function (defined in 'defs' section):
function showId(elem) {
post_it_rect=getBBoxAsRectElement(elem);
document.getElementById('canvas').appendChild(post_it_rect);
}
(The 'getBBoxAsRectElement(elem)' is from the link I posted).
As this stands; this works just fine - however if I change my 'use' element to position the text in a different place like this:
<use x="100" y="100" id="12345" class="postit" xlink:href="#post_it" onclick="showId(this);"/>
Now, the text displays in the correct place, but the resultant 'background-color' (actually a 'rect' element with opacity of 0.5) still shows on the top-left of the svg canvass - and the function used to calculate the rect is returning '-2' rather than '100' ('-98'?) as I need (I think).
What do I need to do to line up the 'rect' elements and the text elements ?
The author of the (very helpful article btw) script provides a more advanced script to draw a box round any 'bb' in an SVG, but I couldn't get this to work (missing 'transform' functions?).
I'm using Firefox 7.x to render the SVG ; and I'm loading a .svg file (ie, not embedded in html etc) straight from disk to test this).
Yes, you may need to compensate yourself for the x and y attributes on the <use> element for the time being, I'll try to find some time to update the blogpost and script.
Here's a draft SVG 1.1 test that among other things checks that the effect of the x and y attributes are included in the bbox. The line starting [myUse] is the one that tests this case, if it's red then that subtest failed. Chromium and Opera Next both pass that subtest, while Firefox nightly and IE9 doesn't. Note that the test itself has not gone through full review yet, and that it may still change.

SVG elements are not shown in a browser

I have faced to a quite strange situation. I have a script which draws some lines using jQuery SVG plugin. It is working in a separate html file. But once I copy that script and insert into another html file it stops showing SVG elements in a browser. It works perfectly, because when I see the source code of the page after running a script I could see that the script is adding SVG elements to the page. Here is SVG code of the page in any case:
<svg version="1.1">
<line x1="492" y1="503" x2="717" y2="576" stroke="#4A4A4A" stroke-width="2"></line>
<line x1="500" y1="400" x2="600" y2="400" stroke="#4A4A4A" stroke-width="2"></line>
<line x1="604.5" y1="539.5" x2="587.5" y2="542.5" stroke="red" stroke-width="2"></line>
<line x1="604.5" y1="539.5" x2="592.5" y2="527.5" stroke="red" stroke-width="2"></line>
</svg>
What could be the problem the those SVG elements are not shown in the browser? Have anybody else faced such a strange situation?
You forgot to add the SVG namespace tag to your page?
Try adding a viewBox attribute to the svg element to ensure that the coordinate system makes the lines appear within the svg viewport. Or make sure that in both documents size of the svg element is the same. My guess is that in one document the svg is quite wide, and in the other it's not as wide (thus clipping away the lines).
The problem is solved. I didn't notice that in the new page where SVG elements were not shown, the DIV element where I was drawing SVG elements had been wrapped by another DIV. And in the CSS file the wrapper DIV had an attribute display: table;. I removed that attribute and now SVG elements are shown. Thanks guys for you help and suggestions.

Categories