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

Two animations for the same element lead to unexpected behavior #119

Open Luar78 opened 1 year ago

Luar78 commented 1 year ago

Hi. Here is the problem I have encountered. I have created two animations for a line "RailR2". The first animation should do a running light to the right and the second animation a running light to the left by the attribute "stroke-dashoffset". image

image

If I start both animations by two input message, then the animations block each other and the line stops and does not move. Although I send more "input message" to stop the animations and then to start them, I can't get the animations to run. Apparently there is no way to check if a certain animation is active to stop it specifically before starting the opposite one.

I am currently using node-red 3.0.2 node-red-dashboard 3.4.0 node-red-contrib-ui-svg 2.3.1

bartbutenaers commented 1 year ago

Hi @Luar78,

It is not entirely clear to me which final visual effect you want to achieve, but here are a few options that 'might' be of any help to you.

  1. Via a custom trigger you can automatically start an animation as soon as another animation ends:
    [{"id":"d54f1a5a3741a707","type":"ui_svg_graphics","z":"6de43ccfaf136eb5","group":"1cadf43404b693ab","order":1,"width":"6","height":"5","svgString":"<svg x=\"0\" y=\"0\" height=\"100\" viewBox=\"0 0 100 100\" width=\"100\" 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=\"my_circle\" fill=\"#ED1C24\" cx=\"50\" cy=\"50\" r=\"25\">\n  </circle>\n</svg>","clickableShapes":[],"javascriptHandlers":[],"smilAnimations":[{"id":"first_animation","targetId":"my_circle","classValue":"","attributeName":"r","transformType":"rotate","fromValue":"25","toValue":"5","trigger":"msg","duration":"4","durationUnit":"s","repeatCount":"1","end":"freeze","delay":"1","delayUnit":"s","custom":""},{"id":"second_animation","targetId":"my_circle","classValue":"","attributeName":"r","transformType":"rotate","fromValue":"5","toValue":"25","trigger":"cust","duration":"3","durationUnit":"s","repeatCount":"1","end":"freeze","delay":"1","delayUnit":"s","custom":"first_animation.end"}],"bindings":[],"showCoordinates":false,"autoFormatAfterEdit":false,"showBrowserErrors":false,"showBrowserEvents":false,"enableJsDebugging":false,"sendMsgWhenLoaded":false,"noClickWhenDblClick":false,"outputField":"payload","editorUrl":"//drawsvg.org/drawsvg.html","directory":"","panning":"disabled","zooming":"disabled","panOnlyWhenZoomed":false,"doubleClickZoomEnabled":false,"mouseWheelZoomEnabled":false,"dblClickZoomPercentage":150,"cssString":"div.ui-svg svg{\n    color: var(--nr-dashboard-widgetColor);\n    fill: currentColor !important;\n}\ndiv.ui-svg path {\n    fill: inherit;\n}","name":"","_mcu":{"mcu":false},"x":700,"y":620,"wires":[[]]},{"id":"4c79f586172f0460","type":"inject","z":"6de43ccfaf136eb5","name":"Start first animation","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"command\":\"trigger_animation\",\"selector\":\"#first_animation\",\"action\":\"start\"}","payloadType":"json","_mcu":{"mcu":false},"x":450,"y":620,"wires":[["d54f1a5a3741a707"]]},{"id":"1cadf43404b693ab","type":"ui_group","name":"Default","tab":"6f7c4e0d64141bac","order":1,"disp":true,"width":"6","collapse":false,"className":"","_mcu":{"mcu":false}},{"id":"6f7c4e0d64141bac","type":"ui_tab","name":"Animation demo","icon":"dashboard","disabled":false,"hidden":false,"_mcu":{"mcu":false}}]
  2. You can inject in the input message an array of 2 commands, i.e. start stop an animation and start another animation:

    image

    [{"id":"d54f1a5a3741a707","type":"ui_svg_graphics","z":"6de43ccfaf136eb5","group":"1cadf43404b693ab","order":1,"width":"6","height":"5","svgString":"<svg x=\"0\" y=\"0\" height=\"100\" viewBox=\"0 0 100 100\" width=\"100\" 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=\"my_circle\" fill=\"#ED1C24\" cx=\"50\" cy=\"50\" r=\"25\">\n  </circle>\n</svg>","clickableShapes":[],"javascriptHandlers":[],"smilAnimations":[{"id":"first_animation","targetId":"my_circle","classValue":"","attributeName":"r","transformType":"rotate","fromValue":"25","toValue":"5","trigger":"msg","duration":"4","durationUnit":"s","repeatCount":"1","end":"freeze","delay":"1","delayUnit":"s","custom":""},{"id":"second_animation","targetId":"my_circle","classValue":"","attributeName":"r","transformType":"rotate","fromValue":"5","toValue":"25","trigger":"msg","duration":"3","durationUnit":"s","repeatCount":"1","end":"freeze","delay":"1","delayUnit":"s","custom":""}],"bindings":[],"showCoordinates":false,"autoFormatAfterEdit":false,"showBrowserErrors":false,"showBrowserEvents":false,"enableJsDebugging":false,"sendMsgWhenLoaded":false,"noClickWhenDblClick":false,"outputField":"payload","editorUrl":"//drawsvg.org/drawsvg.html","directory":"","panning":"disabled","zooming":"disabled","panOnlyWhenZoomed":false,"doubleClickZoomEnabled":false,"mouseWheelZoomEnabled":false,"dblClickZoomPercentage":150,"cssString":"div.ui-svg svg{\n    color: var(--nr-dashboard-widgetColor);\n    fill: currentColor !important;\n}\ndiv.ui-svg path {\n    fill: inherit;\n}","name":"","_mcu":{"mcu":false},"x":1000,"y":620,"wires":[[]]},{"id":"4c79f586172f0460","type":"inject","z":"6de43ccfaf136eb5","name":"Stop second animation and start first animation","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"command\":\"trigger_animation\",\"selector\":\"#second_animation\",\"action\":\"stop\"},{\"command\":\"trigger_animation\",\"selector\":\"#first_animation\",\"action\":\"start\"}]","payloadType":"json","_mcu":{"mcu":false},"x":680,"y":620,"wires":[["d54f1a5a3741a707"]]},{"id":"fa2191985480e250","type":"inject","z":"6de43ccfaf136eb5","name":"Stop first animation and start second animation","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"command\":\"trigger_animation\",\"selector\":\"#first_animation\",\"action\":\"stop\"},{\"command\":\"trigger_animation\",\"selector\":\"#second_animation\",\"action\":\"start\"}]","payloadType":"json","_mcu":{"mcu":false},"x":680,"y":660,"wires":[["d54f1a5a3741a707"]]},{"id":"1cadf43404b693ab","type":"ui_group","name":"Default","tab":"6f7c4e0d64141bac","order":1,"disp":true,"width":"6","collapse":false,"className":"","_mcu":{"mcu":false}},{"id":"6f7c4e0d64141bac","type":"ui_tab","name":"Animation demo","icon":"dashboard","disabled":false,"hidden":false,"_mcu":{"mcu":false}}]

Bart

Luar78 commented 1 year ago

Hello Bart. I use Node Red to visualize the energy flow of my solar system in the RV. As a trigger, measured values from my Victron components are used which are integrated in Node Red. There are lines that move only in one direction or are off and there are lines (like the rail in the middle) that move to the left or right.

image

The corresponding animation is started with infinite cycles. As soon as the measured values of the Victron components show a different flow, the animations are stopped accordingly and others are started. Because of the different measured values, the calls to start and stop the animation overlapped. To avoid this problem I inserted a "Delay Block" which allows only one message per second to pass. This makes the visualization less responsive, but at least there is no freez in the animation.

Raul.

bartbutenaers commented 1 year ago

Hi @Luar78,

Thanks for sharing your project. That makes it much more clear. Nice setup! Yes indeed it might be better to aggregate the measurements, and inject messages to the svg at regular intervals like you do.

Did I understand correctly that this issue is solved? Bart

Luar78 commented 1 year ago

Hi @bartbutenaers. The problem is not really solved, but I avoid it by reducing the number of messages. Thank you very much.

Raul.