SVG <animate> not working when created dynamically using <use> - javascript

While I have found variations of this question I have not found a solution for my problem.
For the sake of brevity I have the following structure...
<svg>
<g>
<rect></rect>
<rect></rect>
<rect></rect>
</g>
</svg>
I can animate these rect elements by adding a use element beneath the rect elements within the group.
However, if I try to dynamically create a use element with animation rules to insert after the rect elements and inside the group, the animation does not take place.
When reviewing in Chrome Dev Tools, I can see that the dynamically created elements are there, but the animation is not taking place.
I have tested in FF and Chrome, and neither work.
I have read that this may be a Chrome bug, but most of the threads that I read were older, and am not sure if a solution has been found yet.
When I am creating my elements I am using createElementNS.
I have tried adding the FakeSmile library even though this seems to be IE specific.
I am only using JavaScript, no jQuery.
If I am not making myself clear, here is the desired result: http://codepen.io/JoeyCinAZ/pen/Hstkr
and here is the non-functioning example: http://codepen.io/JoeyCinAZ/pen/GHhbw

You are creating the <use> element with createElement when you need to use createElementNS to create the element in the SVG namespace.
Also you're trying to set the xlink attribute using setAttribute when you must use setAttributeNS to set it in the xlink namespace.

Related

Can not locate dynamic elements on the page [duplicate]

This question already has answers here:
Selenium WebDriver: clicking on elements within an SVG using XPath
(8 answers)
Closed 1 year ago.
On this page there is a chart.
Here I can only locate the chart boundaries element //div[#data-chart_id='product_cannabinoids'] however I'm not able to locate the rect, svg or g elements inside it.
I see all these elements in the F12 but nothing like //div[#data-chart_id='product_cannabinoids']//svg or //div[#data-chart_id='product_cannabinoids']//rect gives any much.
I guess it's some kind of JavaScript dynamic elements, but still, these are not pseudo elements. They are looking like regular elements!
So why this happens and how can we locate these elements with Selenium?
XPATH requires a different way of finding 'svg' and 'rect' elements,
using this syntax will work -
//*[local-name() = 'svg']
this is caused because 'svg' and 'rect' use different XML namespaces.
An alternative is using css selectors, css works normally with all type of elements.
From my understanding, SVG elements aren't the same as normal elements and can be a little tricky.
Check out this response:
Selenium WebDriver: clicking on elements within an SVG using XPath

Initializing Raphael with an svg element

I have already an SVG element on my HTML page. How can I initialize Raphael with it so that it wont create a new SVG, but use the one I provide.
Thanks
I don't think Raph will allow you to do this. I think you will need to give it a div or container that Raph will place the svg/vml place inside. I don't think you can give it an existing element to use (as svg).
I suspect this is because Raphael does not only create SVG, but possibly VML if its one of the very old browser versions. If you definitely need SVG and want to only use existing elements, you may want to look at Snap.svg, which is Raphaels younger sister (and shares a lot of the same codebase), or another like SVG.js.

Creating a d3 selection over an existing, detached SVG element

