Skip to content
This repository has been archived by the owner on Aug 10, 2024. It is now read-only.

Managing multiple floors

bartbutenaers edited this page Dec 7, 2020 · 1 revision

When you want to display multiple floors, the screen is not always big enough to show all the floors at once.

This page describes a couple of ways to solve this problem, each with their advantages and disadvantages...

Use multiples SVG nodes

Use a separate SVG node for each floorplan, and then show or hide those nodes.

This can be be implemented for example using collapsible groups:

Separate nodes

[{"id":"8571d058.370b1","type":"ui_svg_graphics","z":"42b7b639.325dd8","group":"e97fb24c.c24d","order":1,"width":"7","height":"5","svgString":"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"340px\" height=\"240px\" viewBox=\"0 0 340 240\" preserveAspectRatio=\"xMinYMin meet\">\n  <rect x=\"20\" y=\"20\" width=\"300\" height=\"150\" style=\"fill:yellowgreen;stroke:black;stroke-width:1px;fill-opacity:50%;\"/>\n  <text style=\"fill:forestgreen;font-size:30px;font-weight:bold;\" x=\"70\" y=\"100\">Ground floor</text>\n</svg>","clickableShapes":[{"targetId":"#cam_living_icon","action":"click","payload":"toggle","payloadType":"str","topic":"#cam_living_video"},{"targetId":"#cam_garage_icon","action":"click","payload":"toggle","payloadType":"str","topic":"#cam_garage_video"}],"javascriptHandlers":[],"smilAnimations":[],"bindings":[],"showCoordinates":false,"autoFormatAfterEdit":false,"showBrowserErrors":true,"showBrowserEvents":false,"enableJsDebugging":false,"sendMsgWhenLoaded":false,"outputField":"","editorUrl":"http://drawsvg.org/drawsvg.html","directory":"","panning":"disabled","zooming":"disabled","panOnlyWhenZoomed":false,"doubleClickZoomEnabled":false,"mouseWheelZoomEnabled":false,"name":"Ground floor","x":310,"y":1200,"wires":[[]]},{"id":"e101435.3da2ec","type":"ui_svg_graphics","z":"42b7b639.325dd8","group":"8af2dd4a.30827","order":1,"width":"7","height":"5","svgString":"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"340px\" height=\"240px\" viewBox=\"0 0 340 240\" preserveAspectRatio=\"xMinYMin meet\">\n  <rect x=\"20\" y=\"20\" width=\"300\" height=\"150\" style=\"fill:moccasin;stroke:black;stroke-width:1px;fill-opacity:50%;\"/>\n  <text style=\"fill:peru;font-size:30px;font-weight:bold;\" x=\"90\" y=\"100\">First floor</text>\n</svg>","clickableShapes":[{"targetId":"#cam_living_icon","action":"click","payload":"toggle","payloadType":"str","topic":"#cam_living_video"},{"targetId":"#cam_garage_icon","action":"click","payload":"toggle","payloadType":"str","topic":"#cam_garage_video"}],"javascriptHandlers":[],"smilAnimations":[],"bindings":[],"showCoordinates":false,"autoFormatAfterEdit":false,"showBrowserErrors":true,"showBrowserEvents":false,"enableJsDebugging":false,"sendMsgWhenLoaded":false,"outputField":"","editorUrl":"http://drawsvg.org/drawsvg.html","directory":"","panning":"disabled","zooming":"disabled","panOnlyWhenZoomed":false,"doubleClickZoomEnabled":false,"mouseWheelZoomEnabled":false,"name":"First floor","x":300,"y":1260,"wires":[[]]},{"id":"e97fb24c.c24d","type":"ui_group","z":"","name":"Ground floor","tab":"d3570004.d94f","order":1,"disp":true,"width":"7","collapse":true},{"id":"8af2dd4a.30827","type":"ui_group","z":"","name":"First floor","tab":"d3570004.d94f","order":2,"disp":true,"width":"7","collapse":true},{"id":"d3570004.d94f","type":"ui_tab","z":"","name":"Multiple floor demo","icon":"dashboard","disabled":false,"hidden":false}]

This way of working has a couple of advantages:

  • It is possible to show each floorplan individually, but also to show more (or all) floors at once.
  • Each SVG node can have its own dedicated flow if required.

Replace the entire floor

Since version 2.1.0 of the SVG node, it is possible to replace the entire SVG. When another floor is selected (e.g. via buttons on the dashboard), a message can be inserted which contains the SVG of the selected floor:

