美文网首页
Canvas 运用

Canvas 运用

作者: Primers | 来源:发表于2017-11-23 21:30 被阅读0次

    HTML5 中新增的一个相当于画布的标签,自带各种 API ,通过 JS 调用和搭配,实现图案绘制和想要的效果。

    下面这张截图就是由 canvas 在浏览器中生成的。

    First Step

    想要使用 canvas 标签,首先当然是要添加标签了。
    <canvas></canvas>
    在 JS 中获取该节点,
    var canvas = document.getELementById('canvas')
    然后获取 canvas 的上下文环境来获取绘制 API
    var context = canvas.getContext('2d')

    其中,一定要记住在 getContext 中传入参数 ' 2d '

    不然是没法获取到上下文环境的。

    Seconds Step

    现在画布有了,但是画布的大小还不知道呢, canvas 的默认大小是 300 x 150 个像素。
    但如果想要自定义大小的话,用常规的 CSS 样式设置的话并不适用于 canvas,
    因为在 canvas 内部,并不是使用一般的像素来作为绘制单位,若想设置其大小,

    - 使用内嵌属性 <canvas id= 'canvas' width= '300' height= '500></canvas>
    - 使用 JS 设置节点属性 canvas.width = 300; canvas.height = 500;

    当设置好这些后,就可以开始 “画画” 了,下面是各种常用的 API

    说明一下:

    canvas 绘制方法是一些基于状态的绘制,即多数方法只是为了设置 canvas 的状态,并非即时产生绘制效果,当设置好状态后,需要执行一些特定的绘制方法才能在浏览器中呈现,具体后面会讲到。
    另外,在 context 上下文中设置属性值时,应该设置成字符串形式,比如设置颜色是要设成 "#ccc" ,而上面的宽高的数字本应也要字符串,但会自动转化类型。

    注意:以下方法前面都省略了 context

    • .moveTo (x, y)

    可以想象一下画布上有一支虚拟的画笔,使用这个方法把画笔的笔尖定位到 xy 坐标上。

    • .lineTo (x, y)

    将笔尖移动到 xy 坐标,并与笔尖原坐标之间产生连线。可以理解成笔从原坐标到 xy 画一条线段。如果原坐标未定义,则效果相当于 .moveTo 。
    结合上述两个方法,这里有个栗子:

    // 想要画一条从(50,50)起笔,画到(100,150)的线段。
    
    context.moveTo (50, 50)
    context.lineTo (100, 150)
    
    // 若第一行使用 lineTo (50, 50) 有同样效果。因为在那之前笔尖未定义
    

    需要注意的是,浏览器窗口中并未真正出现了线段,请继续往后看。

    • .lineWidth = "10" / 10

    设置线段的宽度(粗细),
    注意,这里并不能加单位 px,canvas 里并不是用像素来做单位的。

    • .lineCap = "butt" (默认) / "round" / "square"

    按字面理解,就是线段的帽子。
    线段两端呈现的形状是什么,默认为平头,另外还有圆头和方头。
    方头看着好像没差别,但是其实和圆头一样是有突出来了,如下图左。
    有个小技巧,当两条粗线段相接时,使用方头可以完美接合,如下图右两个圈圈标记。

    • .lineJoin = "miter" / "bevel" / "round"

    两条或多条连续线段,在它们的接口(转折)处呈现的形状。
    默认为两条线段斜切出一个尖角,还可以呈现出斜切面和圆滑。如下图左黄圈处。

    • .miterLimit = "20" / 20

    在转折处为尖角时,会有一种情况:当两线段夹角越小,延伸出的尖角就越长,为了使画面处于可控范围,默认对尖角长度做限制,长度为10;超过后自动把转折效果设成 "bevel" 。如果想实现原效果,可手动增加 limit 值。长度判定方法如下图粉色标记。

    • .stroke ()

    通过调用这个方法,将前面设置的路线结合样式绘制出来,即成像。

    • .strokeStyle = "#ccc" / "rgb()" / "rgba()" / "pink"

    用在 stroke 前,这个方法常用于设置线段的颜色,必须设置为字符串,能接受与 JS 相同的颜色表述模式。另外,该方法还能设置渐变和模式。

    • .beginPath ()

    前面已经说过,canvas 是基于状态绘制的。当设置了一种样式状态比如颜色之后,状态会一直保留,会影响后面甚至之前的绘制的图形,比如:

    context.moveTo(50,50)
    context.lineTo(100,100)
    context.strokeStyle = "blue"
    context.stroke()
    《》
    context.moveTo(200,200)
    context.lineTo(300,300)
    context.strokeStyle = "red"
    context.stroke()
    !! 这里看似两次绘制了两条线段,而实际上是第二个stroke时连上面的线段也重新绘制一次,所以:
    !! 第二次设置的状态 “红色” 也会影响到第一条线段。
    

    而这里,引入一个我自己的理解——图层(类似于ps中),
    使用了 beginPath 方法后,程序将新建一个图层,
    这个图层独立于之前,图形、样式等状态将得到初始化,
    具体用法就是在上面书名号那行插入此方法,就可以得到两条不同颜色的线段。

    • .closePath ()

    看名字,我本以为这是和上面那个方法是一对,但事实上功能却没什么关系,该方法用于把线段封闭起来,形成一个封闭的区域,即你只要绘制两条有夹角的线段,然后调用 closePath 就可以得到一个三角形。

    • .fill ()

    填充,在封闭的区域中填充颜色。

    • .fillStyle = "#ccc" / "rgb()" / "rgba()" / "pink"

    设置填充方法的颜色。同上面的 strokeStyle ,还能填充渐变和模式。

    • .fillRect (x, y, w, h)

    绘制一个左上角位于 xy ,宽高为 wh 的矩形,默认为黑色。

    • .clearRect (x,y,w,h)

    类似于橡皮擦,清除左上角位于 xy ,宽高为 wh 的矩形区域。一般用于清空画布。
    context.clearRect (0, 0, canvas.width, canvas.height)

    下面会说到三个图形转换,如果熟悉 CSS3 的 transform 应该会挺了解的。
    下面说列出几点要点:

    • 图形转换是针对整个画布坐标系的转换,而不是单独某个对象。
    • 设置了图形转换,之后设置的绘图状态将会受到影响,而之前的则不会。
    • 多次设置图形转换,效果是传递的。
    • beginPath 也没法清除影响,使用反向转换或储存状态(后面介绍)解决。
    • .translate (x, y)

    位移,使坐标系在 xy 方向上位移,即改变原点位置(默认在画布左上角)。
    当多次设置位移而不清除的话,每次位移都是基于上次位移后的状态继续位移的。
    注意,在 JS 坐标系中 y 轴向下为正方向。

    • .rotate (45*Math.PI/180)

    旋转,以原点为圆心,坐标系旋转角度。角度必须转化为弧度制
    表现特点同上。即,连续设置两个45°等于设置一个90°

    • .scale (0.5, 2)

    伸缩,坐标系在 xy 方向上的伸缩(倍数)。表现特点也如上所述。
    下图中我用线段描绘三个起始点在 50,50 长宽都为50的矩形,
    但是中间插入了两次 scale (2,2) ,而最终出现了三个位置大小都不一样的矩形。
    观察以下可以看到,第一个最小的矩形就是代码描述的样子。
    而第二个矩形,因为 xy 轴伸长成了两倍,所以起始位置,和长宽都是原来两倍。
    第三个矩形,则是在第二个矩形的基础上,继续两倍。
    所以可以看出,图形转换的效果,是会传递的。
    最有趣的,三个矩形连线段宽度都是成倍增长的。

    既然图形转化这么厉害,设置了之后怎么复原呢?下面介绍
    • .save ()

    储存。该方法可以储存当前的状态,包括图形转换的状态。它恢复的是状态设置,而不影响已经绘制的内容。
    一般用于储存画布最初始的状态,然后在一顿绘制之后使用 restore 恢复初始状态。或者在设置图形转换之前储存一下,转换使用完后再 restore ,避免转换持续影响绘图。

    • .restore ()

    恢复成上次储存的状态,用法见上。

    上面再介绍填充的时候有介绍到,除了颜色还可以填充渐变,

    填充渐变,首先就要创建一个渐变模式。

    • .createLinearGradient (x1, y1, x2, y2)

    线性渐变,创建一个从 x1y1 点到 x2y2 点的线性渐变。默认为没有颜色。

    • Object.addColorStop (0.5, "red")

    为上面创建的渐变模式添加颜色锚点,至少两个或以上才会产生渐变效果,例如
    Object.addColorStop(0.5,"red"); Object.addColorStop(1,"blue");
    即表示从两个坐标之间,50%的位置开始,由红色渐变到 100% 的位置蓝色。
    而前面未涉及的50%则由临近的颜色填充,即红色。

    以上仅仅是创建了渐变状态而已,下面来演示一下整个填充的过程:
    • 为了方便起见一般会创建一个对象来储存渐变模式,
    • 给这个对象(渐变状态)添加锚点,
    • 把填充样式设置为该对象(渐变状态),
    • 最后在想要的范围内执行填充动作。(过程中请注意属性的对象)
    var gradient = context.createLinearGradient(0,0,1200,0)
    
    gradient.addColorStop(0,"red")
    gradient.addColorStop(.16,"orange")
    gradient.addColorStop(.34,"yellow")
    gradient.addColorStop(.51,"#0ef51f")
    gradient.addColorStop(.68,"#0beffb")
    gradient.addColorStop(.84,"blue")
    gradient.addColorStop(1,"#8000e8")
    
    context.fillStyle = gradient
    
    context.fillRect(0,0,1200,800)
    
    • .createRadialGradient (x1, y1, r1, x2, y2, r2)

    径向渐变,另一种渐变模式,实现效果的方法和特点同上。
    由一个以 x1y1 为圆心半径为 r1 的圆渐变到以 x2y2 为圆心半径为 r2 的圆。
    一般我们会把 r1 设置为零,实现由圆心渐变到圆周的效果。

    • .createPattern (img || canvas || video, repeatStyle)

    填充模式,这种更加强大,可以使图片、视频甚至是一个新的画布。
    使用方式与上面渐变相似,首先要创建想要填充的模式,传入对象和重复模式。
    重复模式可以选择 "no-repeat" / "repeat-x" / "repeat-y" / "repeat" ,下面有个栗子:

    // 创建一个新的画布
    var pattern = function () {
          var newCanvas = document.createElement('canvas')
          var context2 = newCanvas.getContext('2d')
    
          newCanvas.width = 100
          newCanvas.height = 100
          
          context2.fillStyle = "#000"
          context2.fillRect(0,0,100,100)
    
          retern newCanvas
    }
    
    // 将新画布作为旧画布的填充模式,传入新画布并设置重复
    var fillPattern = context.createPattern(pattern, "repeat") 
    context.fillStyle = fillPatern
    context.fillRect(0,0,400,400)
    
    • .arc (x, y, r, star, end, acw)

    画弧。在画布上画一段圆弧,这是画圆圈的主要方法。
    以 xy 为圆心,r 为半径的一个圆,圆弧开始点为 star 结束 为 end,
    计算起止点时,以右切点为 0 点,顺时针方向增加,并且始终不变。

    这里还有顺逆时针的概念,即从起始点绘制结束点是按顺时针还是逆时针。当 acw 为 false 或不填时,为顺时针。当 acw 为 true 时为逆时针。但无论如何,位置标点都不会变。
    以下举例:
    1、false;2、false, closePath;3、true, closePath;
    4、true;5、false, fill;6、true, fill

    图片来自慕课网

    利用圆弧来画圆角矩形

    • .arcTo (x1, y1, x2, y2, r)

    以参考线画一个弧,相对于上面那个,比较复杂,下面只简要说明要点。
    1、原笔尖所在的位置为起始点,到 x1y1 位置画一条线段。
    2、x1y1 位置到 x2y2 位置画一条线段。
    3、两条线段形成一个夹角,所画的圆弧就在夹角之间,半径为 r。
    4、圆弧与刚才的两条线段相切,起始点到第一个切点为直线。
    5、第一个切点之后开始圆弧,第二个切点曲线结束。
    6、圆弧起止点不一定在线段上,可以是在延长线上。

    • .quadraticCurveTo (x1, y1, x2, y2)

    二次贝塞尔曲线。
    x2y2 为终止点,x1y1 为控制点,将起始点和终止点之间的线段拉扯成弧。

    • .bezeirCurveTo (x1, y1, x2, y2, x3, y3 )

    三次贝塞尔曲线,x1y1 和 x2y2 为控制点。

    除了几何图形,文字肯定是不能少的。
    • .font = "bold 40px Arial"

    就像 CSS 中的 font 属性一样,可以并排设置多种字体属性。其中有五种:
    font-style || font-variant || font-weight || font-size || font-family

    • .strokeText (string, x, y, maxLength)

    描边字,这个方法传入的字符串,呈现出中空只有描边的文字,并将字符串的左上角定位在 xy,若设置了最大长度,当超过后会强制压缩字宽。该方法的样式同样受 strokeStyle 等相关状态影响。

    • .fillText (string, x, y, maxLength)

    填充字,出现经过填充的实心字,特点同上。并且接受 fillStyle 的各种。

    • .textAlign = "left" || "center" || "right"

    文字对齐,设置上面绘制的文字的对齐方式,以文字设置的起始点为基准。

    • .shadowColor

    • .shadowOffsetX

    • .shadowOffsetY

    • .shadowBlur)

    设置阴影状态。之后绘制的图形会有阴影。(颜色,X位移,Y位移,虚化程度)

    • .globalAlpha = 0.5

    全局透明度。

    • .globalCompositeOperation

    叠合操作模式。画布中先后绘制的内容会根据不同的模式来呈现效果。
    默认为后绘制的覆盖先绘制的,也可以设置为先绘制的覆盖后绘制的,甚至可以让两次绘制重叠部分镂空或者提亮颜色。
    属性模式有以下是一种,并且我个人制作了个演示页面,展示不同模式的效果。
    source-over || source-atop || source-in || source-out || destination-over || destination-atop || destination-in || destination-out || lighter || copy || xor

    • .clip()

    剪辑区域。先设置路径再调用。把画布裁剪成刚才设置的路径区域。canvas 标签并没有变小,但是之后的绘制只会在该裁剪区域内可见。

    • .isPointInPath(x, y)

    判定 xy 坐标是否在当前设置的路径内。传回布尔值。Demo (暂时,可能日后会更新)


    写在后面

    可以看到 canvas 标签还是很强大的,它的功能当然不止这些,canvas 的 context 支持自定义,可以自己添加一些原创的方法和规则进去;canvas 甚至能进行一些图像处理,例如打马赛克,添加滤镜等等,在此篇章中就暂不深入介绍了。
    待把这些基础的玩出花,再去进一步扩展也不迟,
    同时,canvas 也还在不断地发展,各个浏览器也慢慢一步步兼容,所以了解 canvas 的最新情况是有必要的。这里可以参考以下W3C 的 canvas 文档。



    Wait me back

    相关文章

      网友评论

          本文标题:Canvas 运用

          本文链接:https://www.haomeiwen.com/subject/ijcbvxtx.html