Replace color in Svg files with Javascript - javascript

I have a lot of Svgs files, and I want to replace one specific color by an other.
I've not path id and set ids in over 600 files is too long.
All the files have the same colors as the two in the example. I would like to select all elements with the color #EB1A21 and replace them with a variable containing another color. My svgs files are embed in object html tags.
I don't want save results in external files because the new colors are set in an input type=text by users, so I can't save all new coloured Svg file. I want them to be "dynamically" changed
The format of my file is like this
<svg>
<g>
<path style="fill:#EB1A21;" d="....."/>
<path style="fill:#292B87;" d="....."/>
<path style="fill:#EB1A21;" d="....."/>
</g>
</svg>
and I want to show files like this :
<svg>
<g>
<path style="fill:#color1;" d="....."/>
<path style="fill:#color2;" d="....."/>`
<path style="fill:#color1;" d="....."/>
</g>
</svg>
Ps: sorry for my language i'm a french guy :)
Thanks in advance..
----SOLUTION----
<script type="text/javascript">
for (i in mySvgFiles){
var curImage = escape(mySvgFiles[i]);
$("#contents").append('<object data="file.svg" type="image/svg+xml" onload="selectObj(this);"><object/ >');
}
function selectObj(my_object){
var colorChoice1 = "#FF0000"
var colorChoice2 = "#00FF00"
var svgDoc = my_object.contentDocument;
var svgRootemp = svgDoc.documentElement;
colorize(svgRootemp, colorChoice1, colorChoice2);
}
function colorize(svgRoot, color1, color2){
$("[style='fill:#292B87;']",svgRoot).css("fill", color1);
$("[style='fill:#EB1A21;']",svgRoot).css("fill", color2);
}
</script>
<div id="contents"></div>
If you have questions about this ask me :)

var color1 = "#00FF00";
var color2 = "#FF0000";
$(document).ready(function () {
$("path").each(function () {
var color = $(this).css("fill");
if (color == "rgb(235, 26, 33)") {
$(this).css("fill", color1);
} else if (color == "rgb(41, 43, 135)") {
$(this).css("fill", color2);
}
});
});

Related

Retrieve a computed svg color with javascript

I've got a CSS variable that dynamically sets the background color of an SVG element with a CSS variable.
Now I wanted to write a unit test that checks if the color is set properly on the object. Unfortunately, I can't seem to retrieve this value with javascript.
I've created a jsfiddle with my current unsuccessful progress: https://jsfiddle.net/Lmfjdc4e. Upon pressing the checkColor button the wrong fill and background-color attribute is written into the console.
Can I even retrieve the correct computed color of a svg element? If yes how?
Here is the complete source of the jsfiddle:
function checkColor() {
var circle = document.getElementById('circle');
var style = window.getComputedStyle(circle);
var fill = style.getPropertyValue('fill');
var bgColor = style.getPropertyValue('background-color');
console.log(fill) //url(#myGradient)
console.log(bgColor) //rgba(0, 0, 0, 0)
}
.myClass {
--background-color: rgb(255, 0, 0)
}
<svg xmlns="http://www.w3.org/2000/svg" class="myClass" viewBox="0 0 300 200" height="150">
<defs>
<linearGradient id="myGradient">
<stop offset="0" stop-color="var(--background-color)" />
</linearGradient>
</defs>
<circle id="circle" cx="50" cy="165" r="35" fill="url(#myGradient)"/>
</svg>
<button onClick="checkColor()">checkColor</button>
You need to get the exact property you are setting. In this case, it will be the following:
var bgColor = style.getPropertyValue('--background-color');
The dashes affect the name of the property.
Edit:
See the following jsfiddle:
https://jsfiddle.net/x90fcLd8/11/
Evaluating the url on the fly for the fill seems to be the only way to get the correct color.

add SVGs inside an SVG programmatically

I need to add SVG objects to specific locations inside an SVG object that's appended to the DOM.
But whenever I do that I see nothing rendered on the screen. I can see the SVG objects are added (in Elements tab of DevTools) but they're not rendered. They're pure SVG (not wrapped around an HTML element like a DIV).
I've tried loading SVGs with ajax and adding them, tried to do with Snap, tried to have these elements inside a <defs> tag, find them with Snap and then add them to the main Snap object. Nothing seems to work. The objects are always added but not rendered.
Is that even possible?
The SVG
<svg width="400" height="300" style="background: gray">
<defs>
<circle id="redc" cx="50" cy="50" r="50" style="fill: red" />
<circle id="yelc" cx="40" cy="40" r="40" style="fill: yellow" />
</defs>
<circle id="bluc" cx="200" cy="200" r="50" style="fill: blue" />
</svg>
JavaScript
const s = Snap("#root");
Snap.load('images/all.svg', function(data){
var all = data;
// append the all.svg node. cool
s.append( all.node );
// get the red circle definition
var redc = all.select('#redc');
s.append(redc.node); // doesn't work
});
with foreign object:
Snap.load('images/all.svg', function(data){
var all = data;
// append the all.svg node. cool
s.append( all.node );
// get the red circle definition
var redc = all.select('#redc');
// foreign object
var foreign = document.createElementNS('http://www.w3.org/2000/svg',"foreignObject");
foreign.setAttribute('width', 500);
foreign.setAttribute('height', 150);
foreign.appendChild(redc);
// add the foreign object - doesn't work
s.append( foreign );
});
It doesn't work because you're appending the circle outside of the <svg> tree i.e. directly under #root which is probably some kind of HTML element such as a <div>
The foreignObject problem is basically the same. Not sure why you're trying to add a circle as a child of a foreignObject (that won't work as you'd need an svg element to be its parent). I've used an html element instead.
const s = Snap("#root");
var svg = '<svg width="400" height="300" style="background: gray"><defs><circle id="redc" cx="50" cy="50" r="50" style="fill: red" /><circle id="yelc" cx="40" cy="40" r="40" style="fill: yellow" /></defs><circle id="bluc" cx="200" cy="200" r="50" style="fill: blue" /></svg>';
var all = Snap.parse(svg);
// append the all.svg node. cool
s.append( all.node );
// get the red circle definition
var redc = all.select('#redc');
all.node.append(redc.node); // append as a child of the svg node
// foreign object
var foreign = document.createElementNS('http://www.w3.org/2000/svg',"foreignObject");
foreign.setAttribute('width', 500);
foreign.setAttribute('height', 150);
foreign.setAttribute('fill', 'pink');
var p = document.createElement('p');
foreign.appendChild(p);
var text = document.createTextNode("Hello World");
p.appendChild(text);
// add the foreign object to the correct part of the tree
all.node.append( foreign );
<script src="http://snapsvg.io/assets/js/snap.svg-min.js"></script>
<div id="root"></div>

Change fill color inside svg using JQuery [duplicate]

This question already has answers here:
How to change color of SVG image using CSS (jQuery SVG image replacement)?
(18 answers)
Closed 6 years ago.
I have an SVG image that is embedded inside 'img src' tag. The svg contains different paths with a color, each separated by id. I want to change the fill color inside each id using jquery
Below are the codes i've used. But the color is not changing. By searching a lot, i found that if svg is added directly to the html, it will work. A working example: http://jsfiddle.net/P6t2B/
But how can I achieve it if it is done via 'img src' to add svg??
Inside html:
<img src="images/hands.svg" width="70px"/>
JQuery code change fill color id 'l1':
$('#l1').css({fill:"#000000"});
Sample SVG:
<path id="l1" fill="#ffffff" d="M85.6,227.3L85.6,227.3c14.2-5.7,21.1-22,15.3-36.2l-35.4-87.5c-2.5-6.1-9.5-9.1-15.6-6.6
l-29.3,11.9c-6.1,2.5-9.1,9.5-6.6,15.6L49.4,212C55.1,226.1,71.4,233,85.6,227.3z"/>
<path id="l2" fill="#ffffff" d="M133.8,206.6L133.8,206.6c15.2-1.5,26.4-15.2,24.9-30.4L142.7,55.9
c-0.6-6.6-6.5-11.4-13.1-10.8l-31.4,3.1c-6.6,0.6-11.4,6.5-10.8,13.1l16.1,120.3C104.9,196.9,118.6,208.1,133.8,206.6z"/>
<path id="l3" fill="#ffffff" d="M181.8,219.6L181.8,219.6c15,3,29.7-6.8,32.7-21.8l22.8-151.7c1.3-6.5-2.9-12.8-9.4-14.1
l-31-6.2c-6.5-1.3-12.8,2.9-14.1,9.4L160,186.9C157,201.9,166.9,216.6,181.8,219.6z"/>
<path id="l4" fill="#ffffff" d="M227.8,247.1L227.8,247.1c13.9,6.5,30.5,0.4,37-13.4l58.1-142c2.8-6,0.2-13.2-5.8-16
l-28.6-13.4c-6-2.8-13.2-0.2-16,5.8l-59.4,137.7C206.6,219.7,208.3,238,227.8,247.1z"/>
<path id="l5" fill="#ffffff" d="M257.1,245.1l51.8-41l37,0.5l24.5,15.4L337.7,256l-90.1,90.2l-31.6,15.9
C216.1,362.1,184.1,325.9,257.1,245.1z"/>
This may do the trick.
$('img.svg').each(function(){
var $img = $(this);
var imgClass = $img.attr('class');
var imgURL = $img.attr('src');
$.get(imgURL, function(data) {
var $svg = $(data).find('svg');
if(typeof imgClass !== 'undefined') {
$svg = $svg.attr('class', imgClass+' style-color-black');
}
$svg = $svg.removeAttr('xmlns:a');
$img.replaceWith($svg);
}, 'xml');
});
source: codedump

Routing onclick event from embedded SVG to higher level

I have an HTML file that embeds two different SVG files, like so:
<html>
<body>
<object id="svg0" data="histograms.svg" type="image/svg+xml"></object>
<object id="svg1" data="test.svg" type="image/svg+xml"></object>
</body>
</html>
Both SVG files are interactive, by adding a javascript function that is triggered by onclick, like such:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:ns1="http://www.w3.org/1999/xlink" height="172pt" version="1.1" viewBox="0 0 1209 172" width="1209pt">
<script type="text/ecmascript">
function choose(obj) {
var values = [0.08,0.77];
var names = [ "hist_1", "hist_2", "hist_3", "hist_4", "hist_5", "hist_6", "hist_7", "hist_8", "hist_9", "hist_10", "hist_11" ];
for ( var i=0; i<names.length; i++) {
var o = document.getElementById( names[i] );
o.style['opacity'] = values[0];
}
obj.style['opacity'] = values[1];
}
</script>
...
<g id="figure_1">
<g id="patch_1">
<path d=" M0 172.8 L1209.6 172.8 L1209.6 0 L0 0 z " style="fill:#ffffff;" />
</g>
<g id="axes_1">
<g cursor="pointer" id="hist_1" onclick="choose(this)">
<path d=" M20.835 70.52 L189.696 70.52 L189.696 12.96 L20.835 12.96 z " style="fill:#ffe6cc;" />
</g>
...
How can I have a click in one SVG file trigger javascript in the other SVG file? (Possibly via top level .html file as intermediate, if necessary?)
If you're writing code in test.svg then top gets you the containiner, so
var svg0 = top.document.getElementById("svg0");
would get you the object element from the container document.
Then
obj0Document = svg0.contentDocument;
if (obj0Document && obj0Document.defaultView)
obj0Window = obj0Document.defaultView;
else if (svg0.window)
obj0Window = svg0.window;
gets you the content's document and window.
accessing the SVG document's "window" allows you to access variables and functions defined in scripts in the SVG document.
e.g. obj0Window.choose(something)
Everything must have the same domain for this to work.

Create SVG anchor element programmatically?

How do I create an SVG anchor through JavaScript? Please see relevant section and an example from spec. How do I convert this example to JavaScript (basically, how to dynamically generate the container element a so that when I click the ellipse, it navigates away.
<?xml version="1.0"?>
<svg width="5cm" height="3cm" viewBox="0 0 5 3" version="1.2" baseProfile="tiny"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Example 17_01</title>
<desc>A simple link on an ellipse.</desc>
<rect x=".01" y=".01" width="4.98" height="2.98"
fill="none" stroke="blue" stroke-width=".03"/>
<a xlink:href="http://www.w3.org/">
<ellipse cx="2.5" cy="1.5" rx="2" ry="1"
fill="red" />
</a>
</svg>
This is just basic DOM:
var xlinkNS="http://www.w3.org/1999/xlink", svgNS="http://www.w3.org/2000/svg";
var a = document.createElementNS(svgNS, "a");
a.setAttributeNS(xlinkNS,"href","http://www.w3.org/");
var ellipse = document.createElementNS(svgNS, "ellipse");
ellipse.setAttributeNS(null,"cx","2.5");
ellipse.setAttributeNS(null,"cy","1.5");
ellipse.setAttributeNS(null,"rx","2");
ellipse.setAttributeNS(null,"ry","1");
ellipse.setAttributeNS(null,"fill","red");
a.appendChild(ellipse);
document.documentElement.appendChild(a);
Using my function below, it's as easy as this:
// Find the first SVG element
var svg = document.getElementsByTagName('svg')[0];
var a = createOn(svg,'a',{'xlink:href':'http://www.w3.org/'});
createOn(a,'ellipse',{cx:2.5,cy:1.5,rx:1,ry:1,fill:'red'});
function createOn(root,name,attrs,text){
var doc = root.ownerDocument,
svg = root.ownerSVGElement || root; // In case the root _is_ the <svg>
var svgNS = svg.getAttribute('xmlns');
var el = doc.createElementNS(svgNS,name);
for (var attr in attrs){
if (!attrs.hasOwnProperty(attr)) continue;
var parts = attr.split(':');
if (parts[1]) el.setAttributeNS(
svg.getAttribute('xmlns:'+parts[0]),parts[1],attrs[attr]
);
else el.setAttributeNS(null,attr,attrs[attr]);
}
if (text) el.appendChild(document.createTextNode(text));
return root.appendChild(el);
}
If you already have the ellipse and want to wrap it, then create the 'a' element and:
// Get a reference to the ellipse however you like
var ellipse = document.getElementsByTagName('ellipse')[0];
// Put the anchor node immediately preceding the ellipse
ellipse.parentNode.insertBefore(a,ellipse);
// Move the ellipse to be a child of the anchor
a.appendChild(ellipse);

Categories