Replace SVG

[{"id":"be0f321d.4f0f7","type":"ui_svg_graphics","z":"42b7b639.325dd8","group":"e2281235.a788c","order":4,"width":"7","height":"5","svgString":"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"340px\" height=\"240px\" viewBox=\"0 0 340 240\" preserveAspectRatio=\"xMinYMin meet\">\n</svg>","clickableShapes":[{"targetId":"#myShape","action":"click","payload":"myShape clicked","payloadType":"str","topic":"#myShape"}],"javascriptHandlers":[],"smilAnimations":[],"bindings":[],"showCoordinates":false,"autoFormatAfterEdit":false,"showBrowserErrors":false,"showBrowserEvents":false,"enableJsDebugging":false,"sendMsgWhenLoaded":true,"outputField":"payload","editorUrl":"//drawsvg.org/drawsvg.html","directory":"","panning":"disabled","zooming":"disabled","panOnlyWhenZoomed":false,"doubleClickZoomEnabled":false,"mouseWheelZoomEnabled":false,"name":"svg-graphics","x":730,"y":1420,"wires":[["719a7ee2.457da"]]},{"id":"719a7ee2.457da","type":"debug","z":"42b7b639.325dd8","name":"Floor loaded","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":910,"y":1420,"wires":[]},{"id":"58a3a4e.bf6ff5c","type":"ui_button","z":"42b7b639.325dd8","name":"Ground floor","group":"e2281235.a788c","order":1,"width":"0","height":"0","passthru":false,"label":"Ground floor","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":310,"y":1420,"wires":[["c21d6609.0a4668"]]},{"id":"c21d6609.0a4668","type":"change","z":"42b7b639.325dd8","name":"Set ground floor SVG","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"command\":\"replace_svg\",\"svg\":\"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" width=\\\"340px\\\" height=\\\"240px\\\" viewBox=\\\"0 0 340 240\\\" preserveAspectRatio=\\\"xMinYMin meet\\\"><rect x=\\\"20\\\" y=\\\"20\\\" width=\\\"300\\\" height=\\\"150\\\" style=\\\"fill:yellowgreen;stroke:black;stroke-width:1px;fill-opacity:50%;\\\"/><text style=\\\"fill:forestgreen;font-size:30px;font-weight:bold;\\\" x=\\\"70\\\" y=\\\"100\\\">Ground floor</text></svg>\"}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":520,"y":1420,"wires":[["be0f321d.4f0f7"]]},{"id":"ace86d79.5151","type":"change","z":"42b7b639.325dd8","name":"Set first floor SVG","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"command\":\"replace_svg\",\"svg\":\"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" width=\\\"340px\\\" height=\\\"240px\\\" viewBox=\\\"0 0 340 240\\\" preserveAspectRatio=\\\"xMinYMin meet\\\"><rect x=\\\"20\\\" y=\\\"20\\\" width=\\\"300\\\" height=\\\"150\\\" style=\\\"fill:moccasin;stroke:black;stroke-width:1px;fill-opacity:50%;\\\"/><text style=\\\"fill:peru;font-size:30px;font-weight:bold;\\\" x=\\\"90\\\" y=\\\"100\\\">First floor</text></svg>\"}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":1480,"wires":[["be0f321d.4f0f7"]]},{"id":"a59f50d0.ea00d","type":"ui_button","z":"42b7b639.325dd8","name":"First floor","group":"e2281235.a788c","order":3,"width":"0","height":"0","passthru":false,"label":"First floor","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":300,"y":1480,"wires":[["ace86d79.5151"]]},{"id":"1ff8894b.cda0a7","type":"inject","z":"42b7b639.325dd8","name":"Load at startup","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":300,"y":1360,"wires":[["c21d6609.0a4668"]]},{"id":"e2281235.a788c","type":"ui_group","z":"","name":"Replace floors","tab":"d3570004.d94f","order":4,"disp":true,"width":"7","collapse":false},{"id":"d3570004.d94f","type":"ui_tab","z":"","name":"Multiple floor demo","icon":"dashboard","disabled":false,"hidden":false}]

Then that floor will be displayed:

Floor replace

⚠️ CAUTION: THERE SEEMS TO BE A BUG, SINCE THE SIZE OF THE INJECTED DRAWING IS INCORRECT!

