node-red-contrib-ui-svg icon indicating copy to clipboard operation
node-red-contrib-ui-svg copied to clipboard

Mechanism to exchange 'widgets'

Open bartbutenaers opened this issue 6 years ago • 7 comments

When somebody creates e.g. a nice SVG animation (e.g. sprinkler rotating with water), it would be nice if we could share this somehow...

Perhaps somehow with SVG definitions???

<svg>
  <defs>
    <!-- Some shared stuff (grouped in a group element) -->
    <g id="shared_sprinkler_widget">
        ...
    </g>
  </defs>
 
   <!-- The user can use the shared stuff -->
  <use x="5" y="5" xlink:href="#shared_sprinkler_widget" />
</svg>

[EDIT 19/8] For Inkscape they use symbols containing a single path, which is being used to draw all required shapes. But I would like to have multiple shapes, each with their own customizable attributes. Perhaps CSS variables can solve this, like here explained.

bartbutenaers avatar Aug 17 '19 22:08 bartbutenaers

Suppose somebody has developed a "sprinkler" svg widget, to visualize water spraying his lawn. Such a widget will have properties, e.g. a sprinkler will typically have following properties:

  • Radius
  • Start angle
  • Spray angle

Would be nice if the users can specify these properties, without having to change the svg shapes used for this widget. Seems to me that this can be achieved using CSS variables.

In the following sprinkler demo, the spray angle is a CSS variable "--spray-angle" which can have different values every time the widget is being used:

<svg class="progress" width="2000" height="400" >
	<defs>
	  <g id="sprinkler" transform="rotate(-10 50 100)"">
		  <circle cx="0" cy="0" r="10" fill="black" stroke="none" />
		  <circle cx="0" cy="0" r="57" fill="none" stroke="lightblue" stroke-width="60" stroke-dasharray="360" stroke-dashoffset="calc(360 - var(--spray-angle))"/>
	  </g>
  </defs>
	
	<use xlink:href="#sprinkler" href="#sprinkler" x="150" y="100" style="--spray-angle:90;"/>
	<use xlink:href="#sprinkler" href="#sprinkler" x="350" y="100" style="--spray-angle:180;"/>
</svg>

Resulting in this:

image

Now we need to figure out how to share those widget 'group' elements between users (just copy paste, or make them available via our repository, or via our node somehow ...)

bartbutenaers avatar Sep 09 '19 06:09 bartbutenaers

P.S. I also tried to add a '--start-angle' property, but for some reason that doesn't work:

<svg class="progress" width="2000" height="400" >
    <defs>
        <g id="sprinkler" transform="rotate(var(--start-angle))"">
            <circle cx="0" cy="0" r="10" fill="black" stroke="none" />
            <circle cx="0" cy="0" r="57" fill="none" stroke="lightblue" stroke-width="60" stroke-dasharray="360" stroke-dashoffset="calc(360 - var(--spray-angle))"/>
        </g>
    </defs>
	
    <use xlink:href="#sprinkler" href="#sprinkler" x="150" y="100" style="--spray-angle:90;--start-angle:45"/>
    <use xlink:href="#sprinkler" href="#sprinkler" x="350" y="100" style="--spray-angle:180;--start-angle:0"/>
</svg>

Have also tried a default value rotate(var(--start-angle, 0)) (which should work following this article), but no success ...

Got following error in the Chrome console log:

image

bartbutenaers avatar Sep 09 '19 08:09 bartbutenaers

Hi bart, this works for me...

<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="none" x="0" y="0" viewBox="0 0 900 710" width="100%" height="100%">
    <defs>
        <g id="sprinkler" transform="rotate(var(--start-angle))">
            <circle cx="0" cy="0" r="10" fill="black" stroke="none" />
            <circle cx="0" cy="0" r="57" fill="none" stroke="lightblue" stroke-width="60" stroke-dasharray="360" stroke-dashoffset="calc(360 - var(--spray-angle))"/>
        </g>
    </defs>
    <use xlink:href="#sprinkler" href="#sprinkler" x="150" y="100" style="--spray-angle:90;--start-angle:45"/>
    <use xlink:href="#sprinkler" href="#sprinkler" x="350" y="100" style="--spray-angle:180;--start-angle:0"/>
