New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
problems rendering an SVG? #1866
Comments
@takluyver, since you're poking into the R magic machinery, perhaps you have some ideas? I'd also like to ping @stefanv, who also saw some SVG weirdness with the octave magic, in case this is similar. Unfortunately right now I'm busy finishing a report that's due so I can't look at this code quite right now. |
No immediate ideas, but I'll try to remember to look at it. |
I can reproduce the problem, but it's not the same one I had with the Octave backend. I can't see anything obvious causing it. |
It turns out that SVGs embedded the way IPython currently does all live inside the same DOM. This means that when any single SVG modifies styles, those changes are propagated to the rest. One solution is to encode SVGs the same way PNGs and JPEGs are, as base64 encoded data chunks, and add them to an I've followed this approach here, and it now renders correctly: https://github.com/stefanv/ipython/tree/svg_as_image_blob The above changes made me realize that there's special casing and duplicate code for png/jpeg, so we may want to look at cleaning that up as well eventually. |
Would that mean they're also saved in the ipynb file as base64 encoded data? It seems a bit ugly to turn XML into unreadable base64 strings, although I guess SVG from plotting isn't going to be very readable anyway. |
Yes, unfortunately. |
Let me see if I understand: with multiple SVG files in the document, when one changes some of its xml representation (say, its axis labels), the browser propagates these changes to the next SVG plot? |
@jonathan-taylor, yes apparently at least some style elements do persist that way. Unfortunately as I pointed out to @stefanv, I'm not sure encoding is a good idea: it seems to kill the scriptability support of SVG, and that would immediately rule out things like interactive d3.js figures. That sounds like throwing away the baby with the bathwater. We should try to find a solution to this that doesn't preclude things like interactive d3.js svg objects. @minrk, you know a lot about graphics stuff, any thoughts on this front? |
before i open a new issue, is the following related: i'm trying to display some svg and possibly missing something obvious. the command executes without error but nothing is displayed. from IPython.core.display import display_svg
display_svg(url='http://en.wikipedia.org/wiki/File:Correlation_examples2.svg') sys info:
|
I reached this page when investigating a plotting issue with the ipython notebook and rpy2: it turns out to be the same problem. Shouldn't SVG rendering the last possible rendering option by default, until the problem is resolved ? (that is iPython would try first to display PNG, JPEG, or other possible alternatives). |
This would be a shame to deactivate svg if they are resolution independent. we can try to wrap them in a IFrame. In the meantime you can locally monkey patch notebook from js console/custom.js:
Just set it to another value and new output will follow the new preference. |
Right now we have resolution-independent figures, only garbled as soon as there is more than one figure in a notebook. ;-) I'd trade those for PNGs with a reasonable resolution any day. |
@lgautier Yes, multiple figures in a notebook is such specialized use, isn't it :) |
I'm seeing the issue as well. The dev-version of igraph renders SVG and the second plot has messed-up labels. |
This annoys me so I have looked a bit into this issue. A simple test reproducing the problem is <html>
<head>
</head>
<body>
<!-- First inline SVG with inline style block -->
<svg width="10cm" height="5cm" viewBox="0 0 1000 500">
<defs>
<style><![CDATA[
rect {
fill: red;
stroke: blue;
stroke-width: 3
}
]]></style>
</defs>
<rect x="200" y="100" width="600" height="300"/>
</svg>
<!-- Second SVG -->
<svg width="10cm" height="5cm" viewBox="0 0 1000 500">
<rect x="200" y="100" width="600" height="300"/>
</svg>
</body>
</html> Both rectangles are red because the style of the first svg leaks into the second svg.
So what can we do about it ? I have explored the following solutions:
I think approach 6 is probably the more elegant one. The problem is that scoped is planned but not yet included into SVG2 specification (http://www.w3.org/TR/SVG2/styling.html#Scope). Also html scoped is I have successfully experimented the following approach:
Using this the above code would become: <html>
<head>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="jquery.scoped.js"></script>
</head>
<body>
<div>
<style scoped >
rect {
fill: red;
stroke: blue;
stroke-width: 3
}
</style>
<svg width="10cm" height="5cm" viewBox="0 0 1000 500">
<defs>
</defs>
<rect x="200" y="100" width="600" height="300"/>
</svg>
</div>
<svg width="10cm" height="5cm" viewBox="0 0 1000 500">
<rect x="200" y="100" width="600" height="300"/>
</svg>
<script>
$.scoped();
</script>
</body>
</html> which renders correctly. Another maybe more pragmatical solution would be to embed svg into an iframe or object for now, and use inline svg when browsers are ready. What do you think ? Thanks, Pablo |
When you write "not supported in major browsers", are you saying that that the scoped style fix won't help at the moment? |
See this table http://caniuse.com/style-scoped for the full details. In a nutshell, current versions of Chrome and IE do not support scoped style. But this jquery plugin https://github.com/thingsinjars/jQuery-Scoped-CSS-plugin plugin enables scoped style on current browser (while disabling itself on browsers with scoped support). |
The jQuery plugin then sounds like a viable approach to me. |
This is an expérimental feature that can be enabled in chrome://flags Envoyé de mon iPhone Le 19 sept. 2013 à 11:02, Stefan van der Walt notifications@github.com a écrit :
|
When multiple SVG figures are inlined in the same dom, they share the same css namespace. This patch, scopes each SVG's style CSS rules so they do not leak into other figures. Should help fixing ipython#1866
Actually, I realized #4236 does not fix the initial issue (rendering https://github.com/jonathan-taylor/ipython/tree/Rdevice). My reduced test case is too simple and possibly exhibits a different problem. Something else is going on with the original example, but I have no clue for the moment. EDIT: It seems the initial issue in https://github.com/jonathan-taylor/ipython/tree/Rdevice is not due to style leaks, but to The SVG spec allows to reuse elements defined inside a The <defs>
<rect id="MyRect" width="60" height="10"/>
</defs>
...
<use x="20" y="10" xlink:href="#MyRect" /> The problem in the Making the Nevertheless this is getting hairy, maybe wrapping the svg in an img/iframe/object is the best option for now ? |
The basic message here is that SVG is just like any other HTML - ids have to be global on the page. I consider it to be a bug in other's libraries if they are writing SVG like this. It would be the same if pandas was writing HTML tables that couldn't be on the page with other pandas HTML tables. I would tell them to 1) use classes instead of ids or 2) use ids that are always unique on a page. I am -1 on the iframe fix. |
I think the argument is that most of the time, SVGs are treated like images - they don't all exist on the same page, but are sourced from separate URLs, avoiding any conflict. it's a bit unusual that we inline SVGs rather than treating them individually as separate documents, which any normal webpage would do. |
Yes, @minrk is right: most of the time SVGs are treated as images so the programs producing SVGs do not need to produce unique ids. Even Inkscape may produce SVGs with colliding ids. This means that, right now, SVG support in IPython notebook is broken in most non-trivial usages. [*] I'm not sure it's upstream responsibility to guarantee a clean namespace (btw, non trivial problem, would you use UUID ?) but the application that inlines multiple contents. |
I agree that is the traditional model of SVG. But in the modern web, where the Notebook lives, SVG in understodd to be "just part of the DOM". Libraries such as d3 fully embrace this way of thinking about SVG. I know that IPython can't completely ignore the old way of think about SVGs, I am just not ready to throw all SVG in iframes, as it seriously retricts the more modern usages cases by sandboxing SVG away from the rest of the code on the page. |
I thought we were discussing using the 'scoped' option for styles along |
@ellisonbg: I agree, but to encourage the new Web SVG we should encourage adoption of SVG by providing solid support. We could by default inline SVGs and provide a compatibility mode for old SVGs. SVG(url="xxx", scoped=True). What do you think? |
Another option could be to parse the SVGs and replace IDs with some image |
+1 Sent from my iPhone
|
At first I though this was the way to go (see ~11 comments above :) ), but now I think it's a bad idea because:
|
Agreed that this is suboptimal to search and replace ids. I think this would be easier to "fix" once we have the plug-able mechanism for arbitrary mimetype. We should also try to think that as a language agnostic issue. |
I updated #4250 to disable SVG iframe wrapping by default. I agree with @Carreau that using a special mimetype for this would be nice, whenever support for that comes. In the meantime, the proposed patch adds a class descriptor to the svg named "ipython-scoped".
Could you please clarify this point? |
The notebook format as well as the message specs try to make as little assumption as possible from the fact that So knowing that usually you can send from the kernel (<- did not write python) either You can add more question to that like : |
Let discuss this in the lab meeting tomorrow... On Wed, Sep 25, 2013 at 9:06 AM, Matthias Bussonnier <
Brian E. Granger |
When multiple inline SVGs are included in a single document, they share the same parse tree. Therefore, style collisions and use id collisions can occur and upset the rendering. This patch wraps each SVG inside an individual iframe, ensuring that SVG's declarations do not collide. (The SVG representation is kept as XML and not converted to a binary format, so I do not think this approach precludes the use of d3.js) Tested on: * Chrome Version 29.0.1547.57 Debian 7.1 (217859) * Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130806 Firefox/17.0 Iceweasel/17.0.8 Closes ipython#1866
When multiple inline SVGs are included in a single document, they share the same parse tree. Therefore, style collisions and use id collisions can occur and upset the rendering. This patch wraps each SVG inside an individual iframe, ensuring that SVG's declarations do not collide. (The SVG representation is kept as XML and not converted to a binary format, so I do not think this approach precludes the use of d3.js) Tested on: * Chrome Version 29.0.1547.57 Debian 7.1 (217859) * Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130806 Firefox/17.0 Iceweasel/17.0.8 Closes ipython#1866
This biggest issue here is that the vanilla notebooks treated SVGs as images, such that the IDs used in their generation were not treated as unique. Therefore, when painted onto the DOM, since SVGs could have non-unique IDs, they would collide with each other. This isn't really seen in jupyterlab because of how it does rendering, but this issues was originally seen in ipython/ipython#1866. I fixed this by quickly parsing the SVG data and inserting the original hash of the data into the unique ids. Kind of a pain, but it fixes this problem
Work around ipython/ipython#1866 in Jupyter Notebook by prepending a unique slug to the id fields within the SVG. This also requires updating any filter, marker-start, and marker-end nodes which have a 'url(#id)' reference to refer to the beslugged version. If ever you see an issue where the SVG on the Model tab is fine but the rest are broken in some way, suspect a cross-SVG ID referencing issue. The Model tab is the first one rendered and will "win" any such conflict. JupyterLab renders SVGs within an iframe and is not impacted. Only Notebook (and Voila) really need to have the IDs uniquified. As it doesn't hurt JupyterLab to do this, we do so unconditionally.
In a local branch, I seem to have run into a possible rendering problem with the notebook. The branch is:
The last cell of docs/notebooks/examples/rmagic_extension.ipynb is mangled in my browser but when I extract the svg from the .ipynb file and view it with chrome it looks fine.
I used the following script to extract the svg data from the notebook:
The text was updated successfully, but these errors were encountered: