Draw your own LCARS home automation user interface with Javascript and SVG

Some time ago I wrote already why I like LCARS as a user interface design for home automation. Looking around on the internet you will find several frameworks to build your own LCARS-styled UI. Some of them are quite old and I did not even look into them. I hope nobody is using Flash for new UIs anymore. Others use a lot of image files. I don’t like this approach as the controls are really simple and you don’t need to load a graphics file for a simple rectangle.

The project I liked most was the LCARS SDK. It is using Javascript in the browser and

blocks to build a UI. However as the documentation wasn’t always clear it took me a lot of time to build even a simple UI.

But why using

blocks? There is an even better way: SVG. Scalable vector graphics are part of the web standard since more then 10 years, but they aren’t used widely yet. Fortunately all modern browsers support them and it is very simple to draw some rectangles and circles. You can also add styling using CSS, modify them with Javascript and add Javascript event. Rendering is very lightweight as the number of objects is usually relatively small (between 50 and 500 objects on screen). This makes this approach also ideal for browsers on tablets and mobile phones.

Programming a simple control frame doesn’t need a lot of code:

function home() {
    lcarsgen.container=document.getElementById("canvas");
    lcarsgen.next_x = 10
    lcarsgen.next_y = 10
    lcarsgen.knee({x:10, height2: 40})
    save_x = lcarsgen.next_x
    lcarsgen.button({x:10, text:"Light", id:"b_light"})
    lcarsgen.button({x:10, text:"Heating", id:"b_heating"})
    lcarsgen.button({x:10, text:"Blinds", id:"b_blinds"})
    lcarsgen.button({x:10, text:"Weather", id:"b_weather"})
    lcarsgen.button({x:10, text:"Movies", id:"b_movies"})
    lcarsgen.button({x:10, text:"Music", id:"b_music"})
    lcarsgen.button({x:10, text:"Config", id:"b_config"})
    lcarsgen.knee({x:10, height1: 120, height2: 40, \
                   type:"bottomleft"})
    save_y = lcarsgen.next_y - lcarsgen.spacing - 40
 
    // top bar
    lcarsgen.next_x=save_x
    lcarsgen.button({y: 10, width: 310, height: 40} )
    lcarsgen.button({y: 10, width: 310, height: 40} )

    // save for text display
    tx = lcarsgen.next_x-lcarsgen.spacing
    lcarsgen.button({y: 10, width: 55, height: 40, \
                     type:"rounded_right"} )

    // bottom bar
    lcarsgen.next_x=save_x
    lcarsgen.button({y: save_y, width: 310, height: 40} )
    lcarsgen.button({y: save_y, width: 310, height: 40} )
    lcarsgen.button({y: save_y, width: 55, height: 40, \
                     type:"rounded_right"} )

    lcarsgen.text({x:tx, y: 50, height: 40, text:"H.11 CONTROL", \
                   text_align: "right"} )
}

The result look already pretty cool:
Screenshot 2016-05-12 12.15.52