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

getting control of elements wihtin "templates" / symbols #89

Open JoeWiseman opened 3 years ago

JoeWiseman commented 3 years ago

Hi there,

first of all I'm very impressed by this great work. I've been searching around for a SCADA-like GUI and finally find your node.... Exactly what I've been searching for!

The situation: I like to use templates for some elements like "roller blinds" or "power plugs". Both include a rectangular background, some texts and of course some "pickable" symbols. In the case of an power plug it is "only" one circle (LED) in case of a roller blind there are two arrows (one for up, one for down).

When inserting those groups as plain text for each element the LED (for a power plug) is getting an unique id (for each power plug), so that I can add an event within the nodes Event-tab.

When using / and inserting the element by I just can give an id to the entire symbol, but cannot access the LED wihtin this symbol....

So now is the question if it is possbile anyway to get control of an element wihtin a template / symbol?

Would be great to get some hints about that.

Regards Joe

Steve-Mcl commented 3 years ago

Hi. You should be able to use defs and use...

http://tutorials.jenkov.com/svg/use-element.html#:~:text=The%20SVG%20element%20can,invisible%20until%20used)%20or%20outside.

JoeWiseman commented 3 years ago

Hi @Steve-Mcl

thanks for answering so fast .... Unfortunately thats exactly what I've described in my post.... Maybe I try to refine the problem:

given is a SVG-file with the following <symbol id="MyPlug"> <rect id="MyBackground" x="0" y="0" width="100" height="50" rx="10" fill="url(#FarbeHintergrund)" stroke-width="2px" stroke="url(#FarbeRahmen)" paint-order="fill"/> <circle id="MyLED" cx="87" cy="13" r="10" fill="url(#FarbeLEDaus)" stroke="transparent"/> <text id="MyDescription1" x="6" y="20" fill="url(#FarbeText)" font-size="15px" font-family="Arial" line-height="1" letter-spacing="0px" word-spacing="0px"> Description Text Line 1 </text> <text id="MyDescription2" x="6" y="40" fill="url(#FarbeText)" font-size="15px" font-family="Arial" line-height="1" letter-spacing="0px" word-spacing="0px"> Description Text Line 2 </text> </symbol> Note: The colors #FarbeHintergrund, #FarbeRahmen, #FarbeText, #FarbeLEDaus were allready defined before defining the symbol itself.

Now I'm able to use (visualize) the symbol e.g.: <use id="Plug1" xlink:href="#MyPlug" transform="translate(75, 0)"/> <use id="Plug2" xlink:href="#MyPlug" transform="translate(75, 0)"/>

When adding an Event on the SVG-node I'm able to use:

MyPlug, #MyBakcgroud, #MyDescription1, #MyDescription2 and #MyLED (all given by the -definition)

Also availible are #Plug1 and #Plug2, but nothing like: #Plug1.MyLED, #Plug1.Description1 or #Plug2.MyLED

The aim is to change the style (especially the color) of the LED and some Text (for actual values) in the Description1/2 .... ...but I don't know if this is possible at all?

Best regards Joe

Steve-Mcl commented 3 years ago

Ah ok, well...

There is no simple way to do what you want. The inherent nature of defs and use elements dictates that sub-elements within an original defs element cannot be manipulated individually in use elements derived from it. To do so would require that each use element have a separate copy of each sub-element. That would defeat one of the purposes of the defs/use partnership, i.e. to save memory.

However, while you cannot change the attributes of one specific sub-element in a use element, you can change the attributes of all of the sub-elements in a use element at one time (not entirely desirable)

There are 2 solutions...

  1. You duplicate the objects (not ideal but a solution none the less)
  2. We implement something inside the node like an "expand" method that generates full elements and replaces the use elements (at run time) - this is not likely to be picked up any time soon (by me anyway - I am sure Bart will comment soon)
JoeWiseman commented 3 years ago

That's exactley the answer I didn't want to hear :-D

Well, I think there's nothing much to add ....

Just another small question, although it is not directly dealing with the current topic: When coding my GUI elements within an SVG I need two range-slider to be shown, when I click on the element. E.g. there is a slats roller shutter outside element. It contains a icon for UP, one for DOWN, one for ROTATE (switch between 90° / 180°) for which the Click-Events are clearly described in the node reference. Additionally there is an Window-Icon. If I click on that Icon I want two Range-Slider to "pop up" so that I'm able to set the exact height and the exact angle of the slats.

Now is the question how to code this behaviuor ... ... by setting up an "more-complex-SVG"? ... or using Java?

What is your tip?

Regards Joe

bartbutenaers commented 3 years ago

Hi Joe, Will get back to you later on, for more details.

Had no time to try your example yet, but can't you use CSS variables inside your symbol? And then every time you use the symbol, you pass other other color values. Here you can find an example and some explanation.

About the slider: you want a popup window? Or a slider popping up somewhere else in your dashboard? Bart

JoeWiseman commented 3 years ago

Hi @bartbutenaers,

thanks for answering. I will have a closer look to the given example later on. I saw a similar video on youtube about the dashboard-slider controlling a roboter-like gripper.

If I am using the native dashboard I have to chage the tabs every time I like to set the value. It would be more comfortable to get an popup "near" the widget.

Best regards Joe

Actually thas what I've figured out my GUI elements so far (only internal SVG-animations) that the user gets feedback: AnimatedIconsAndTemplates