The disadvantage is that the entire SVG drawing needs to be intialized every time, which means a series of messages needs to be inserted (e.g. to make sure some icon is blinking...). The "Send output msg when the client is (re)loaded" option (in the "Settings" tabsheet), can be activated as an aid for this: as soon as a (re)load output message is send, the newly inserted SVG can be initialised by the flow.

Move the viewbox

It is also possible to create one large SVG drawing, containing the floorplans of all the floors next to each other:

Large drawing

When another floor is selected (e.g. via buttons on the dashboard), a message can be inserted which contains the new dimensions of the viewbox (i.e. a new area of the SVG drawing that will be visualized):

Viewbox flow

[{"id":"f4cd53cc.34b7e","type":"ui_svg_graphics","z":"42b7b639.325dd8","group":"8206b178.89c87","order":4,"width":"7","height":"5","svgString":"<svg id=\"my_svg\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"340px\" height=\"180px\" viewBox=\"0 0 340 180\" preserveAspectRatio=\"xMinYMin meet\">\n  <!--Ground floor-->\n  <rect x=\"20\" y=\"20\" width=\"300\" height=\"150\" style=\"fill:yellowgreen;stroke:black;stroke-width:1px;fill-opacity:50%;\" />\n  <text style=\"fill:forestgreen;font-size:30px;font-weight:bold;\" x=\"70\" y=\"100\">Ground floor</text>\n  <!--Second floor-->\n  <rect x=\"20\" y=\"190\" width=\"300\" height=\"150\" style=\"fill:moccasin;stroke:black;stroke-width:1px;fill-opacity:50%;\" />\n  <text style=\"fill:peru;font-size:30px;font-weight:bold;\" x=\"90\" y=\"270\">First floor</text>\n</svg>","clickableShapes":[],"javascriptHandlers":[],"smilAnimations":[],"bindings":[],"showCoordinates":false,"autoFormatAfterEdit":false,"showBrowserErrors":false,"showBrowserEvents":false,"enableJsDebugging":false,"sendMsgWhenLoaded":false,"outputField":"payload","editorUrl":"//drawsvg.org/drawsvg.html","directory":"","panning":"disabled","zooming":"disabled","panOnlyWhenZoomed":false,"doubleClickZoomEnabled":false,"mouseWheelZoomEnabled":false,"name":"svg-graphics","x":730,"y":1380,"wires":[[]]},{"id":"fb040848.797c88","type":"ui_button","z":"42b7b639.325dd8","name":"Ground floor","group":"8206b178.89c87","order":1,"width":"0","height":"0","passthru":false,"label":"Ground floor","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":310,"y":1380,"wires":[["86b0810.3c3d98"]]},{"id":"86b0810.3c3d98","type":"change","z":"42b7b639.325dd8","name":"Viewbox \"0 0 340 180\"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"command\":\"update_attribute\",\"selector\":\"#my_svg\",\"attributeName\":\"viewBox\",\"attributeValue\":\"0 0 340 180\"}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":520,"y":1380,"wires":[["f4cd53cc.34b7e"]]},{"id":"d7603048.47334","type":"change","z":"42b7b639.325dd8","name":"Viewbox \"0 190 340 180\"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"command\":\"update_attribute\",\"selector\":\"#my_svg\",\"attributeName\":\"viewBox\",\"attributeValue\":\"0 171 340 180\"}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":530,"y":1440,"wires":[["f4cd53cc.34b7e"]]},{"id":"30d8f1e0.76735e","type":"ui_button","z":"42b7b639.325dd8","name":"First floor","group":"8206b178.89c87","order":3,"width":"0","height":"0","passthru":false,"label":"First floor","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":300,"y":1440,"wires":[["d7603048.47334"]]},{"id":"8206b178.89c87","type":"ui_group","z":"","name":"Viewbox zooming","tab":"d3570004.d94f","order":5,"disp":true,"width":"7","collapse":false},{"id":"d3570004.d94f","type":"ui_tab","z":"","name":"Multiple floor demo","icon":"dashboard","disabled":false,"hidden":false}]

This is based on the viewbox of the drawing, which specifies which part of the drawing (i.e. viewport) will become visible:

viewport

The viewbox can be updated to make one of the floors visible on the dashboard, by zooming in on that floor. This can be achieved by inserting an input message to update the SVG viewbox dimensions:

Floors viewbox

Use layered floors

It is also possible to create one large SVG drawing, containing the floorplans of all the floors on top of each other:

Layered drawing

Note that each layer will be packed in an SVG group element, which will contain all the SVG shapes of that layer. When another floor is selected (e.g. via buttons on the dashboard), a message can be inserted to show a single floor group (and hide all the other floor groups). Such a group can be made (in)visible by updating the visbility attribute (visible or hidden):

