结合vue使用canvas绘制轮播图心得

最近公司做的项目中有要求用canvas在图片上显示标注信息。

而图片是以弹出框的方式显示出来的,并且还是一个轮播图,

轮播图用的是swiper插件,
实现步骤:获取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的时候,犯了一个很大的错误,导致搞了很久都没有获取到这个元素,因为一开始就在网上各种搜搜搜,因为网上的都是绘制一张图片,而不是轮播图,所以只需要用document.getElementById("myCanvas")就能获取到canvas,然后就也跟着使用document.getElementById("myCanvas")来获取,但是很尴尬,总是获取不到,console.log打引出来的是undefined,另外我又试了用vue的获取dom元素的ref,结果还是一样的,我很纳闷,为什么别人也是这么做的我这么做就行不通,认真的观察一番,幡然醒悟,原来是因为我要实现的是轮播图,用了v-for来渲染出多个canvas,这时候用document.getElementById("myCanvas")来获取肯定是不对的,id具有唯一性,v-for把多个id为myCanvas渲染出来,显示是大错特错,真是太糊涂了。ref同理。
于是换了document.querySelectorAll(".myCanvas")来获取,终于就获取到了。
注意:这里还有个地方会导致获取不到canvas,因为使用的是vue,所以一开始直接获取canvas是获取不到的,需要保证canvas元素加载完成才能获取,否则获取不到,所以要用$nextTick()。
如果能认真点,就不会犯这种错误了。欸

这里是有20个canvas

初始化canvas和图片并绘制。

本来以为获取到canvas以后就万事大吉了,没想到在初始化这里还是有点坎坷的,
因为canvas是有多个的,所以不能像别的文章那样去获取,需要对canvas数组进行遍历,然后一个一个初始化,初始化的同时再通过new Image()的方式创建一个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) => {//循环canvas
          ctx[index] = item.getContext("2d"); //获取canvas的上下文
          let img = [];          
          img[index] = new Image(); //创建img对象
          img[index].src = this.data[index].path;//将路径赋值给对象
          img[index].onload = function() {       //必须要图片加载完成才能实现         
              ctx[index].canvas.width = img[index].width; //获取图片的宽赋值给canvas的宽,使canvas自适应图片宽
              ctx[index].canvas.height = img[index].height; //获取图片的宽赋值给canvas的高,使canvas自适应图片高       
              ctx[index].drawImage(img[index], 0, 0); //绘制图片          
          };
        });
      });
    }

实现到这里正常情况下基本是已经绘制完成了。但是无奈,还是出了bug

这是点击的第一张,它的高度是canvas初始时设置的高

当我切换到下一张的时候
这是切换下一张的图片,这时已经自适应图片了

再切换回原来那张,canvas的高度就自适应了图片的高了
切换回来后的图片

然后去看了元素样式的变化,发现是因为<swiper >和<swiper-slide>第一次点击的时候,先获取到了canvas最开始的初始值。所以没有自适应图片的宽高。
所以第一次点击的时候,需要将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) => {//循环canvas
          ctx[index] = item.getContext("2d"); //获取canvas的上下文
          let img = [];          
          img[index] = new Image(); //创建img对象
          img[index].src = this.data[index].path;//将路径赋值给对象
          img[index].onload = function() {       //必须要图片加载完成才能实现         
              ctx[index].canvas.width = img[index].width; //获取图片的宽赋值给canvas的宽,使canvas自适应图片宽
              ctx[index].canvas.height = img[index].height; //获取图片的宽赋值给canvas的高,使canvas自适应图片高       
              ctx[index].drawImage(img[index], 0, 0); //绘制图片          
          if(index == _this.activeIndex){ //另外这里的activeIndex是图片数组的索引,用于点击指定索引图片就把图片的宽高赋值给<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的宽高
            }
          };
        });
      });
    }

到这里就结束了。
不知道有没有人会来看,哈哈哈哈,如果有来看的发现哪里不对请联系我纠正,在此谢过~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,776评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,527评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,361评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,430评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,511评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,544评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,561评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,315评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,763评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,070评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,235评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,911评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,554评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,173评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,424评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,106评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,103评论 2 352

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,094评论 1 32
  • 一、JS前言 (1)认识JS 也许你已经了解HTML标记(也称为结构),知道了CSS样式(也称为表示),会使用HT...
    凛0_0阅读 2,763评论 0 8
  • 一、图形的组合方式 globalAlpha是一个介于0和1之间的值(包括0和1),用于指定所有绘制的透明度。默认值...
    空谷悠阅读 1,267评论 0 0
  • 神奇且强大的canvas 一.Canvas的基本介绍 1.什么是Canvas 定义:是HTML5提供的一种新标签,...
    Ainy尘世繁花终凋落阅读 10,744评论 1 18
  • 外出学习一周归来,我推开教室的门。“哇!老师你回来啦!”“嘿!Miss张,你可回来了!”孩子们七嘴八舌的问...
    张静祎阅读 550评论 0 0