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

Mechanism to exchange 'widgets' #12

Open bartbutenaers opened 4 years ago

bartbutenaers commented 4 years ago

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 commented 4 years ago

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:

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 commented 4 years ago

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

Steve-Mcl commented 4 years ago

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 commented 4 years ago

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

... 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
bartbutenaers commented 4 years ago

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:

Other ideas?

Steve-Mcl commented 4 years ago

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 commented 4 years ago

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?