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

Fill a shape with a pattern (to create shutter effect)

bartbutenaers edited this page May 2, 2022 · 1 revision

SVG offers patterns, which are shapes that will be repeated in X and y directions. Such patterns can be used to fill the area of other shapes.

Draw a roller shutter

We will show the steps to display a roller shutter for a house:

  1. A typical roller shuttor consists out of long narrow rectangles, which are repeated a number of times:

    image

  2. One way to simulate such an effect, is by creating a pattern that consists out of a lightgrey rectangle followed by a black line:

    <defs>
       <pattern id="shutter_pattern" width="6" height="6" patternUnits="userSpaceOnUse">
          <rect x="0" y="0" width="6" height="6" fill="lightgrey" stroke="none"/>
          <line x1="0" y1="2" x2="6" y2="2" stroke="black" stroke-width="2"/>
       </pattern>
    </defs>
    

    This pattern has very small dimensions (i.e. 6 x 6), but can be repeated by the browser in both X and Y directions.

  3. We can now draw a rectangle that represents the window itself:

    <rect id="imagebackground" x="0" y="0" width="50" height="80" stroke="none" fill="url(#shutter_pattern)"/>
    

    The pattern is applied to the window rectangle, by specifying the pattern id via a fill url.

  4. The browser will repeat the pattern in both directions to fill the entire window rectangle, resulting in a closed roller shutter:

    image

Open/close the roller shutter

As shown above, the browser will fill the entire window rectangle. However most of the time the roller shutter will be open completely or partially. I didn't find a simple way to achieve this, so we will solve this by using two separate rectangles:

  1. Use the same pattern as in the above example.

  2. Create two separate rectangles:

    <rect x="0" y="0" width="50" height="80" stroke="none" fill="white"/>
    <rect x="0" y="0" width="50" height="40" stroke="none" fill="url(#shutter_pattern)" id="roller_shutter"/>
    

    We draw a large white rectangle that represents the entire window. On top of that we draw a rectangle of half the height, which gets the roller shutter pattern.

  3. This will result in the roller shutter being half open:

    image

  4. Since the roller shutter rectangle has an id (i.e. "roller_shutter"), we can inject a message to change the rectangle height:

    payload = {
     command: "set_attribute",
     selector: "#roller_shutter",
     attributeName: "height",
     attributeValue: msg.payload
    }
    

The following example flow shows how this works:

image

[{"id":"98d8ef2e2cd646d7","type":"ui_svg_graphics","z":"8fee6c7e9e28fe94","group":"f014eb03.a3c618","order":1,"width":"14","height":"10","svgString":"<svg version=\"1.1\" id=\"Capa_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" width=\"100%\" height=\"100%\" viewBox=\"0 0 463 463\" style=\"enable-background:new 0 0 463 463;\" xml:space=\"preserve\">\n  <defs>\n    <pattern id=\"shutter_pattern\" width=\"6\" height=\"6\" patternUnits=\"userSpaceOnUse\">\n      <rect x=\"0\" y=\"0\" width=\"6\" height=\"6\" fill=\"lightgrey\" stroke=\"none\" />\n      <line x1=\"0\" y1=\"2\" x2=\"6\" y2=\"2\" stroke=\"black\" stroke-width=\"2\" />\n    </pattern>\n  </defs>\n  <rect x=\"0\" y=\"0\" width=\"50\" height=\"80\" stroke=\"none\" fill=\"white\" />\n  <rect x=\"0\" y=\"0\" width=\"50\" height=\"40\" stroke=\"none\" fill=\"url(#shutter_pattern)\" id=\"roller_shutter\"/>\n</svg>","clickableShapes":[{"targetId":"#temp_living","action":"change","payload":"temperature_living","payloadType":"str","topic":"temperature_living"}],"javascriptHandlers":[{"selector":"#temp_living","action":"change","sourceCode":"if(evt.target.valueAsNumber < 10) {\n    $(\"#temp_living_label\")[0].style.color=\"blue\";\n}\nelse if(evt.target.valueAsNumber > 20) {\n    $(\"#temp_living_label\")[0].style.color=\"red\";\n}\nelse {\n    $(\"#temp_living_label\")[0].style.color=\"orange\";\n}"}],"smilAnimations":[],"bindings":[],"showCoordinates":false,"autoFormatAfterEdit":false,"showBrowserErrors":true,"showBrowserEvents":true,"enableJsDebugging":true,"sendMsgWhenLoaded":false,"noClickWhenDblClick":false,"outputField":"","editorUrl":"http://drawsvg.org/drawsvg.html","directory":"","panning":"disabled","zooming":"disabled","panOnlyWhenZoomed":false,"doubleClickZoomEnabled":false,"mouseWheelZoomEnabled":false,"dblClickZoomPercentage":"150","cssString":"div.ui-svg svg{\n    color: var(--nr-dashboard-widgetColor);\n    fill: currentColor !important;\n}\ndiv.ui-svg path {\n    fill: inherit;\n}","name":"","x":720,"y":320,"wires":[[]]},{"id":"3b736443b32a9749","type":"inject","z":"8fee6c7e9e28fe94","name":"Value 0","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":250,"y":320,"wires":[["b2ae01c2ad154562"]]},{"id":"b2ae01c2ad154562","type":"function","z":"8fee6c7e9e28fe94","name":"Change rectangle height","func":"msg.payload = {\n    command: \"set_attribute\",\n    selector: \"#roller_shutter\",\n    attributeName: \"height\",\n    attributeValue: msg.payload\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":490,"y":320,"wires":[["98d8ef2e2cd646d7"]]},{"id":"2b9ecbd548389816","type":"inject","z":"8fee6c7e9e28fe94","name":"Value 20","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"20","payloadType":"num","x":260,"y":360,"wires":[["b2ae01c2ad154562"]]},{"id":"41b7ebbd718019ab","type":"inject","z":"8fee6c7e9e28fe94","name":"Value 40","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"40","payloadType":"num","x":260,"y":400,"wires":[["b2ae01c2ad154562"]]},{"id":"aea6bf6a34253e3c","type":"inject","z":"8fee6c7e9e28fe94","name":"Value 60","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"60","payloadType":"num","x":260,"y":440,"wires":[["b2ae01c2ad154562"]]},{"id":"54e2adbe3704e9c3","type":"inject","z":"8fee6c7e9e28fe94","name":"Value 80","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"80","payloadType":"num","x":260,"y":480,"wires":[["b2ae01c2ad154562"]]},{"id":"f014eb03.a3c618","type":"ui_group","name":"Pattern fill demo","tab":"80068970.6e2868","order":1,"disp":true,"width":"18","collapse":false,"className":""},{"id":"80068970.6e2868","type":"ui_tab","name":"SVG","icon":"dashboard","order":14,"disabled":false,"hidden":false}]

Which works like this:

pattern_fill_demo