SVG node, change one item's color from another node?

I've been all over Google looking for this, 98% of it has to do with d.3/HTML. I want to use an SVG node and would like to change the color of ONE element from another node. I've seen data-bind, looks way to complicated to try w/o any HTML. I'm leaning towards a function node with an if-else statement to do a one-time animation of the node? Or a better way from someone who knows...

So far: Can't figure how to get an inject node's msg data to relate to anything inside a function node. Can't even figure out basic cr@p like how to pass the msg THRU the function node! I know, I'm a sorry excuse for an idiot!

I'm guessing to get any farther, I'll need to make the "element to change" in my SVG code have some kind of identifier so as to be unique. How is that done?

Thanks for looking!

[{"id":"853e59c1.2ea598","type":"ui_svg_graphics","z":"8b830e5d.944ee8","group":"4eddf1f8.72684","order":5,"width":0,"height":0,"svgString":"<svg width=\"40\" height=\"40\">\n  <defs>\n    <filter id=\"blurme\">\n      <feGaussianBlur in=\"SourceGraphic\" stdDeviation=\"3\" />\n    </filter>\n  </defs>\n\n  <circle cx=\"20\" cy=\"20\" r=\"14\" stroke=\"#0000CD\" stroke-width=\"2\" fill=\"#1E90FF\" filter=\"url(#blurme)\"/>     \n  <circle cx=\"20\" cy=\"20\" r=\"18\" stroke=\"#555555\" stroke-width=\"3\" fill=\"none\"/>\n\n</svg>","clickableShapes":[],"smilAnimations":[],"bindings":[],"showCoordinates":false,"autoFormatAfterEdit":false,"showBrowserErrors":false,"outputField":"payload","editorUrl":"//","directory":"","panning":"disabled","zooming":"disabled","panOnlyWhenZoomed":false,"doubleClickZoomEnabled":false,"mouseWheelZoomEnabled":false,"name":"","x":480,"y":180,"wires":[[]],"info":"Would like to change the fill color of circle on line #8 programmatically\n"},{"id":"4eddf1f8.72684","type":"ui_group","z":"","name":"text labels","tab":"81831aab.f2f568","order":2,"disp":false,"width":7,"collapse":false},{"id":"81831aab.f2f568","type":"ui_tab","z":"","name":"GTO-500 Gate Opener","icon":"dashboard","disabled":false,"hidden":false}]

Please check node comment section as I'm too stupid to put a comment inside the svg code w/o wrecking it...


Hi Russ,
Was it your intention to include the function-node and inject-node also in your flow? Because the flow that you have shared only contains the svg-node...

Bart, I found it! You had a great example on Github that got me working, it just took me a bit to find the right one.

