I have an SVG image, parts of which I change dynamically depending on responses from an API call. One aspect I change is the colour of different elements within the SVG, which I can handle somewhat cleanly via applying different CSS classes. However there are also text elements that I would like to change.
I have this currently working by inlining the full SVG image into my component template and picking out the parts I wish to bind to the model. However, this means that any time I want to edit the raw SVG image I need to copy/paste the SVG markup back into the template and reapply these bindings.
Ideally what I would do is keep the SVG as an external file, then inline the SVG as part of the build process so I can avoid sandboxing (something I can currently do), but I also want to dynamically apply the data bindings via a selector (e.g. id/class associated with each SVG sub-element) after the SVG is inlined. Two solutions I've come up with would be to create a directive that would do some DOM manipulation to associate the relative elements with the values I want to set, or to modify the SVG tags in the build process post-inline to add the Angular binding syntax here. Neither option seems great to me.
Is there another way to do this that I'm missing?
Related
I have SVG icons of some elements. These elements are for example road signals on the level crossing. If a road signal is shining RED light, I change the appropriate SVG element's fill to red.
Now I have these elements in a menu, and I want each of them to have it's icon, but also that this icon represents its lamp state. So when the lamp state changes, the icon at the appropriate element also changes.
I did this before in Java (GWT) and I did it by loading the icon into a variable in a helper class (SvgHelper) and then anytime I wanted to display icon of particular element anywhere, I called svgHelper.getIcon(element) and it modified the svg, that it has stored in a variable, (in the background) and then returned me new cloned SVGImage that I could the put anywhere. So I only had one icon, changed its state, cloned it and returned.
Now when I want to do it in javascript, it seems, that to work with the SVG in any way, it has to be in the DOM first.
Is there a way to work with the SVG "in the background" so that it is not in the DOM? Because I would rather change multiple SVG properties and once finished then put the SVG in the DOM. Also I target the elements by ID and there can be multiple of those icons on a single page, so the IDs would collide.
I tried using svg.js and import my svg from string, but from what I understood the library actually requires some div to work in, so it adds it to the DOM.
In java I was doing it using this library and since it is in the end compiled to JS, there should be a way to do it.
Since even the GWT library adds the SVG to the DOM, I ended up doing just that. So I have some object which I have in a DOM somewhere outside of the screen, target the element by ID, change its properties. Onec the SVG is ready, I put it in its destination using vuejs's v-html directive.
I have been searching for months now about this subject, but I can't find anything about it. What I'm looking for: I have sheetmusic on my screen, which is xml converted to svg with javascript. Now I want to make buttons with which I can manipulate the SVG that's displayed on the screen. For example: the music has lyrics underneath the notes and chords above it. Let's say I want to replace or remove them with an onclick button. All this temporarily, only on the screen.
I am currently working on a similar project. You have 2 approaches:
Directly modify SVG (hmmm not cool if you have complex objects)
Find out which SVG element is to be modified, find the corresponding id
in the XML structure, modify the XML node, "recompile" XML to SVG.
As a more performant way, you may compile only the node that changed and
then insert it in the SVG.
In order to select the element you want to apply an action on, you can set
a 'click' event listener on each selectable element.
I have a web app that uses SVG files to map various sorts of data onto our underlying experimental dataset. Each SVG file represents a mapping of one type of data to the experimental dataset and, in most of the pages on the site, they are displayed one at a time, with the various nodes carrying tooltips to make the maps more informative and links to associated data.
I would like to add a page where maps can be compared side-by-side, which means having multiple self-contained SVG's all on the same page. When I do this, however, the files seem to step on each others' toes in that only the first SVG on the page displays the correct text in the labels and axes. The rest appear to inherit the alphabet used in the first image, leaving the axes and labels garbled and nonsensical.
The snippet below shows how I am currently embedding the SVG's in the page. The object blocks are loaded up with SVG content via javascript/ajax when the user chooses a map on a dropdown menu. Everything functions correctly except for the noted problem with the SVG text.
<object id="map" name="map" class="compBuild" width=800 height=460></object>
Javascript:
$(document).on("change", ".db_field", function(e) {
var tmp = this.name.split("_");
var field = "map_" + tmp[1];
$(document.getElementById(field)).load(getSvgUrl($(this).val()));
// getSvgUrl just makes a Jquery AJAX call to obtain the location of
// the SVG file.
})
Maybe not obvious from the code given, but what actually happens on the page is that the menus and object blocks are dynamically generated, so the actual drop-downs and object blocks are addressed as mapSelect_X map_X, where X is a number appended when the block is created. (code not shown for the sake of brevity!)
I am wondering if there is a workaround for this as I would rather not convert the SVG files to images, since I would lose the functionality in the SVG's. Any help would be appreciated. Thanks!
Check that there are no duplicate id attributes in the two SVGs. ids must be unique on the page, otherwise any SVG features that use id references (like <use>, gradients etc) can't be trusted to point to the right thing.
Since Chrome and FF handle duplicate ids differently, a quick way to check this is the cause would be to see if the two browsers render the two-svg page differently.
This is a bit of a long shot, but does anyone know of a tool that can export a png from an svg input AND retain the CSS styles applied to it. I have used canvg, but everything appears black in the output, as the styles are kept in css and not part of the svg document.
The solution is web based, and i'd like to perform the conversion client side using a javascript solution if possible.
Update:
I understand that you are using an external stylesheet for your SVG markup. So I think you need a three-step solution:
Make the stylesheet declarations that apply to the SVG markup inline. This is done best client-side. I do not have a solution in source code right now, but it should be possible to use W3C DOM Level 2 Style interface implementations to find out the selectors that apply to an element, and the declarations that have been used in the corresponding blocks (document.defaultView.getComputedStyle() alone will probably result in an SVG fragment having too many inline declarations).
Convert SVG markup with inline stylesheets to PNG. This is best done server-side (e. g., with ImageMagick), so you would need to send the SVG markup to the server.
Serve the PNG resource to the user.
Those two steps could be performed on form submission where in the onsubmit attribute you do step #1 and then call the form's submit() method.
#pluke, you've asked in the comments of the reply of #PointedEars for source code to turn external CSS styling into inline styles for your SVG. I've spent hours of searching for such a tool myself, and found none. However, I've discovered a quite specific solution that applies SVG generated with Rickshaw / D3: #thirdcreed has posted the JavaScript it at: Rickshaw CSS/Axes in JSDOM - just adapt those D3 specific selectors to your custom CSS / SVG elements as needed.
I have to add some interactive features to SVG directed graphs.
So far the graphs I want to show are generated from a dot file and rendered as SVG. I'd like to know if there is some easy way to add interactivity (Maybe with Javascript) to such SVG documents.
What I need is to display some information when the mouse goes over a node and to make it possible to compare two nodes.
Since my models are generated automatically I would prefer to keep the dot-generated SVG and put on it additional information with a separate Javascript.
I have an example with inline SVG. The difference between this SVG and what you have is that the one in my demo has id attributes for nodes and things. I did get this SVG from the graphviz website.
Demo
(Click on the "Hello" node)
When I get a chance to upload an SVG on my server, I will try accessing SVG from an embed element. I can't do it on JSFiddle do to same domain policy in browsers.
This page may also be of help. It shows some of the scripting capabilities of SVG, although for all of the examples, the script is in the SVG itself.