Vue.js SVG example

by boulabiar

HTML

<script src="http://vuejs.org/js/vue.min.js"></script>
<!-- Vue.js can handle SVG too! -->
<svg width="200" height="200"
     viewPort="0 0 200 200" version="1.1"
     xmlns="http://www.w3.org/2000/svg">
    <polygon v-attr="points:points"/>
    <circle cx="100" cy="100" r="80"/>
    <text v-component="svg-label"
        v-repeat="stats"
        v-attr="x:x, y:y">
        {{label}}
    </text>
</svg>

<!-- controls -->
<div v-repeat="stats">
    <label>{{label}}</label>
    <input type="range" v-model="value" min="0" max="100" />
    <span>{{value}}</span>
</div>
    
<p style="font-size:12px">* input[type="range"] requires IE10 or above.</p>

CSS

body {
    font-family: Helvetica Neue, Arial, sans-serif;
}

polygon {
    fill: #42b983;
    opacity: .75;
}

circle {
    fill: transparent;
    stroke: #999;
}

text {
    font-family: Helvetica Neue, Arial, sans-serif;
    font-size: 10px;
    fill: #666;
}

label {
    display: inline-block;
    margin-left: 10px;
    width: 20px;
}
}

JavaScript

var size = 200

// A label component
Vue.component('svg-label', {
    created: function () {
        this.x = this.y = 0
        this.$watch('value', function (val) {
            var point = valueToPoint(+val + 10, this.$index)
            this.x = point.x - 4
            this.y = point.y + 4
        })
    }
})

// bootstrap the demo
new Vue({
    el: 'body',
    data: {
        stats: [
            { label: 'A', value: 100 },
            { label: 'B', value: 100 },
            { label: 'C', value: 100 },
            { label: 'D', value: 100 },
            { label: 'E', value: 100 },
            { label: 'F', value: 100 }
        ]
    },
    computed: {
        points: function () {
            return this.stats.map(function (stat, i) {
                var point = valueToPoint(stat.value, i)
                return point.x + ',' + point.y
            }).join(' ')
        }
    }
})

// do some math...
function valueToPoint (value, i) {
    var x     = 0,
        y     = -value * (size / 100) * 0.4,
        angle = Math.PI / 3 * i,
        cos   = Math.cos(angle),
        sin   = Math.sin(angle),
        tx    = x * cos - y * sin + size / 2,
        ty    = x * sin + y * cos + size / 2
    return {
        x: tx,
        y: ty
    }
}