</svg>

Perhaps the double quote transform="rotate(var(--start-angle))""> was the issue or the missing xlink directives in the SVG element?

Now we need to figure out how to share those widget 'group' elements between users (just copy paste, or make them available via our repository, or via our node somehow

For many environments being isolated / offline, a local repository would be good however this is gonna take some doing. We could simplify this in V1 by having a JSON file containing items.

e.g.

{
  "sprinker": {
    "defs" : "the defs to include in the defs section"
    "elements" : "the elements to include"
    "vars" {
      "--spray-angle": { "type": "integer", "min": 0, "max:359}
    }
  }
}

.. then a user could at least add his own (albeit without a fancy editor or perhaps an ace instance to permit JSON editing of the widgets)

future... Perhaps make use of github gists for a public repository which can perhaps be sync'd down to the node-red installation for new and future widgets?

Again, I hope I have at least provided a :bulb: moment for us :slightly_smiling_face:

Steve-Mcl avatar Sep 09 '19 09:09 Steve-Mcl

Hi bart, this actually doesnt works for me (sorry)...

<defs>
    <g id="sprinkler" transform="rotate(var(--start-angle))">
        <circle cx="0" cy="0" r="10" fill="black" stroke="none" />
        <circle cx="0" cy="0" r="57" fill="none" stroke="lightblue" stroke-width="60" stroke-dasharray="360" stroke-dashoffset="calc(360 - var(--spray-angle))"/>
    </g>
</defs>
<use xlink:href="#sprinkler" href="#sprinkler" x="150" y="100" style="--spray-angle:90;--start-angle:45"/>
<use xlink:href="#sprinkler" href="#sprinkler" x="350" y="100" style="--spray-angle:180;--start-angle:0"/>

... I get the same error in chrome dev tools.

Another thought on how to provide a library of widgets... It is possible to specify an SVG file and an ID e.g.

<use xlink:href="resources/widgets.svg#sprinkler"></use>

..so perhaps we could have a resources directory with a collection of SVGs or a master SVG with multiple ID'd widgets? We could enumerate the widgets, provide a multi-level dropdown menu (with svg previews in-line?) to "Insert at cursor" when selected?

e.g.

└Symbols
  └ lamp.svg
  └ switch.svg
└Icons
  └ telgram.svg
  └ facebook.svg

Steve-Mcl avatar Sep 09 '19 11:09 Steve-Mcl

Hi Steve, But people that only use DrawSVG (so no manual coding in the SVG Source tabsheet), should also have these widgets at their disposal. So we need to send those widgets to DrawSvg, to make sure you can use them there. Suppose:

  • We create an extra tabsheet 'Widgets' where you can select widgets (e.g. your json files). Perhaps those files should be included in our npm package, for installations without internet access?

  • The user adds in that tabsheet a row for 'sprinkler'.

  • The group-element of the sprinkler will automatically be added to the defs-element in the SVG source (or a sub-svg like you propose).

  • But I'm not sure whether you select those sub-svg's in DrawSvg, because this seems to be the only option:

    image

Other ideas?

bartbutenaers avatar Sep 09 '19 20:09 bartbutenaers

I wonder, does the clipboard allow pasting of SVG code? if so, we could have our own toolbar to insert into the editor?

Steve-Mcl avatar Sep 09 '19 21:09 Steve-Mcl

we could see if it is possible to add a custom library like the libraries already in DrawSVG? not sure how or if possible. perhaps contact the author?

Steve-Mcl avatar Sep 09 '19 21:09 Steve-Mcl