使用vue.js在画布上绘图
Drawing onto a canvas with vue.js
我不认为这一定是一个基于Vue的问题,但是我遇到了一些麻烦。
我想给画布写一个Vue变量。如果我删除vue,我的初始代码工作得很好,但是如果我添加vue,画布实际上不会启动。
我的代码
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = "black";
ctx.font="20px Georgia";
ctx.fillText("Hello World!",10,50);
var v = new Vue({
el: '#app',
data: {
'exampleContent': 'This is TEXT'
},
watch: {
exampleContent: function(val, oldVal) {
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.fillStyle = "black";
ctx.font="20px Georgia";
ctx.fillText(this.exampleContent,10,50);
}
}
});
如果我注释掉/* var v = new Vue({ ...
,初始位有效。如果我在监视器中记录exampleContent
的值,也可以工作。但是画布的某些部分不工作。
演示:http://codepen.io/EightArmsHQ/pen/EgGbgR?editors=1010
请查看此jsFiddle: https://jsfiddle.net/mani04/r4mbh6nu/
EDIT:更新为动态文本:https://jsfiddle.net/mani04/r4mbh6nu/1/
在上面的例子中,我能够写入画布,并确保input
文本进入span
,正如你所期望的那样,所有使用Vue.js
<div id="app">
<canvas id="canvas" width="800" height="600"></canvas>
<input type="text" v-model="exampleContent" />
<span>{{ exampleContent }}</span>
</div>
Vue.js读取#app
中的元素,并将其作为Vue应用的模板。所以你的canvas
, input
和span
元素现在将由Vue.js在构建DOM时重新渲染。
在此过程中,您的原始画布文本-在初始化Vue应用程序之前设置的文本将丢失。
没有明确的方法来解决这个问题,除了使用directive
,在我的jsFiddle的例子。Vue指令可以帮助您捕获DOM元素。
在我的例子中,我定义了一个名为insert-message
的Vue指令,我在画布上使用v-insert-message
。这允许我捕获DOM元素,然后执行其他步骤:getContext
和fillText
。不需要id
,或者不需要javascript代码到getElementById
。
还有一件事-你的画布太大了,因此你无法看到你的input
和span
元素。他们也在你的例子中正常工作!
编辑:指令绑定示例
我刚刚找到了一种方法,使用指令,仍然写入动态的东西到画布。
查看更新后的jsFiddle: https://jsfiddle.net/mani04/r4mbh6nu/1/
下面是一个使用Vuejs 2的简单方法:
-
使用引用属性将画布添加到模板中:
ref="myCanvas"
-
你可以使用
在组件内的任何地方访问它var canvas = this.$refs.myCanvas
正如@Mani的答案中详述的那样,Vue删除并重新呈现Vue实例所调用的DOM元素。
如果你将你的画布更新抽象到一个Vue实例method
中,你可以在mounted
生命周期钩子上触发它(获得exampleContent
的初始值),当exampleContent
发生变化时,在watch
中重新调用它。
var v = new Vue({
el: '#app',
data: {
'exampleContent': 'This is TEXT'
},
methods: {
updateCanvas: function (){
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d');
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.fillStyle = "black";
ctx.font="20px Georgia";
ctx.fillText(this.exampleContent,10,50);
}
},
watch: {
exampleContent: function(val, oldVal) {
this.updateCanvas();
}
},
mounted: function (){
this.updateCanvas();
}
});
canvas{
background:red;
width:800px;
height:600px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.1/vue.min.js"></script>
<div id="app">
<canvas id="canvas" width="800" height="600"></canvas>
<input type="text" v-model="exampleContent" />
<span>{{ exampleContent }}</span>
</div>
前面的SO代码片段是从OP的CodePen的分支版本创建的
这个问题已经被浏览了几次,自从我第一次问这个问题以来,我已经使用画布和Vue数千次了。这是我在实践中发现的最好的选择。
给画布一个ref
,正如一些人提到的:
<div id="app">
<canvas width="800" height="600" ref="nameOfCanvas"></canvas>
</div>
在挂载函数中设置画布的context
:
mounted(){
this.canvas = this.$refs.nameOfCanvas;
this.ctx = this.canvas.getContext("2d");
this.render();
}
没有必要将ctx放在data
对象中,除非您想要监视它。
就是这样。从那里,可以创建render
方法并在组件中引用数据…
render(){
this.ctx.clearRect(0,0,this.canvas.width, this.canvas.height);
this.ctx.fillRect(0, 0, 20, 20);
}
您还可以在此方法中设置一个requestAnimationFrame
循环,如下所示:
render(){
this.ctx.clearRect(0,0,this.canvas.width, this.canvas.height);
this.ctx.fillRect(0, 0, 20, 20);
requestAnimationFrame(this.render);
}
完整demo/starter:https://codepen.io/EightArmsHQ/pen/gOROpqQ
- Canvas Html5绘图应用程序,移动画布会导致重大问题
- 如何创建带有插槽的vue js组件预加载程序
- [Vue warn]:未能解析组件
- HTML画布在绘图后立即擦除矩形
- 引用vue.js中v-for中的上一个值
- 如何在JS Leatflet绘图插件中获取圆的坐标
- 在一个页面中具有多个捕捉绘图和捕捉内容
- 如何访问<插槽>内部v-for(vue.js)
- [Vue warn]:找不到元素
- SVG手写字母绘图动画
- 如何确定Vue何时完成DOM更新
- Fresh Spark Install+Homestead上的Vue异步堆栈跟踪错误
- Vue iFrames与Vue路由器
- 绘图悬停文本未显示
- 调用laravel{{action(Controller@method}}通过传递vue.js数组中的变量
- 为画布绘图添加鼠标事件
- 访问vue组件中的ID标记
- 如何强制绘图将x轴编号显示为类别
- Vue.js获取组件中的一个元素
- 使用vue.js在画布上绘图