JSFiddle - React, Tailwind, and code Playground

by uedatakuya

HTML

<script src="https://github.com/downloads/SteveSanderson/knockout/knockout-2.0.0.js"></script>
<div data-bind="template: { name: 'svg-template', foreach: pathes}"></div>
<script type="image/svg+xml" id="svg-template">
    <svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="4cm" height="4cm" viewBox="0 0 400 400">
        <path data-bind="shape:$data"/>
    </svg>
</script>

CSS

path {
    fill: none;
    stroke:blue;
    stroke-width:3;
}

CoffeeScript

class Shape
    constructor:->
        @transformArray = ko.observableArray()
        @transform = ko.computed(()=>
            (t.toString() for t in @transformArray()).join(" ")
        , @)

class Rotate
    constructor:(param)->
        @angle = param.angle ? ko.observable(0)
        @x = param.x ? ko.observable(0)
        @y = param.y ? ko.observable(0)
    toString:->
        "rotate(#{ko.utils.unwrapObservable(@angle)},#{ko.utils.unwrapObservable(@x)},#{ko.utils.unwrapObservable(@y)})"                

class Path extends Shape
    constructor:()->
        @d = ko.observableArray()
        
class LineTo
    constructor:(param)->
        @x = param.x ? ko.observable(0)
        @y = param.y ? ko.observable(0)
        @toString = ()->
            "L #{ko.utils.unwrapObservable(@x)} #{ko.utils.unwrapObservable(@y)}"  

class MoveTo
    constructor:(param)->
        @x = param.x ? ko.observable(0)
        @y = param.y ? ko.observable(0)
        @toString = ()->
            "M #{ko.utils.unwrapObservable(@x)} #{ko.utils.unwrapObservable(@y)}"

class SVGViewModel
    constructor:()->
        @pathes = ko.observableArray()

ko.bindingHandlers.shape =
    init:(element, valueAccessor, allBindingsAccessor, viewModel)->
        for k, v of valueAccessor()
            value = ko.utils.unwrapObservable(v)
            if $.isArray(value)
                $(element).attr(k, (m.toString() for m in value).join(" "))
            else
                $(element).attr(k, value)
    ,
    update:(element, valueAccessor, allBindingsAccessor, viewModel)->
        for k in valueAccessor()
            element[k] = valueAccessor()[k]        
            
model = new SVGViewModel()
path = new Path()
path.d.push(new MoveTo(
    x: ko.observable(100)
    y: ko.observable(100)
))
path.d.push(new LineTo(
    x: ko.observable(300)
    y: ko.observable(100)
))
path.d.push(new LineTo(
    x: ko.observable(200)
    y: ko.observable(300)
))
model.pathes.push(path)
ko.applyBindings(model)