An universal framework using vue.js, enabling declarative markup for canvas drawing.
vue-canvas.js provides 'v-canvas' directive, with these functionalities:
- orderd rendering of child component
- callback after all rendering of child components
- automatic re-rendering on vue instance updated
You must/can define child components inside canvas for your purpose.
- vue.js(ver2)
Just load vue-canvas.js, something like:
<script type="text/javascript" src="js/vue-canvas.js"></script>
Sample codes of Demo
HTML:
<canvas id="canvas" v-canvas:cb="onRendered" width="600" height="400">
<v-bg path="img/world.svg" ord="1"></v-bg><!-- sample component -->
<v-text ord="2" x="300" y="200" :message="message"></v-text><!-- sample component -->
</canvas>
Javascript(for main):
var vc = new Vue({
el: '#canvas',
data: {
message: "Hello!"
},
methods: {
onRendered: function (ctx) {
ctx.textAlign = "start";
ctx.fillStyle = "red";
ctx.fillText("rendering done!", 10, 30);
}
}
});
// Let's update vue instance data
setTimeout(function () {
vc.message = "Good-bye!"; // => re-draw canvas automatically!
}, 2000);
Javascript(for sample components):
// sample component to draw background image of canvas
Vue.component('v-bg', Vue.extend({
props: ["ord", "path"],
methods: {
draw: function (ctx, done) {
var img = new Image();
img.src = this.path;
img.onload = function(){
ctx.drawImage(img, 0, 0);
done();
}
}
}
}));
// sample component to draw message with provided coordinates
Vue.component('v-text', Vue.extend({
props: ["ord", "message", "x", "y"],
methods: {
draw: function (ctx, done) {
var canvas = ctx.canvas;
ctx.textAlign = "center";
ctx.fillStyle = "black";
ctx.font = "bold 30pt Courier";
ctx.fillText(this.message, parseInt(this.x), parseInt(this.y));
done();
}
}
}));
Result canvas:
Vue.component('[component name]', Vue.extend({
props: ["ord", ["prop1", "prop2",...]],
methods: {
draw: function (ctx, done) {
...// ctx is canvas context. draw with ctx as you like here.
done(); // please call done() at the end of drawing.
}
}
}));
Please assume that,
you already defined 2 components('v-score', 'v-baloon'), and you want to define new component('v-baloon-with-score') comprising of them.
You can do that like this.
Vue.component('v-baloon-with-score', Vue.extend({
props: ["ord", "score", "x", "y", "lightDirection"],
template: '<v-canvas-wrapper><v-score :score="score" :x="parseInt(x) + 25" :y="y - 45" light-direction="left" ord="2"></v-score>'
+ '<v-baloon title="hoge" :amount="score" :x="x" :y="y" direction="left" ord="1"></v-baloon></v-canvas-wrapper>',
methods: {
onRendered: function(ctx, done){
console.log("onRendered");
done();
}
}
}));
- You just need to wrap child components by <v-canvas-wrapper></v-canvas-wrapper> tag
- If you want to do something after rednering children, you can do that in onRendered method.