Canvas 使用指南

html-css023

Canvas 使用指南,第1张

canvas 的能力是通过 context 对象表现出来的,context一般称为绘图环境。

DOMString 为 "2d" 时,context 是 CanvasRenderingContext2D 对象;(本文重点)

DOMString 为 "webgl" 时,context 是 WebGLRenderingContext 对象;

DOMString 为 "webgl2" 时,context 是 WebGL2RenderingContext 对象;

DOMString 为 "bitmaprenderer" 时,context 是 ImageBitmap 对象;

CanvasRenderingContext2D 对象实例 instance 共有16个属性,只要设置了这些属性,就会影响 instance 调用绘制方法时的表现,常用的有:

注意:可使用 instance 的 save() 和 restore() 方法来临时修改 instance 的属性

1、一般用来保存数据,不展示在浏览器页面上,创建的两种方式:a、css 方式设置为 display:none;b、JS创建 document.createElement('canvas');

2、与HTML结合使用:可以采用 CSS 定位的方式,将 HTML 元素置于 canvas 元素之上,比如:在 canva 上叠加一个 div panel 作为某个开关控制界面;选景橡皮筋;时钟等

3、也可使用两个 canvas,一个用来显示,另一个用来做数据准备和处理,这种方式通常效率高,但比较耗费内存

1、准备一个绘制背景的函数,用于每次擦除上一次绘制的结果

2、绘制辅助线

3、监听事件,做坐标转换 windowToCanvas

4、绘制内容的保存于恢复

5、三事件

onmousedown:保存初始 canvas 绘制状态

onmousemove: 更新位置信息,并不断调用初始 canvas 绘制状态来擦除上一个绘制

onmouseup: 调用初始 canvas 绘制状态来擦除上一个绘制,并根据onmousemove保存的信息做最终绘制,将结果绘制在 canvas 上

fillStyle 和 strokeStyle 可以是任意有效的css颜色值或者渐变色以及图像Pattern

canvas 某一时刻只能有一条路径存在,这条路径可以包含多条子路径。用 beginPath 来开始一条新路径或清除上一次子路径

textAlign: left,center,right

textBaseline: top,middle,bottom

1、三属性 font,textAlign,textBaseline

2、三方法 strokeText, fillText, measureText

strokeText(text,x,y,maxWidth) 指定文本超过maxWidth会被缩放

measureText(text).width 返回指定文本宽度

3、水平垂直居中

注意每次变换前,用 save 和 restore 来保存原来绘制上下文

1、由路径定义的一片区域,如一个三角形,矩形,圆形,然后调用 clip 即可得到剪辑区域

2、默认和 canvas 大小一致

3、设置剪辑区域后,浏览器将只对该区域进行绘制

4、调用clip会把剪辑区域设为当前剪辑区域与当前路径定义的区域的交集,故clip 的调用经常在 save 和 restore 之间,这是为了防止剪辑区域越来越小

主要是 drawImage,getImageData,putImageData,createImageData 四个 API

作者:鲁小夫

链接:https://www.zhihu.com/question/26585266/answer/33518900

来源:知乎

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

canvas可以添加css3特效:

用css3动画,也就意味着需要依赖dom,动画都是作用在dom上的。而移动浏览器上的dom性能真是低下,因为这里面涉及到排版引擎,你只能通过减少节点和操作去规避问题,却很难解决。

而canvas动画把整个画布的控制权交给你了,动画性能的上限也由程序员来把握。

有人说canvas动画性能不如css3动画,在排版引擎不成为瓶颈的情况下是成立的,毕竟css3动画更方便,更与内容分离。但不要忘了,css3动画虽然不占用js主线程,却受排版引擎的限制,与整个页面的dom结构息息相关。你想想,假如dom真是万能的话,canvas是用来做啥的呢?事实上,像素操作比dom操作性能要高得多,就连2048这样简单的游戏,用dom来写,在手机上都觉得css3动画帧率不行了,我基本上只敢用dom来做找茬这样的无动画游戏。

总结,dom和css3动画是用来给内容布局加上特效的通用解决方案,在性能堪忧的移动浏览器上很可能会受排版性能所限,达不到理想的效果。而对性能有要求的特定场景,比如游戏,用canvas会有很大的提高,如果觉得事件和坐标管理麻烦的话,可以用一个好一些的游戏引擎。对于大量创建销毁对象的情况,例如打飞机游戏,你可能还需要用到对象池,毕竟js gc的开销也是够呛。

1.出现跨域的情况

这种情况只会出现在html2Canvas需生成的海报中的图片与当前环境不在同一个域下

2.解决方案

处理跨域,将接口返回的url处理为base64再进行处理或者后端直接返回base64

3.如何将url转换为base64?(利用canvas的toDataURL属性将url转为base64)

  function getImageBase64Data(imgSrc) {

    function getBase64(img) {

      let canvas = document.createElement("canvas")

      canvas.width = img.width

      canvas.height = img.height

      let ctx = canvas.getContext("2d")

      ctx.drawImage(img, 0, 0, canvas.width, canvas.height)

      let dataURL = canvas.toDataURL('image/jpeg')

      return dataURL

    }

    let baseUrl = new Promise(function (resolve, reject) {

      let image = new Image()

      image.crossOrigin = '*'// 图片处理跨域

      if (imgSrc.indexOf('data:image/jpegbase64') >-1) {

        image.src = imgSrc + '?v=' + Math.random()// 处理图片从缓存获取

      } else {

        image.src = imgSrc

      }

      image.onload = function () {

        let imageBase64Data = getBase64(image)

        resolve(imageBase64Data)

      }

    })

    return baseUrl

  }

4.使用html2Canvas生成海报

  const download = () => {

    let content = document.getElementById('promote-content')

    if (content) {

      html2canvas(content, { useCORS: true, allowTaint: true }).then(res => {

        const imgBase64 = res.toDataURL('image/jpeg')

        let link = document.createElement('a')

        link.style.display = 'none'

        link.href = imgBase64

        link.setAttribute('download', name + moment().format('YYYYMMDDHHmm'))

        document.body.appendChild(link)

        link.click()

        document.body.removeChild(link)

      })

    }

  }