Layered flow

[{"id":"3c399fb2.580f9","type":"ui_svg_graphics","z":"42b7b639.325dd8","group":"28a3c5d2.90ed5a","order":4,"width":"7","height":"5","svgString":"<svg id=\"my_svg\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"340px\" height=\"180px\" viewBox=\"0 0 340 180\" preserveAspectRatio=\"xMinYMin meet\">\n  <g id=\"ground_floor\" visibility=\"visible\">\n    <rect x=\"20\" y=\"20\" width=\"300\" height=\"150\" style=\"fill:yellowgreen;stroke:black;stroke-width:1px;fill-opacity:50%;\" />\n    <text style=\"fill:forestgreen;font-size:30px;font-weight:bold;\" x=\"70\" y=\"100\">Ground floor</text>\n  </g>\n  <g id=\"first_floor\" visibility=\"hidden\">\n    <rect x=\"20\" y=\"20\" width=\"300\" height=\"150\" style=\"fill:moccasin;stroke:black;stroke-width:1px;fill-opacity:50%;\" />\n    <text style=\"fill:peru;font-size:30px;font-weight:bold;\" x=\"90\" y=\"100\">First floor</text>\n  </g>\n</svg>","clickableShapes":[],"javascriptHandlers":[],"smilAnimations":[],"bindings":[],"showCoordinates":false,"autoFormatAfterEdit":false,"showBrowserErrors":false,"showBrowserEvents":true,"enableJsDebugging":false,"sendMsgWhenLoaded":false,"outputField":"payload","editorUrl":"//drawsvg.org/drawsvg.html","directory":"","panning":"disabled","zooming":"disabled","panOnlyWhenZoomed":false,"doubleClickZoomEnabled":false,"mouseWheelZoomEnabled":false,"name":"svg-graphics","x":770,"y":1540,"wires":[[]]},{"id":"a093c141.6b4bf","type":"ui_button","z":"42b7b639.325dd8","name":"Ground floor","group":"28a3c5d2.90ed5a","order":1,"width":"0","height":"0","passthru":false,"label":"Ground floor","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":310,"y":1540,"wires":[["8e3cb425.72d7b8"]]},{"id":"8e3cb425.72d7b8","type":"change","z":"42b7b639.325dd8","name":"Show ground floor group","rules":[{"t":"set","p":"payload","pt":"msg","to":"[{\"command\":\"update_attribute\",\"selector\":\"#ground_floor\",\"attributeName\":\"visibility\",\"attributeValue\":\"visible\"},{\"command\":\"update_attribute\",\"selector\":\"#first_floor\",\"attributeName\":\"visibility\",\"attributeValue\":\"hidden\"}]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":530,"y":1540,"wires":[["3c399fb2.580f9"]]},{"id":"9121d57f.8c4cf8","type":"change","z":"42b7b639.325dd8","name":"Show first floor group","rules":[{"t":"set","p":"payload","pt":"msg","to":"[{\"command\":\"update_attribute\",\"selector\":\"#ground_floor\",\"attributeName\":\"visibility\",\"attributeValue\":\"hidden\"},{\"command\":\"update_attribute\",\"selector\":\"#first_floor\",\"attributeName\":\"visibility\",\"attributeValue\":\"visible\"}]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":520,"y":1600,"wires":[["3c399fb2.580f9"]]},{"id":"84145536.8e6328","type":"ui_button","z":"42b7b639.325dd8","name":"First floor","group":"28a3c5d2.90ed5a","order":3,"width":"0","height":"0","passthru":false,"label":"First floor","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":300,"y":1600,"wires":[["9121d57f.8c4cf8"]]},{"id":"28a3c5d2.90ed5a","type":"ui_group","z":"","name":"Layered floors","tab":"d3570004.d94f","order":6,"disp":true,"width":"7","collapse":false},{"id":"d3570004.d94f","type":"ui_tab","z":"","name":"Multiple floor demo","icon":"dashboard","disabled":false,"hidden":false}]

It is required to hide all the other floor groups, because otherwise all floors will be drawn criss-cross through each other:

Criss-cross floors

Note that most SVG editors will have a layer manager, to allow drawing layer by layer. This feature is also available in DrawSvg, the editor which we have embedded inside the SVG node:

Layer manager

A disadvantage of this way of working, is that it is impossible to show all floors at once.