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

Easy way to publish SVG images #1

Open bartbutenaers opened 5 years ago

bartbutenaers commented 5 years ago

When using an SVG 'image' element, a source image needs to be specified.

For example:

<svg ...>
  <image ... xlink:href="https://www.roomsketcher.com/wp-content/uploads/2016/10/1-Bedroom-Floor-Plans.jpg"/>
</svg>

Would like to have an easy way to make local images available. But how? And should it be possible to push the images (as a base64 string) via an input message?

boisei0 commented 5 years ago

Bart, brainstorming here without thinking of the memory footprint just yet. Could you define an endpoint on Node-RED where (temporary) images are made available, or even converted from a base64 incoming message? Then that URL to be put in the image source.

QuagmireMan commented 5 years ago

Is Inkscape something you would consider easy? This is how some of the other home automation groups generate SVGs.

https://community.openhab.org/t/design-your-svg-floorplan-or-dashboard-for-habpanel-with-inkscape/38441

https://inkscape.org/

Or were you trying to keep it local with a web interface? Maybe something like this could be run local: https://editor.method.ac/

bartbutenaers commented 5 years ago

Hi @QuagmireMan,

Thanks for your feedback! Have read that openhab article of couple of weeks ago, and that was for me indeed an indication that the svg-based node was a good way to design my floorplans in Node-RED.

But could it be that your feedback is more related to this issue? I will answer you there, to keep things separated... Bart

bartbutenaers commented 5 years ago

@Steve-Mcl , I think this issue has become worse due to our third party editor(s) integration: In our demos we use a public available background image. But suppose I have created a background image of my house, which I don't want to publish to the whole world. How can I refer to a private image in my SVG editor and script editor?

About the latter option:

But not sure how this works:

bartbutenaers commented 5 years ago

When the user adds a local image using the DrawSVG online editor:

drawsvg_image

Then we see that this image also has been inserted by DrawSVG into the SVG as base64 string:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1130px" height="660px" viewBox="0 0  1130 660" preserveAspectRatio="xMidYMid meet" >
     <rect id="svgEditorBackground" x="0" y="0" width="1130" height="660" style="fill: none; stroke: none;"/>
     <image x="216" y="128" width="362" height="334.287" id="e1_image" preserveAspectRatio="xMidYMid meet" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAnMAAAJDCAIAAADvqAX..." style="stroke:black;stroke-width:1px;fill:rosybrown;"/>
</svg>

From this I conclude that we should do something similar: When a local file is being added manually to the SVG source xlink:href="file:///some_local_file_path"), then we should load it automatically into a base64 string (before we load it into the external drawing editor).

Remark: when returning back from the external SVG editor, the original local path should be restored somehow (since we don't want to store the base64 string into Node-RED's flow.json file).

Steve-Mcl commented 5 years ago

Remark: when returning back from the external SVG editor, the original local path should be restored somehow (since we don't want to store the base64 string into Node-RED's flow.json file).

Hi Bart, this is certainly possible (can easily temporarily store the path in a custom attribute) however when the SVG is served in dashboard, the image file:// may not be accessible in the browser (certainly not on a remote browser)

Options I can think of are (ranked from easiest to hardest)...

Hopefully this feedback gives you a :bulb: moment

bartbutenaers commented 5 years ago

Hey Steve, I have also been thinking about an extra 'images' tabsheet, but not sure if that can help us. Users can specify a path to an image (which can be available local or online) both in DrawSvg and manually in the 'Source' tab of our node, and the dashboard needs to be able to access the image.

I think the following situations are possible:

1 - Online image

image

  1. The user adds in the SVG source a hyperlink to an online image. Note that the user can also select such a hyperlink via drawsvg.
  2. The exported SVG will contain the hyperlink.
  3. DrawSVG can load the image from the cloud and display it.
  4. The imported SVG will contain the hyperlink.
  5. The SVG with the hyperlink will be send to the dashboard, which can show it.

Caution: if the dashboard has no internet access, the image cannot be displayed. So we could convert the hyperlink to a base64 string, before sending the SVG to the dashboard. But of course that is only possible when the Node-RED flow can access the internet ... Don't think there is a waterproof solution and it is best to put on the readme page that local images should be used in these kind of situations.

2 - Link to local image

image

  1. The user can use a link (file:///...) to a local image in his SVG source tabsheet.
  2. The exported SVG will contain the local link.
  3. DrawSVG cannot access the local image via the link, so the image cannot be displayed.

This can be solved by doing it another way:

  1. The user can use a link (file:///...) to a local image in his SVG source tabsheet.
  2. The exported SVG will contain a base64 string representation of the local image. So the svg-node will automatically load all local files and convert them to base64 (and store the local link into a data-attribute). This is conversion C1.
  3. DrawSVG can display the base64 string as image.
  4. The imported SVG will contain the base64 string (and the local link in a data-attribute). The svg-node will remove the base64 string and replace it again by the local link. This is conversion C2.
  5. The base64 string will again be created to send the SVG to the Node-RED dashboard, since the dashboard cannot access the local link.

3 - Included local image

image

  1. No image has been added manually via the SVG source tabsheet (since this user solely uses DrawSVG).
  2. The user can load a local image (via a file explorer popup) into DrawSVG, so a base64 encoded string of that image will be included into the svg.
  3. The imported SVG will contain the base64 string. P.S. since there is no data-attribute containing a local link, the base64 string will be left untouched.
  4. The base64 string will be send to the dashboard, as part of the SVG.

4 - User overwrites a local image (Special case)

image

  1. The user adds a link to a local image via the SVG source tabsheet.
  2. The exported SVG will contain a base64 string representation of the local image (and the local link in a data-attribute).
  3. DrawSVG will display the image, but the user decides to load another local image into the same image shape.
  4. The imported SVG string will contain the base64 string of the new image and the link to the old local image (in a data-attribute). Our svg-node must NOT replace the new image by the old local link! Think we can only solve this by comparing the base64 of the local link image and the base64 string in the imported SVG. When both strings are different, the base64 string should remain untouched in the svg (and the data-attribute with the local link should be removed).

We will only need an endpoint to get the base64 string of a specified local image file ...