[{"id":"71d5a00a.73848","type":"group","z":"c199b9b6.017a2","name":"GPIO pim 40 verification closed","style":{"stroke":"#6f2fa0","fill":"#6f2fa0","fill-opacity":"0.25","label":true,"color":"#000000"},"nodes":["2fa1b114.94cff6","afd0b118.45cb58","b1a6e150.0276e8","95376fc5.6e31c"],"x":24,"y":19,"w":562,"h":122},{"id":"2fa1b114.94cff6","type":"rpi-gpio in","z":"c199b9b6.017a2","g":"71d5a00a.73848","name":"40 Closed Verified","pin":"40","intype":"up","debounce":"25","read":true,"x":140,"y":80,"wires":[["afd0b118.45cb58"]]},{"id":"afd0b118.45cb58","type":"switch","z":"c199b9b6.017a2","g":"71d5a00a.73848","name":"If input is 1","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"1","vt":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":320,"y":80,"wires":[["95376fc5.6e31c"],["b1a6e150.0276e8"]]},{"id":"b1a6e150.0276e8","type":"change","z":"c199b9b6.017a2","g":"71d5a00a.73848","name":"Change to 0","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"command\":\"update_style\",\"selector\":\"#verClosed\",\"attributeName\":\"fill\",\"attributeValue\":\"#333333\"}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":100,"wires":[["f9f17505.564b88"]]},{"id":"95376fc5.6e31c","type":"change","z":"c199b9b6.017a2","g":"71d5a00a.73848","name":"Change to 1","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"command\":\"update_style\",\"selector\":\"#verClosed\",\"attributeName\":\"fill\",\"attributeValue\":\"#1E90FF\"}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":60,"wires":[["f9f17505.564b88"]]},{"id":"a7402322.19d7e","type":"group","z":"c199b9b6.017a2","name":"GPIO pin 38 verification open","style":{"stroke":"#6f2fa0","fill":"#6f2fa0","fill-opacity":"0.25","label":true,"color":"#000000"},"nodes":["3f8dee4c.474622","ab956729.6141f","5189b379.44c39c","a912f64a.f60bf"],"x":24,"y":159,"w":562,"h":122},{"id":"3f8dee4c.474622","type":"switch","z":"c199b9b6.017a2","g":"a7402322.19d7e","name":"If input is 1","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"1","vt":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":310,"y":220,"wires":[["5189b379.44c39c"],["ab956729.6141f"]]},{"id":"ab956729.6141f","type":"change","z":"c199b9b6.017a2","g":"a7402322.19d7e","name":"Change to 0","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"command\":\"update_style\",\"selector\":\"#verOpen\",\"attributeName\":\"fill\",\"attributeValue\":\"#333333\"}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":240,"wires":[["235bd56a.d9af4a"]]},{"id":"5189b379.44c39c","type":"change","z":"c199b9b6.017a2","g":"a7402322.19d7e","name":"Change to 1","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"command\":\"update_style\",\"selector\":\"#verOpen\",\"attributeName\":\"fill\",\"attributeValue\":\"#1E90FF\"}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":200,"wires":[["235bd56a.d9af4a"]]},{"id":"a912f64a.f60bf","type":"rpi-gpio in","z":"c199b9b6.017a2","g":"a7402322.19d7e","name":"38 Open Verified","pin":"38","intype":"up","debounce":"25","read":true,"x":130,"y":220,"wires":[["3f8dee4c.474622"]]},{"id":"dea38dc1.3a8ca","type":"group","z":"c199b9b6.017a2","name":"Open / Close SVG LEDs","style":{"stroke":"#6f2fa0","fill":"#6f2fa0","fill-opacity":"0.25","label":true,"color":"#000000"},"nodes":["235bd56a.d9af4a","f9f17505.564b88"],"x":614,"y":199,"w":392,"h":82},{"id":"235bd56a.d9af4a","type":"ui_svg_graphics","z":"c199b9b6.017a2","g":"dea38dc1.3a8ca","group":"7deb7f7c.de4dd","order":1,"width":3,"height":2,"svgString":"<svg x=\"0\" y=\"0\" height=\"50\" viewBox=\"0 0 50 50\" width=\"50\" xmlns=\"\" xmlns:svg=\"\" xmlns:xlink=\"\"></svg>\n\n<svg width=\"40\" height=\"40\">\n  <defs>\n    <filter id=\"blurme\">\n      <feGaussianBlur in=\"SourceGraphic\" stdDeviation=\"3\" />\n    </filter>\n  </defs>\n\n  <circle id=\"verOpen\" cx=\"20\" cy=\"20\" r=\"14\" stroke=\"#000040\" stroke-width=\"2\" fill=\"#333333\" filter=\"url(#blurme)\"/>     \n  <circle cx=\"20\" cy=\"20\" r=\"18\" stroke=\"#555555\" stroke-width=\"3\" fill=\"none\"/>\n\n</svg>","clickableShapes":[],"smilAnimations":[],"bindings":[],"showCoordinates":false,"autoFormatAfterEdit":false,"showBrowserErrors":false,"outputField":"payload","editorUrl":"//","directory":"","panning":"disabled","zooming":"disabled","panOnlyWhenZoomed":false,"doubleClickZoomEnabled":false,"mouseWheelZoomEnabled":false,"name":"verOpen","x":700,"y":240,"wires":[[]],"info":"Would like to change the fill color of circle on line #8 programmatically\n"},{"id":"f9f17505.564b88","type":"ui_svg_graphics","z":"c199b9b6.017a2","g":"dea38dc1.3a8ca","group":"7deb7f7c.de4dd","order":2,"width":3,"height":2,"svgString":"<svg x=\"0\" y=\"0\" height=\"50\" viewBox=\"0 0 50 50\" width=\"50\" xmlns=\"\" xmlns:svg=\"\" xmlns:xlink=\"\"></svg>\n\n<svg width=\"40\" height=\"40\">\n  <defs>\n    <filter id=\"blurme\">\n      <feGaussianBlur in=\"SourceGraphic\" stdDeviation=\"3\" />\n    </filter>\n  </defs>\n\n  <circle id=\"verClosed\" cx=\"20\" cy=\"20\" r=\"14\" stroke=\"#000040\" stroke-width=\"2\" fill=\"#333333\" filter=\"url(#blurme)\"/>     \n  <circle cx=\"20\" cy=\"20\" r=\"18\" stroke=\"#555555\" stroke-width=\"3\" fill=\"none\"/>\n\n</svg>","clickableShapes":[],"smilAnimations":[],"bindings":[],"showCoordinates":false,"autoFormatAfterEdit":false,"showBrowserErrors":false,"outputField":"payload","editorUrl":"//","directory":"","panning":"disabled","zooming":"disabled","panOnlyWhenZoomed":false,"doubleClickZoomEnabled":false,"mouseWheelZoomEnabled":false,"name":"verClosed","x":910,"y":240,"wires":[[]]},{"id":"7deb7f7c.de4dd","type":"ui_group","z":"","name":"widget group","tab":"81831aab.f2f568","order":2,"disp":false,"width":6,"collapse":false},{"id":"81831aab.f2f568","type":"ui_tab","z":"","name":"GTO-500 Gate Opener","icon":"dashboard","disabled":false,"hidden":false}]