I have a component in JavaScript that will provide an <svg> element to its host. I want to populate the SVG element using d3.js.
If I let d3.js create the SVG element and add it to the <body>, then things work as expected:
var chart = d3.select('body').append('svg');
However I already have an SVG element. I want my code to more closely resemble:
var svg = document.createElement('svg'),
chart = d3.select(svg);
This latter approach populates the SVG element (as seen in the elements panel of Chrome's developer tools) but it does not render properly.
Am I going about this incorrectly?
I don't mind if d3 creates the SVG element, so long as it doesn't attach it to the DOM and I can access it.
EDIT I've created a jsFiddle that reproduces my problem. You can toggle the APPROACH variable between 1 and 2 to see alternate approaches. I see this issue in both Chrome and Firefox (latest versions on Ubuntu 13.04.)
EDIT 2 I've created a screenshot showing the working and non-working versions side by side:
You can see that the element trees are largely the same. However on the non-working version (left) the Styles panel (to the right of the element tree) is missing some user agent rules. I have no idea why this should be different. I'd suggest it was a bug in Chrome, but the same behaviour is visible in Firefox.
The problem is that you're creating the SVG element in the HTML namespace where it gets interpreted incorrectly. If you replace
var svg = document.createElement('svg');
with
var svg = document.createElementNS("http://www.w3.org/2000/svg", 'svg');
it works fine. D3 takes care of this for you by setting the namespace automatically.

update SVG dynamically

I have some objects inside of svg that can be clicked by user.
Is there any way to:
- send information about object (id) that was clicked by user to the 'main html document'?
- draw from outside document in the svg file.
Probably, my description is unclear,... I want to implement something like this:
user click on any object inside of svg-image;
main document will receive id of the clicked object and:
display some information about that object;
draw additional object inside of the svg-image.
Questions: how to communication from svg to document and from document to svg?
Thanks a lot, any thoughts are welcome!
P.S. Probably SVG is not the best way do that? What is better then?
EDIT: I saw recommendation regarding use of Raphael,.. but I would like to see 'native' options. (For now I'm analyzing Raphaels implementation to see that, but don't think it is doing exactly what I need).
See this example for how to get the DOM of a referenced svg from the parent document.
And here's an example of how you can call from an svg file to the parent document.
SVG is very well suited for doing what you describe.
I'd suggest using a library like Raphaël to support your SVG building. You can attach events to DOM objects that you can get through the node property of an image component.
Raphaël.js is indeed a good solution if you want to stick to SVG / VML. Now you can use canvas (new HTML 5 functionality) as well. Canvas is a new html tag (that can have id, events, ...) that allows you to draw free shapes a bit like SVG does. IE doesn't support canvas natively, of course, and you will need "excanvas.js" (this one or another, but this one works pretty well...) to make it IE compatible.
Only one restriction I know of regarding canvas: using background images makes IE be very slow. I would use Raphaël.js if it was something you'd consider doing.
Good luck
Nobody suggested, but accidentally I've found that svg is already supported by jQuery!
http://plugins.jquery.com/project/svg
Probably that is not the best approach, but I will try to work with svg using jquery. And actually, that seems like reasonable

Is it possible to use webkit css masks with SVG without an external file?

Webkit allows the use of an external SVG file as a mask for any HTML element. Ie:
<img src="kate.png" style="-webkit-mask-image: url(circle.svg)">
Resulting in:
(More information here: http://webkit.org/blog/181/css-masks/)
Does anyone know if there's a way to do it without an external SVG file? More specifically, can it be done with SVG generated from javascript?
Well, two years have passed since I asked this question and the browser landscape changed a lot. Here's an example of exactly what I wanted to do, which works only in Firefox for now: http://mozilla.seanmartell.com/persona/
As you can see there's a div with id chameleon which has the following style:
<div id="chameleon" style="clip-path:url(#clip1); -webkit-mask-box-image: url(mask.png);">
#clip1 points to a clipPath element inside an inline SVG element which links to a shape.
<clipPath id="clip1"><use xlink:href="#shape1"/></clipPath>
So now it's doable in Firefox.
Thanks #mart3ll for the practical example!
I'm not sure about the WebKit specific extension but Mozilla allow you to apply SVG effects like masks and filters on HTML elements. These can be defined in external files or directly in the markup. See this post. This isn't in any spec at the moment, but the SVG and CSS working groups are working together to spec this approach. See the Working Group's page (although only filters, not masks are mentioned explicitly there).
You can usually link to something in SVG by including the id of the element in the url value (e.g. url(#someID)). You could try generating the SVG via JS, giving it an id and inject it into the document and see if it works. There is no spec as it is a WebKit extension so it is hard to say without trying it out.
Yes I believe it's possible. Recently I used PHP to generate the SVG file.
Here is an example that I made:
http://jsfiddle.net/brokeneye/ygsKm/
Also check out http://raphaeljs.com/

Categories

Resources