I am trying to alter colors in an SVG with JavaScript. Is this possible? Can I load it as an object and then somehow have access to the color and image data?
-
of course peter! you mean vote your answer up?Potney Switters– Potney Switters2012-03-28 07:35:26 +00:00Commented Mar 28, 2012 at 7:35
-
you can also upvote but the best is to check my answer as the accepted answer (the geen v mark), thankspeter– peter2012-03-29 10:08:41 +00:00Commented Mar 29, 2012 at 10:08
12 Answers
Sure, here is an example (standard HTML boilerplate omitted):
<svg id="svg1" xmlns="http://www.w3.org/2000/svg" style="width: 3.5in; height: 1in">
<circle id="circle1" r="30" cx="34" cy="34"
style="fill: red; stroke: blue; stroke-width: 2"/>
</svg>
<button onclick="circle1.style.fill='yellow';">Click to change to yellow</button>
9 Comments
<svg> element as an <object>; this answer does not do that.onclick is most definitely JavaScript code changing the fill color. Last I knew HTML didn't have dot notation or end lines with semi-colons.<svg> or <object>? "Load it as an object" can reasonably mean to load an external SVG file into an <object>, in which case this example falls short. If using object tag, document.getElementById( 'obj-id' ).contentDocument.getElementById( 'circle1' ).style.fill = 'yellow' would work. See answers below.This is for loading an SVG via <object>:
<object class="svgClass" type="image/svg+xml" data="image.svg"></object>
The JavaScript code is like this:
// change to red
document.querySelector(".svgClass").getSVGDocument().getElementById("svgInternalID").setAttribute("fill", "red")
To change svgInternalID you have to open the SVG file which is plain text (e.g., image.svg) and edit it:
<path id="svgInternalID"
3 Comments
getSVGDocument() is deprecated, it's recommended to use the contentDocument attribute instead, see w3.org/TR/SVG11/…Given some SVG:
<div id="main">
<svg id="octocat" xmlns="http://www.w3.org/2000/svg" width="400px" height="400px" viewBox="-60 0 420 330" style="fill:#fff;stroke: #000; stroke-opacity: 0.1">
<path id="puddle" d="m296.94 295.43c0 20.533-47.56 37.176-106.22 37.176-58.67 0-106.23-16.643-106.23-37.176s47.558-37.18 106.23-37.18c58.66 0 106.22 16.65 106.22 37.18z"/>
<path class="shadow-legs" d="m161.85 331.22v-26.5c0-3.422-.619-6.284-1.653-8.701 6.853 5.322 7.316 18.695 7.316 18.695v17.004c6.166.481 12.534.773 19.053.861l-.172-16.92c-.944-23.13-20.769-25.961-20.769-25.961-7.245-1.645-7.137 1.991-6.409 4.34-7.108-12.122-26.158-10.556-26.158-10.556-6.611 2.357-.475 6.607-.475 6.607 10.387 3.775 11.33 15.105 11.33 15.105v23.622c5.72.98 11.71 1.79 17.94 2.4z"/>
<path class="shadow-legs" d="m245.4 283.48s-19.053-1.566-26.16 10.559c.728-2.35.839-5.989-6.408-4.343 0 0-19.824 2.832-20.768 25.961l-.174 16.946c6.509-.025 12.876-.254 19.054-.671v-17.219s.465-13.373 7.316-18.695c-1.034 2.417-1.653 5.278-1.653 8.701v26.775c6.214-.544 12.211-1.279 17.937-2.188v-24.113s.944-11.33 11.33-15.105c0-.01 6.13-4.26-.48-6.62z"/>
<path id="cat" d="m378.18 141.32l.28-1.389c-31.162-6.231-63.141-6.294-82.487-5.49 3.178-11.451 4.134-24.627 4.134-39.32 0-21.073-7.917-37.931-20.77-50.759 2.246-7.25 5.246-23.351-2.996-43.963 0 0-14.541-4.617-47.431 17.396-12.884-3.22-26.596-4.81-40.328-4.81-15.109 0-30.376 1.924-44.615 5.83-33.94-23.154-48.923-18.411-48.923-18.411-9.78 24.457-3.733 42.566-1.896 47.063-11.495 12.406-18.513 28.243-18.513 47.659 0 14.658 1.669 27.808 5.745 39.237-19.511-.71-50.323-.437-80.373 5.572l.276 1.389c30.231-6.046 61.237-6.256 80.629-5.522.898 2.366 1.899 4.661 3.021 6.879-19.177.618-51.922 3.062-83.303 11.915l.387 1.36c31.629-8.918 64.658-11.301 83.649-11.882 11.458 21.358 34.048 35.152 74.236 39.484-5.704 3.833-11.523 10.349-13.881 21.374-7.773 3.718-32.379 12.793-47.142-12.599 0 0-8.264-15.109-24.082-16.292 0 0-15.344-.235-1.059 9.562 0 0 10.267 4.838 17.351 23.019 0 0 9.241 31.01 53.835 21.061v32.032s-.943 11.33-11.33 15.105c0 0-6.137 4.249.475 6.606 0 0 28.792 2.361 28.792-21.238v-34.929s-1.142-13.852 5.663-18.667v57.371s-.47 13.688-7.551 18.881c0 0-4.723 8.494 5.663 6.137 0 0 19.824-2.832 20.769-25.961l.449-58.06h4.765l.453 58.06c.943 23.129 20.768 25.961 20.768 25.961 10.383 2.357 5.663-6.137 5.663-6.137-7.08-5.193-7.551-18.881-7.551-18.881v-56.876c6.801 5.296 5.663 18.171 5.663 18.171v34.929c0 23.6 28.793 21.238 28.793 21.238 6.606-2.357.474-6.606.474-6.606-10.386-3.775-11.33-15.105-11.33-15.105v-45.786c0-17.854-7.518-27.309-14.87-32.3 42.859-4.25 63.426-18.089 72.903-39.591 18.773.516 52.557 2.803 84.873 11.919l.384-1.36c-32.131-9.063-65.692-11.408-84.655-11.96.898-2.172 1.682-4.431 2.378-6.755 19.25-.80 51.38-.79 82.66 5.46z"/>
<path id="face" d="m258.19 94.132c9.231 8.363 14.631 18.462 14.631 29.343 0 50.804-37.872 52.181-84.585 52.181-46.721 0-84.589-7.035-84.589-52.181 0-10.809 5.324-20.845 14.441-29.174 15.208-13.881 40.946-6.531 70.147-6.531 29.07-.004 54.72-7.429 69.95 6.357z"/>
<path id="eyes" d="m160.1 126.06 c0 13.994-7.88 25.336-17.6 25.336-9.72 0-17.6-11.342-17.6-25.336 0-13.992 7.88-25.33 17.6-25.33 9.72.01 17.6 11.34 17.6 25.33z m94.43 0 c0 13.994-7.88 25.336-17.6 25.336-9.72 0-17.6-11.342-17.6-25.336 0-13.992 7.88-25.33 17.6-25.33 9.72.01 17.6 11.34 17.6 25.33z"/>
<path id="pupils" d="m154.46 126.38 c0 9.328-5.26 16.887-11.734 16.887s-11.733-7.559-11.733-16.887c0-9.331 5.255-16.894 11.733-16.894 6.47 0 11.73 7.56 11.73 16.89z m94.42 0 c0 9.328-5.26 16.887-11.734 16.887s-11.733-7.559-11.733-16.887c0-9.331 5.255-16.894 11.733-16.894 6.47 0 11.73 7.56 11.73 16.89z"/>
<circle id="nose" cx="188.5" cy="148.56" r="4.401"/>
<path id="mouth" d="m178.23 159.69c-.26-.738.128-1.545.861-1.805.737-.26 1.546.128 1.805.861 1.134 3.198 4.167 5.346 7.551 5.346s6.417-2.147 7.551-5.346c.26-.738 1.067-1.121 1.805-.861s1.121 1.067.862 1.805c-1.529 4.324-5.639 7.229-10.218 7.229s-8.68-2.89-10.21-7.22z"/>
<path id="octo" d="m80.641 179.82 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m8.5 4.72 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m5.193 6.14 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m4.72 7.08 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m5.188 6.61 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m7.09 5.66 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m9.91 3.78 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m9.87 0 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m10.01 -1.64 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z"/>
<path id="drop" d="m69.369 186.12l-3.066 10.683s-.8 3.861 2.84 4.546c3.8-.074 3.486-3.627 3.223-4.781z"/>
</svg>
</div>
Using jQuery, for instance, you could do:
var _currentFill = "#f00"; // red
$svg = $("#octocat");
$("#face", $svg).attr('style', "fill:"+_currentFill); })
I provided a coloring book demo as an answer to another stackoverflow question: http://bl.ocks.org/4545199. Tested on Safari, Chrome, and Firefox.
Comments
For the background color - the fill property can be accessed like so:
svgElement.style.fill = '#fff';
To set the border color, do the same for the stroke property.
See it in action:
const svgElement = document.getElementById('svg')
const checkboxElement = document.getElementById('check')
checkboxElement.addEventListener('change', e => {
svgElement.style.fill = e.target.checked ? 'PeachPuff' : 'PapayaWhip'
})
<input type="checkbox" id="check" />
<svg id="svg" fill="AliceBlue">
<circle r="50" cx="70" cy="70" />
</svg>
Please refer to the W3C reference on SVG for more capabilities, as it's a broad issue.
6 Comments
Raphael API code of mine. this is the value sent to the attr() method. deleted that, thanks.Here's a full example that shows how to modify the fill color of an svg referenced via <embed>, <object> and <iframe>.
1 Comment
Your SVG must be inline in your document in order to be styled with CSS. This can be done by writing the SVG markup directly into your HTML code, or by using SVG injection, which replaces the img element with the content from and SVG file with Javascript.
There is an open source library called SVGInject that does this for you. All you have to do is to add the attribute onload="SVGInject(this)" to you <img> tag.
A simple example using SVGInject looks like this:
<html>
<head>
<script src="svg-inject.min.js"></script>
</head>
<body>
<img src="image.svg" onload="SVGInject(this)" />
</body>
</html>
After the image is loaded the onload="SVGInject(this) will trigger the injection and the <img> element will be replaced by the contents of the SVG file provided in the src attribute.
Comments
I know this is a pretty old question. But I stumbled over it searching for the same topic. Out of this and some other answers I finally built a function for precisely this topic:
- It loads a SVG completely in JavaScript ...
- removes the size-tags to make it scale with its parent DIV
- even adjusts the viewbox to make it square and
- changes the fillColor in different ways.
Maybe this is of help for some of you:
/* inspired by https://codepen.io/osublake/pen/OMRdKq */
function loadSvgIntoDiv(theDIV, pathToSvg, prefix = 'myPrefix-', fillColor = null, fillColorID = null)
{
if ( theDIV == null || typeof theDIV.appendChild != 'function' ) return null;
fetch(pathToSvg).then( (res) => {
// check the status
if (!res.ok)
{
switch (res.status)
{
case 404:
throw new Error('"' + pathToSvg + '" not found (error 404).');
default:
throw new Error('Failed to fetch "' + pathToSvg + '": ' + res.status + ' (' + res.statusText + ')');
}
}
let contentType = res.headers.get('content-type');
if ( typeof contentType == 'string' && contentType.indexOf('image/svg') !== -1 )
{
// hand over SVG-content to next .then
return res.text();
} else {
throw new Error('Unexpected content type (' + iconPath + ', ' + contentType + ')');
}
})
.then( (iconData) => {
// clean up SVG
// remove width and height from <svg ...>-tag to allow scaling
iconData = iconData.replace(/\<svg([^>]*)\>/ig, (match) => {
return match.replace(/width\=[\'\"]([^\"^\']*)[\"\']/ig, '').replace(/height\=[\'\"]([^\"^\']*)[\"\']/ig, '');
});
// adjust viewbox to be a square image
iconData = iconData.replace(/\<svg([^>]*)\>/ig, (match) => {
return match.replace(/viewbox\=[\'\"][^0-9^\.^\-]*([0-9\.\-]*)[^0-9^\.^\-]*([0-9\.\-]*)[^0-9^\.^\-]*([0-9\.\-]*)[^0-9^\.^\-]*([0-9\.\-]*)[^\"^\']*[\"\']/ig, (match, x, y, w, h) => {
x = Number(x);
y = Number(y);
w = Number(w);
h = Number(h);
if ( w < h ) { x=x-(h-w)/2; w=h; }
if ( h < w ) { y=y-(w-h)/2; h=w; }
return 'viewbox="' + x + ' ' + y + ' ' + w + ' ' + h + '"';
});
});
let origIcon = iconData;
// add fill-style to a given id
if ( fillColorID != null && fillColor != null )
{
let search = '/id\=[\"\']' + fillColorID + '[\"\']/ig';
iconData = iconData.replace(search, 'id="' + fillColorID + '" style="fill: ' + fillColor + '" ');
}
// edit all fill-statements within path-tags
if ( fillColor != null ) fillColor='fill="' + fillColor + '"';
if ( fillColor == null || fillColorID != null ) fillColor='';
iconData = iconData.replace(/\<path([^>]*)\>/ig, (match) => {
return match.replace(/fill\=[\'\"]([^\"^\']*)[\"\']/ig, fillColor);
});
iconData = iconData.replace(/\<g\ ([^>]*)\>/ig, (match) => {
return match.replace(/fill\=[\'\"]([^\"^\']*)[\"\']/ig, fillColor);
});
// no fill was added, as nothing was changed
if ( iconData == origIcon)
{
iconData = iconData.replace(/\<g\ ([^>]*)\>/ig, (match, p) => {
return '<g ' + replaceFill + p + '>';
});
iconData = iconData.replace(/\<path([^>]*)\>/ig, (match, p) => {
return '<path ' + replaceFill + p + '>';
});
}
// add prefix in front of every ID to prevent duplicates
iconData = iconData.replace(/id\=[\"\']([^\"^\']*)[\"\']/ig, 'id="' + prefix + '$1"');
// finally add the SVG to the div
theDIV.innerHTML = iconData;
})
.catch( (error) => {
// handle error messages
});
}
see also: https://gist.github.com/aroesler-privat/2c304d42644c72142195842b10fff781
Comments
The Objects contentDocument exposes the SVG's DOM for manipulation. Here the kangaroos first change to yellow in the external CSS then Javascript sets them to gold.
Comments
You can manipulate an SVG color with the "fill" style. However, to do so, you have to use an SVG tag directly in your html document. You can't reference it in an "img" tag using the "src" attribute. Here's an example of using the SVG in your html.
circle { cursor: pointer; transition: all 0.33s; }
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SVG Manipulation</title>
</head>
<body>
<!-- SVG embedded directly in HTML -->
<svg class="info-icon" width="100" height="100" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>
<script>
var icon = document.querySelector(".info-icon");
icon.addEventListener("click", changeColor);
function changeColor() {
icon.querySelector('circle').style.fill = "#222"; // Change the fill color of the circle element
}
</script>
</body>
</html>
Sometimes the path of the SVG can be lengthy, so be careful! If you don't want to do that, then you can reference the SVG in an "img" tag "src" attribute, and change the colour of the SVG by using the "filter" style. Simple solution to that is using a hex to filter converter.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SVG Manipulation with IMG</title>
<style>
.circle {
width: 100px;
height: 100px;
cursor: pointer;
}
</style>
</head>
<body>
<img class="circle" src="https://www.svgrepo.com/show/529031/info-circle.svg">
<script>
var icon = document.querySelector(".circle");
icon.addEventListener("click", changeColor);
function changeColor() {
icon.style.filter = "invert(41%) sepia(44%) saturate(4130%) hue-rotate(77deg) brightness(95%) contrast(98%)";
}
</script>
</body>
</html>
Comments
Built off the above but with dynamic creation and a vector image, not drawing.
function svgztruck() {
tok = "{d path value}"
return tok;
}
function buildsvg( eid ) {
console.log("building");
var zvg = "svg" + eid;
var vvg = eval( zvg );
var raw = vvg();
var svg = document.getElementById( eid );
svg.setAttributeNS(null,"d", raw );
svg.setAttributeNS(null,"fill","green");
svg.setAttributeNS(null,"onlick", eid + ".style.fill=#FF0000");
return;
}
You could call with:
<img src="" onerror="buildscript">
Now you can add colors by sub element and manipulate all elements of the dom directly. It is important to implement your viewbox and height width first on the svg html, not done in the example above.
There is no need to make your code 10 pages when it could be one... but who am I to argue. Better use PHP while your at it.
The inner element that svg builds on is a simple <svg lamencoding id=parenteid><path id=eid><svg> with nothing else.
1 Comment
If it is just about the color and there is no specific need for JavaScript, you could also convert them to a font. This link gives you an opportunity to create a font based on the SVG. However, it is not possible to use img attributes afterwards - like "alt". This also limits the accessibility of your website for blind people and so on.