Рисуем на холсте с помощью 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
Ответы
Ответ 1
Пожалуйста, проверьте этот jsFiddle: https://jsfiddle.net/mani04/r4mbh6nu/
EDIT: обновлен динамическим текстом: https://jsfiddle.net/mani04/r4mbh6nu/1/
В приведенном выше примере я могу записать в холст, а также убедиться, что текст input
переходит в span
, как и следовало ожидать, все с помощью Vue.js
Возвращаясь к вашему примеру, HTML:
<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.
В моем примере я определяю директиву Vue, называемую insert-message
, которую я использую на холсте как v-insert-message
. Это позволяет мне захватить элемент DOM, а затем выполнить другие шаги: getContext
и fillText
. Существует не id
, либо код javascript для getElementById
.
Еще одно: ваш холст слишком велик, и поэтому вы не смогли увидеть ваши элементы input
и span
. Они тоже нормально работали в вашем примере!
EDIT: пример для привязок директив
Я только нашел способ использовать директивы и все еще писать динамические материалы в холст.
Проверьте обновленный jsFiddle: https://jsfiddle.net/mani04/r4mbh6nu/1/
Ответ 2
Вот простой способ, который работает с Vuejs 2:
-
Добавьте шаблон canvas к вам со ссылочным атрибутом:
ref="myCanvas"
-
Затем вы можете получить доступ к нему в любом месте вашего компонента, используя
var canvas = this. $refs.myCanvas
Ответ 3
Как описано в @Mani Отвечать, Vue удаляет и повторно отображает элемент DOM, к которому вызывается экземпляр Vue.
Если вы аннулируете обновление своего холста в экземпляр Vue method
, вы можете запустить его при крючке жизненного цикла mounted
(чтобы получить начальное значение exampleContent
), повторите его в своем watch
когда exampleContent
изменяется.
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>