Here's the finished product now working off pi pins. I didn't include the inject nodes as I'm finished troubleshooting them and using pi now. Hope it all comes thru, I tested it on a new flow page...



1 Like

Hi Bart,

Another Q on your SVG node. Do the included viewport "callouts" have any bearing within the node? Reason I ask is because I'm experimenting with placement of two nodes on my UI. Both are identical in size and structure (save for a couple color attributes) but they will not align equally while in the same group. Here's the first line in my SVG, placed there from "new" and unaltered:

<svg x="0" y="0" height="100" viewBox="0 0 100 100" width="100" xmlns="" xmlns:svg="" xmlns:xlink=""></svg>

Both my SVGs are 40x40 px and should fit safely inside a 1x1 (48px) widget box but don't. One fits in a 2x2 box but both actually need to be sized 3x3 to look and line up decently. The first one on the grid fits a 2x2 just fine, the second needs a 3x3 to not see scrollbars. I've been tinkering around on Code Pen and see I can completely remove the viewport (0 0 0 0) w/o affecting the SVG. Not sure what the actual SVG drawing's x: & y: dims are being referenced to, as the viewport & x:/y: numbers don't seem to mean as much in the node as the N-R box size does. Changing the VP numbers does nothing, deleting them is another story!

Pretty sure I'm missing something easy here...


Hi Russ,
It is always better to start a new discussion if you encounter a new problem. Because it is confusing for readers, and people with knowledge about dashboard alignment might not read a thread with a subject about SVG item colors...

And can you please add some screenshots, with arrows to point where we have to look. That makes it much easier to understand your problem. And then hopefully some others can join the discussion, because I'm not an expert in dashboard widget alignments ...

That I don't understand. The width and height of your SVG are "100" which means "100px" (not "100%"), so your SVG is 100p x 100px isn't it?

You can see in this StackOverflow discussion that the x/y attributes are only used when you have an SVG nested into another SVG.

That I also don't understand. The viewport is defined by your svg width and height attributes. Do you mean the viewbox attribute? The viewbox can be used to specify which part of your SVG drawing needs to be displayed in your viewport. See this viewbox demo that I made for somebody else this evening...

What do you mean with that? By using a viewBox, the svg contents will scale (with its parent container), without it won't...

Hi Bart.

Don't feel bad, I don't know what I mean by any of this either. :frowning_man: I took the day off to rest my head after looking at a couple great tutorials. Even though I felt like I knew "what was what" and tinkered with the various attributes in Code Pen with acceptable results, in N-R nothing worked as expected. I have (a pair of) individual 40x40 SVG's I'm trying to draw in a known, controllable area. I guess it would help me "see" the viewport and viewbox if they could be colored differently so changes could actually be seen in realtime. Of course, that's not in my realm of knowledge.

