最近公司做的項目中有要求用canvas在圖片上顯示標注信息态兴。
而圖片是以彈出框的方式顯示出來的兄春,并且還是一個輪播圖,
輪播圖用的是swiper插件,
實現(xiàn)步驟:獲取canvas元素 ------- 初始化canvas ------- 初始化圖片 ------ 使用canvas繪制圖片
頁面具體代碼如下:
<swiper :options="swiperOption" v-if="modal" ref="mySwiper">
<swiper-slide v-for="item of data" :key="item.id">
<div class="imgBox">
<canvas class="myCanvas" width="600" height="500"></canvas>
</div>
</swiper-slide>
<div class="swiper-button-prev" slot="button-prev"></div>
<div class="swiper-button-next" slot="button-next"></div>
</swiper>
獲取canvas
獲取canvas的時候,犯了一個很大的錯誤,導致搞了很久都沒有獲取到這個元素,因為一開始就在網(wǎng)上各種搜搜搜浪默,因為網(wǎng)上的都是繪制一張圖片,而不是輪播圖,所以只需要用document.getElementById("myCanvas")就能獲取到canvas,然后就也跟著使用document.getElementById("myCanvas")來獲取浴鸿,但是很尷尬井氢,總是獲取不到,console.log打引出來的是undefined,另外我又試了用vue的獲取dom元素的ref,結(jié)果還是一樣的岳链,我很納悶花竞,為什么別人也是這么做的我這么做就行不通,認真的觀察一番掸哑,幡然醒悟约急,原來是因為我要實現(xiàn)的是輪播圖,用了v-for來渲染出多個canvas,這時候用document.getElementById("myCanvas")來獲取肯定是不對的苗分,id具有唯一性厌蔽,v-for把多個id為myCanvas渲染出來,顯示是大錯特錯摔癣,真是太糊涂了奴饮。ref同理。
于是換了document.querySelectorAll(".myCanvas")來獲取择浊,終于就獲取到了戴卜。
注意:這里還有個地方會導致獲取不到canvas,因為使用的是vue,所以一開始直接獲取canvas是獲取不到的,需要保證canvas元素加載完成才能獲取琢岩,否則獲取不到投剥,所以要用$nextTick()。
如果能認真點担孔,就不會犯這種錯誤了江锨。欸
初始化canvas和圖片并繪制。
本來以為獲取到canvas以后就萬事大吉了糕篇,沒想到在初始化這里還是有點坎坷的啄育,
因為canvas是有多個的,所以不能像別的文章那樣去獲取拌消,需要對canvas數(shù)組進行遍歷灸撰,然后一個一個初始化,初始化的同時再通過new Image()的方式創(chuàng)建一個img對象拼坎,將圖片的路徑賦值給它,然后再使用canvas的api----------"drawImage" 來獲取完疫,值得注意的是泰鸡,想要在canvas上繪制圖片就必須要保證圖片成功加載完成,所以需要在img.onload方法中去做繪制操作壳鹤。
initCanvas() {
//這里必須要使用$nextTick()才能獲取到canvas
this.$nextTick( () => {
let myCanvas = document.querySelectorAll(".myCanvas"); //獲取所有的canvas
let ctx = [];
let _this = this;
Array.from(myCanvas).forEach((item,index) => {//循環(huán)canvas
ctx[index] = item.getContext("2d"); //獲取canvas的上下文
let img = [];
img[index] = new Image(); //創(chuàng)建img對象
img[index].src = this.data[index].path;//將路徑賦值給對象
img[index].onload = function() { //必須要圖片加載完成才能實現(xiàn)
ctx[index].canvas.width = img[index].width; //獲取圖片的寬賦值給canvas的寬盛龄,使canvas自適應(yīng)圖片寬
ctx[index].canvas.height = img[index].height; //獲取圖片的寬賦值給canvas的高,使canvas自適應(yīng)圖片高
ctx[index].drawImage(img[index], 0, 0); //繪制圖片
};
});
});
}
實現(xiàn)到這里正常情況下基本是已經(jīng)繪制完成了。但是無奈余舶,還是出了bug
當我切換到下一張的時候
再切換回原來那張匿值,canvas的高度就自適應(yīng)了圖片的高了
然后去看了元素樣式的變化赠制,發(fā)現(xiàn)是因為<swiper >和<swiper-slide>第一次點擊的時候,先獲取到了canvas最開始的初始值挟憔。所以沒有自適應(yīng)圖片的寬高钟些。
所以第一次點擊的時候,需要將canvas的寬高賦值給<swiper >和<swiper-slide>的寬高绊谭,這樣子能做到第一次點擊的時候政恍,能把canvas初始的值替換。
修改后的代碼如下:
initCanvas() {
//這里必須要使用$nextTick()才能獲取到canvas
this.$nextTick( () => {
let myCanvas = document.querySelectorAll(".myCanvas"); //獲取所有的canvas
let ctx = [];
let _this = this;
Array.from(myCanvas).forEach((item,index) => {//循環(huán)canvas
ctx[index] = item.getContext("2d"); //獲取canvas的上下文
let img = [];
img[index] = new Image(); //創(chuàng)建img對象
img[index].src = this.data[index].path;//將路徑賦值給對象
img[index].onload = function() { //必須要圖片加載完成才能實現(xiàn)
ctx[index].canvas.width = img[index].width; //獲取圖片的寬賦值給canvas的寬达传,使canvas自適應(yīng)圖片寬
ctx[index].canvas.height = img[index].height; //獲取圖片的寬賦值給canvas的高篙耗,使canvas自適應(yīng)圖片高
ctx[index].drawImage(img[index], 0, 0); //繪制圖片
if(index == _this.activeIndex){ //另外這里的activeIndex是圖片數(shù)組的索引,用于點擊指定索引圖片就把圖片的寬高賦值給<swiper>和<swiper-slider>的寬高
_this.swiper.slides[index].style.height = ctx[index].canvas.offsetHeight+ "px";//將canvas的高賦值給<swiper-slide>
_this.swiper.wrapperEl.style.height =ctx[index].canvas.offsetHeight + "px";//將canvas的高賦值給<swiper >
_this.swiper.updateSize();//更新swiper的寬高
}
};
});
});
}
到這里就結(jié)束了宪赶。
不知道有沒有人會來看宗弯,哈哈哈哈,如果有來看的發(fā)現(xiàn)哪里不對請聯(lián)系我糾正逊朽,在此謝過~