bartbutenaers / node-red-contrib-ui-svg

A Node-RED widget node to show interactive SVG (vector graphics) in the dashboard
Apache License 2.0
94 stars 27 forks source link

Manipulating path elements #85

Closed tkirchm closed 3 years ago

tkirchm commented 3 years ago

Hi @bartbutenaers,

any idea how to edit length of path? I want to show status of my blinds. LineLength

There are two ways to achieve this I can think of: 1) New command to set specific part of path. 2) New command get_attribute to get actual path -> change value by string manipulation (in my example change length of vertical line without knowing where it starts)-> set_attribute.

I would prefer second one as it has more opportunities to change attributes.

bartbutenaers commented 3 years ago

Hi @tkirchm,

Not sure whether I understand it correctly. I would assume you do it like this:

Is there something that I have overlooked?

bartbutenaers commented 3 years ago

I mean something like this:

image

[{"id":"4e273549.9a90ac","type":"inject","z":"7f1827bd.8acfe8","name":"Sensor A = ON","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"SENSOR_A","payload":"ON","payloadType":"str","x":360,"y":2020,"wires":[["2612c30a.10e16c"]]},{"id":"900291ac.fcd07","type":"inject","z":"7f1827bd.8acfe8","name":"Sensor A = OFF","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"SENSOR_A","payload":"OFF","payloadType":"str","x":360,"y":2060,"wires":[["2612c30a.10e16c"]]},{"id":"25bae59e.b13fea","type":"comment","z":"7f1827bd.8acfe8","name":"Sensor values arriving from anywhere (MQTT, GPIO, ....)","info":"","x":370,"y":2100,"wires":[]},{"id":"2612c30a.10e16c","type":"change","z":"7f1827bd.8acfe8","name":"Store on flow memory","rules":[{"t":"set","p":"SENSOR_A","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":2020,"wires":[["623f05b6.ac76ac"]]},{"id":"7ea64feb.98a6f","type":"inject","z":"7f1827bd.8acfe8","name":"Load from flow memory at startup","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"SENSOR_A","payload":"SENSOR_A","payloadType":"flow","x":560,"y":1960,"wires":[["623f05b6.ac76ac"]]},{"id":"623f05b6.ac76ac","type":"change","z":"7f1827bd.8acfe8","name":"Construct command","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\t   \"command\":\"update_attribute\",\t   \"selector\":\"#sensor_a\",\t   \"attributeName\":\"fill\",\t   \"attributeValue\": payload = \"ON\" ? \"blue\" : \"red\"\t}","tot":"jsonata"},{"t":"delete","p":"topic","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":860,"y":2020,"wires":[["8570c9cc.c80118"]]},{"id":"8570c9cc.c80118","type":"ui_svg_graphics","z":"7f1827bd.8acfe8","group":"d4b5416a.9c25f","order":1,"width":"14","height":"10","svgString":"<svg preserveAspectRatio=\"none\" x=\"0\" y=\"0\" viewBox=\"0 0 900 710\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n  <circle id=\"sensor_a\" cx=\"50\" cy=\"50\" r=\"20\" stroke-width=\"0\" fill=\"#FF0000\" />\n</svg> ","clickableShapes":[{"targetId":"#camera_living","action":"click","payload":"camera_living","payloadType":"str","topic":"camera_living"}],"javascriptHandlers":[],"smilAnimations":[],"bindings":[{"selector":"#banner","bindSource":"payload.title","bindType":"text","attribute":""},{"selector":"#camera_living","bindSource":"payload.position.x","bindType":"attr","attribute":"x"},{"selector":"#camera_living","bindSource":"payload.camera.colour","bindType":"attr","attribute":"fill"}],"showCoordinates":false,"autoFormatAfterEdit":false,"showBrowserErrors":true,"showBrowserEvents":false,"enableJsDebugging":false,"sendMsgWhenLoaded":false,"outputField":"","editorUrl":"http://drawsvg.org/drawsvg.html","directory":"","panning":"disabled","zooming":"disabled","panOnlyWhenZoomed":false,"doubleClickZoomEnabled":false,"mouseWheelZoomEnabled":false,"dblClickZoomPercentage":"150","name":"","x":1100,"y":2020,"wires":[[]]},{"id":"d4b5416a.9c25f","type":"ui_group","z":"","name":"Floorplan test","tab":"b9052fac.2b0e9","order":1,"disp":true,"width":"14","collapse":false},{"id":"b9052fac.2b0e9","type":"ui_tab","z":"","name":"SVG","icon":"dashboard","disabled":false,"hidden":false}]

When you update your Node-RED settings to store the context memory, the context memory will automatically be restored after a restart (so your sensor values will be remembered)...

tkirchm commented 3 years ago

It has nothing to do with memory and global. On the long run this information will come from storage or sensors but right now its just how to manipulate an existing path. [{"id":"e3cb5f80.1488a","type":"function","z":"b7209503.a11f58","name":"SetAttribute","func":"if (msg.topic == \"get_attribute\") {\n//msg should also contain old msg.payload to determine what was aked for\n\nvar str = msg.payload // output of get_attribute\n\nvar regex = /[a-z][^a-z]*/ig;\nvar sa = str.match(regex);\nsa[1] = \"v50\" //get from external IO from global or direct via msg\nvar s = sa.join('')\n\nmsg.payload = {\n \"command\": \"set_attribute\", //information from get_attribute\n \"selector\": \"#Rs_EsstischStatus\", //information from get_attribute\n \"attributeName\": \"d\",\n \"attributeValue\": s\n}\nreturn msg;\n}","outputs":1,"noerr":0,"x":770,"y":960,"wires":[["6daff55a.61039c"]]},{"id":"6daff55a.61039c","type":"ui_svg_graphics","z":"b7209503.a11f58","group":"d6a8741e.15ed58","order":4,"width":"30","height":"15","svgString":"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0\" y=\"0\" height=\"700\" viewBox=\"0 -0.09671179950237274 1500 700.1934204101562\" width=\"1500\" preserveAspectRatio=\"xMidYMid meet\"><rect id=\"svgEditorBackground\" x=\"0\" y=\"-0.09671179205179214\" width=\"1500\" height=\"700.1934204101562\" style=\"fill: none; stroke: none;\"/>\n <path d=\"M256.409,423.964v48\" style=\"fill:none;stroke:darkturquoise;stroke-width:30;\" id=\"Rs_EsstischStatus\"/>\n<rect x=\"237.671\" y=\"420.019\" style=\"stroke: black; stroke-width: 1px;fill:none;\" id=\"e1_rectangle\" width=\"37.475\" height=\"56.213\"/></svg>","clickableShapes":[{"targetId":"[id^=\"Li_\"]","action":"click","payload":"EG","payloadType":"str","topic":"[id^=\"Li_\"]"},{"targetId":"[id^=\"Rs_\"]","action":"click","payload":"[id^=\"Rs_\"]","payloadType":"str","topic":"[id^=\"Rs_\"]"},{"targetId":"[id^=\"Ro_\"]","action":"click","payload":"[id^=\"Ro_\"]","payloadType":"str","topic":"[id^=\"Ro_\"]"}],"javascriptHandlers":[],"smilAnimations":[],"bindings":[],"showCoordinates":false,"autoFormatAfterEdit":false,"showBrowserErrors":false,"showBrowserEvents":false,"enableJsDebugging":false,"sendMsgWhenLoaded":false,"outputField":"payload","editorUrl":"http://drawsvg.org/drawsvg.html","directory":"","panning":"disabled","zooming":"disabled","panOnlyWhenZoomed":false,"doubleClickZoomEnabled":false,"mouseWheelZoomEnabled":false,"dblClickZoomPercentage":"150","name":"Test","x":550,"y":900,"wires":[["e3cb5f80.1488a"]]},{"id":"f137e58e.9e54a8","type":"comment","z":"b7209503.a11f58","name":"length of path","info":"","x":420,"y":820,"wires":[]},{"id":"ddc7e600.8be538","type":"function","z":"b7209503.a11f58","name":"get_atribute","func":"msg.payload = {\n \"command\": \"get_attribute\",\n \"selector\": \"#Rs_EsstischStatus\",\n \"attributeName\": \"d\",\n}\nreturn msg;","outputs":1,"noerr":0,"x":390,"y":900,"wires":[["6daff55a.61039c"]]},{"id":"d6a8741e.15ed58","type":"ui_group","z":"","name":"WZ","tab":"6cb18d06.187a14","order":1,"disp":true,"width":"100","collapse":true},{"id":"6cb18d06.187a14","type":"ui_tab","z":"","name":"Plan","icon":"dashboard","disabled":false,"hidden":false}] For presistant memory I prefer Postgres as it is running on my raspi anyway.

bartbutenaers commented 3 years ago

@tkirchm,

I have added a new section to the readme.

You can now replace parts of an attribute value via an msg.

Here is your flow:

image

[{"id":"6daff55a.61039c","type":"ui_svg_graphics","z":"7f1827bd.8acfe8","group":"d6a8741e.15ed58","order":4,"width":"30","height":"15","svgString":"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0\" y=\"0\" height=\"700\" viewBox=\"0 -0.09671179950237274 1500 700.1934204101562\" width=\"1500\" preserveAspectRatio=\"xMidYMid meet\"><rect id=\"svgEditorBackground\" x=\"0\" y=\"-0.09671179205179214\" width=\"1500\" height=\"700.1934204101562\" style=\"fill: none; stroke: none;\"/>\n <path d=\"M256.409,423.964v48\" style=\"fill:none;stroke:darkturquoise;stroke-width:30;\" id=\"Rs_EsstischStatus\"/>\n<rect x=\"237.671\" y=\"420.019\" style=\"stroke: black; stroke-width: 1px;fill:none;\" id=\"e1_rectangle\" width=\"37.475\" height=\"56.213\"/></svg>","clickableShapes":[{"targetId":"[id^=\"Li_\"]","action":"click","payload":"EG","payloadType":"str","topic":"[id^=\"Li_\"]"},{"targetId":"[id^=\"Rs_\"]","action":"click","payload":"[id^=\"Rs_\"]","payloadType":"str","topic":"[id^=\"Rs_\"]"},{"targetId":"[id^=\"Ro_\"]","action":"click","payload":"[id^=\"Ro_\"]","payloadType":"str","topic":"[id^=\"Ro_\"]"}],"javascriptHandlers":[],"smilAnimations":[],"bindings":[],"showCoordinates":false,"autoFormatAfterEdit":false,"showBrowserErrors":false,"showBrowserEvents":false,"enableJsDebugging":false,"sendMsgWhenLoaded":false,"outputField":"payload","editorUrl":"http://drawsvg.org/drawsvg.html","directory":"","panning":"disabled","zooming":"disabled","panOnlyWhenZoomed":false,"doubleClickZoomEnabled":false,"mouseWheelZoomEnabled":false,"dblClickZoomPercentage":"150","name":"Test","x":510,"y":2620,"wires":[[]]},{"id":"982109e1.78d568","type":"inject","z":"7f1827bd.8acfe8","name":"Replace","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"command\":\"replace_attribute\",\"selector\":\"#Rs_EsstischStatus\",\"attributeName\":\"d\",\"regex\":\"[a-z][^a-z]*\",\"replaceValue\":\"v20\"}","payloadType":"json","x":340,"y":2620,"wires":[["6daff55a.61039c"]]},{"id":"337fbd68.322d82","type":"inject","z":"7f1827bd.8acfe8","name":"Replace all","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"command\":\"replace_all_attribute\",\"selector\":\"#Rs_EsstischStatus\",\"attributeName\":\"d\",\"regex\":\"[a-z][^a-z]*\",\"replaceValue\":\"v20\"}","payloadType":"json","x":340,"y":2660,"wires":[["6daff55a.61039c"]]},{"id":"d6a8741e.15ed58","type":"ui_group","z":"","name":"WZ","tab":"6cb18d06.187a14","order":1,"disp":true,"width":"100","collapse":true},{"id":"6cb18d06.187a14","type":"ui_tab","z":"","name":"Plan","icon":"dashboard","disabled":false,"hidden":false}]

You can install the Github version within your .node-red folder:

npm install bartbutenaers/node-red-contrib-ui-svg
tkirchm commented 3 years ago

works great. Thanks.