Vue bind to SVG Elements
by Ben Clayton
HTML
<script src="//unpkg.com/vue"></script>
<script type="text/x-template" id="mycircle-template">
<!-- <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" /> -->
<circle :cx="prop('x')" :cy="prop('y')" :r="prop('r')" :stroke="prop('stroke')" :fill="color()" stroke-width="1" />
</script>
<!-- demo root element -->
<div id="demo">
<!-- SVG Elements -->
<svg width="500" height="300">
<g v-for="stat in stats">
<mycircle :stat="stat"></mycircle>
</g>
</svg>
<!-- controls -->
<div v-for="stat in stats">
<label>{{stat.label}} (radius)</label>
<input type="range" v-model="stat.r" min="0" max="100">
<label>(colour)</label>
<input type="checkbox" v-model="stat.state" value=0>
</div>
</div>
JavaScript
// The raw data to observe
var stats = [{
label: 'C1',
r: 10,
fill: "gray",
x: 50,
y: 123,
stroke: "black"
},
{
label: 'C2',
r: 10,
fill: "gray",
x: 100,
y: 123,
stroke: "black"
},
{
label: 'C3',
r: 10,
fill: "gray",
x: 150,
yd: 123,
stroke: "black"
},
{
label: 'C4',
r: 10,
fill: "gray",
x: 200,
y: 123,
stroke: "black"
}
/* ,{ label: 'C2', r: 100 },
{ label: 'C3', r: 100 },
{ label: 'C4', r: 50 } */
]
Vue.component('mycircle', {
props: ['stat'],
template: '#mycircle-template',
// components data must be a function
// used here as default if 'stat' doesn't provide property
data: function() {
return {}
},
methods: {
color: function() {
return this.stat.state ? "red" : "green"
},
prop: function(nm) {
return this.stat[nm] || this[nm];
}
}
})
// bootstrap the demo
new Vue({
el: '#demo',
data: {
newLabel: '',
stats: stats
},
methods: {
add: function(e) {
e.preventDefault()
if (!this.newLabel) return
this.stats.push({
label: this.newLabel,
value: 100
})
this.newLabel = ''
},
remove: function(stat) {
if (this.stats.length > 3) {
this.stats.splice(this.stats.indexOf(stat), 1)
} else {
alert('Can\'t delete more!')
}
}
}
})