What might be throwing me is the line (above) included in your node. I've tried altering and even deleting parts of it with no understanding of what I'm doing. Here's the full code of one working node. They both work fine, but I can't seem to move either where I need them. It's odd, to me, that a "widget" at 48x48 cannot hold a 40x40 SVG. And believe me, I've "adjusted" every dimension possible.

<svg x="0" y="0" height="50" viewBox="0 0 50 50" width="50" 

<svg width="40" height="40">
    <filter id="blurme">
      <feGaussianBlur in="SourceGraphic" stdDeviation="3" />

  <circle id="verOpen" cx="20" cy="20" r="14" stroke="#000040" stroke-width="2" fill="#333333" filter="url(#blurme)"/>     
  <circle cx="20" cy="20" r="18" stroke="#555555" stroke-width="3" fill="none"/>


I have no idea if my code is interfering with the items in the first line (somewhat altered) or ? Should that be deleted or is it required? I have two different "width=" and "height=" callouts, I don't know which is being read or both.. Not sure if more than one tag is a problem or if multiple tags are OK in the same node. Many Q's on stuff that's different because N-R is different than...


Perhaps I'm not interpreting your question correctly.

  • The viewport is the section of the dashboard where the SVG will be visible. In your case you have defined that the visible section should be 50px wide and 50px high:

    <svg x="0" y="0" height="50" width="50" ...>

    P.S. The viewbox x and y coordinates are not relevant for you (those are only used to position a nested svg into another svg at that location)...

  • The viewbox is the part of the SVG drawing that you want to display in your SVG viewport. In your case

    <svg ... viewBox="0 0 50 50" ...>

So your viewBox is exactly the same size as your viewPort, which means that there will be no scaling:


Suppose you would have a viewbox like e.g. "0 0 25 25", this means that this section of your drawing needs to be scaled to fit your viewport:


So your drawing would be displayed scaled:


I hope that somebody else can help you with this, because I'm not a CSS specialist.
But as I said before, without screenshot (preferably with arrows and some explanation) it is very hard for us to help you.

Wehn you drag a node onto the workspace, there's an <svg></svg> line ("built in" if you will) aleady there. Is it there mainly for the outside web references with simple generic data for coordinates? It's confunsing because my dwg has it's own <svg width="xx" height="xx"> as does line 1, so which of those takes preference? Or does it even matter?

How many <svg></svg> tags can be in one node and how does line #1 affect them, any or all?

I love N-R, the more I learn, the more there is to be had. But as a rookie, I find laying out visual node items to be a royal PIA! Maybe someday there'll be a better, easier, nicer way to get items where you want them. I have obsessed away almost a weeks' worth of time tweaking the UI, pretty sure the N-R authoring crew didn't intend for that to be the case...

Love your SVG node and thanks again as always!


Not sure anymore why it was added. I think it was simply to show users what kind of input we expect. In this case an empty drawing.

If you have your own <svg ...> then you should remove the default empty one that we have generated. Otherwise you end up with two SVG drawings: our empty one and yours. Ah now I see it in the SVG that you have shared above. Had completely overlooked it ...
So you should only keep your own SVG:

<svg width="40" height="40" viewBox="0 0 40 40">
    <filter id="blurme">
      <feGaussianBlur in="SourceGraphic" stdDeviation="3" />
  <circle id="verOpen" cx="20" cy="20" r="14" stroke="#000040" stroke-width="2" fill="#333333" filter="url(#blurme)"/>     
  <circle cx="20" cy="20" r="18" stroke="#555555" stroke-width="3" fill="none"/>

I have added a viewbox to your first line, so you experiment with it.
Ah now I finally understand why you where talking about "your first line". To be honest, I had no clue what that was all about :rofl:

I'm very curious whether it works now better for you. Because I have no idea what happens when you add two SVG drawings, since that was not really the intention of this node :wink:

I was also not aware that the the default empty SVG (which is automatically added) was confusing for less technical users. So it is good that you mention it! Do you think it would be clearer if I would generate something like this for new nodes:

<svg x="0" y="0" height="50" viewBox="0 0 50 50" width="50" 
  <!--Add here your SVG shapes (circles, rectangles, ...)-->
  <!--Or remove everything, if you want to paste an entire drawing (<svg...>...</svg>).-->

I should also check whether the namespaces are required (based on this Stackoverflow discussion) for this node:


Because if those are not needed, it is only confusing for novice users so it would be better to not generate those...

So you can see the "pull" to the left of -10 to line up the horizontal of the open, while closed remains at 0. Then there's the vertical, -8 for open and -10 for closed to place them vertically. Two pixels off for some reason...


I'm afraid I will need to keep repeating myself...
Can you share some screenshots to explain what your problem is, and draw some arrows to where we need to look. Perhaps then somebody can help you.

Nevermind, it's me. :blush: I took a (phone) screen-cap, imported it into my laptop and blew it up so the tops of the two SVGs were up against the upper edge of the screen. Ends up that -08 and -10 were misaligned horizontally even though my eyes saw different.Prolly due the dropped "p". But -10 on both is perfect, so there it'll be. Apologies for the confusion, numbers don't lie!


No problem!
Can I assume that everything is solved now, or did I forgot something?

Yessir, all good. Thanks!


1 Like

BTW the version on Github now shows the extra comments in the SVG string that is automatically added when you add a new SVG node in the flow:


This change is not available on NPM yet, but will be published in the next release.
Hopefully it is now a bit more self-explaining ...
See you around!

1 Like

Ahhhh, help! My SVG nodes disappeared and won't reinstall:

2020-12-16T20:34:50.680Z Install : node-red-contrib-ui-svg 2.1.1

2020-12-16T20:34:56.814Z npm install --no-audit --no-update-notifier --no-fund --save --save-prefix=~ --production node-red-contrib-ui-svg@2.1.1
2020-12-16T20:35:12.046Z [err] npm WARN node-red-contrib-ui-led@0.3.3 requires a peer of node-red-dashboard@2.23.x but none is installed. You must install peer dependencies yourself.
2020-12-16T20:35:12.046Z [err] 
2020-12-16T20:35:12.120Z [err] npm
2020-12-16T20:35:12.121Z [err]  ERR! code EEXIST
2020-12-16T20:35:12.121Z [err] npm ERR! path /home/pi/.node-red/node_modules/js-beautify/node_modules/.bin/mkdirp
2020-12-16T20:35:12.166Z [err] npm 
2020-12-16T20:35:12.167Z [err] ERR! Refusing to delete /home/pi/.node-red/node_modules/js-beautify/node_modules/.bin/mkdirp: is outside /home/pi/.node-red/node_modules/js-beautify/node_modules/mkdirp and not a link
2020-12-16T20:35:12.167Z [err] npm ERR! File exists: /home/pi/.node-red/node_modules/js-beautify/node_modules/.bin/mkdirp
2020-12-16T20:35:12.167Z [err] npm
2020-12-16T20:35:12.167Z [err]  ERR! Remove the existing file and try again, or run npm
2020-12-16T20:35:12.167Z [err] npm ERR!
2020-12-16T20:35:12.167Z [err]  with --force to overwrite files recklessly.
2020-12-16T20:35:12.202Z [err] 
2020-12-16T20:35:12.203Z [err] npm ERR! A complete log of this run can be found in:
2020-12-16T20:35:12.203Z [err] npm ERR!     /home/pi/.npm/_logs/2020-12-16T20_35_12_180Z-debug.log
2020-12-16T20:35:12.223Z rc=1

Can I manually "npm" or "apt-get" them or something else?

Nevermind, there's a problem with my file structure, gotta get that figured out. I lost my SD card a couple days ago and been having to rebuild my system by hand. npm is looking for /home/pi/ while my folder is actually /home/pi/.node-red/ . Something's gotta give!

pi@pigate:~ $ npm install node-red-contrib-ui-svg
npm WARN saveError ENOENT: no such file or directory, open '/home/pi/package.json'
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN enoent ENOENT: no such file or directory, open '/home/pi/package.json'
npm WARN pi No description
npm WARN pi No repository field.
npm WARN pi No README data
npm WARN pi No license field.

+ node-red-contrib-ui-svg@2.1.1
added 29 packages from 28 contributors and audited 29 packages in 6.524s

1 package is looking for funding
  run `npm fund` for details

found 0 vulnerabilities

Sorry, I'll try and figure it out...


This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.