8_1Canvas

线条样式

  1. 绘制直线,第五章知识简单回顾
  • lineWidth 设置或返回当前的线条宽度,单位为像素

  • lineCap 设置或返回线条的结束端点样式

    • butt 默认。向线条的每个末端添加平直的边缘。
    • round 向线条的每个末端添加圆形线帽。
    • square 向线条的每个末端添加正方形线帽。
    • "round" 和 "square" 会使线条略微变长。

    cxt.lineCap = "round";

  • lineJoin 设置或返回两条线相交时,所创建的拐角类型

    • miter 默认。创建尖角。
    • bevel 创建斜角。
    • round 创建圆角。

    cxt.lineJoin = "bevel";

  • miterLimit 设置或返回最大斜接长度。
    斜接长度指的是在两条线交汇处内角和外角之间的距离。该属性定义了斜连线长度和线条宽度的最大比率

    • 只有当 lineJoin 属性为 "miter" 时,miterLimit 才有效。
    • 边角的角度越小,斜接长度就会越大。为了避免斜接长度过长,我们可以使用 miterLimit 属性。
    • 如果斜接长度超过 miterLimit 的值,边角会以 lineJoin 的 "bevel" 类型来显示
    cxt.lineJoin = "miter";
    cxt.miterLimit=2;
    

矩形

  1. rect(x,y,w,h) 创建矩形。
  • fillRect(x,y,w,h) 绘制"被填充"的矩形。
  • strokeRect(x,y,w,h) 绘制矩形(无填充)。
  • clearRect(x,y,w,h) 在给定的矩形内清除指定的像素。
cxt.fillRect(100,100,100,100)
cxt.clearRect(110,110,80,80);

路径方法

  • fill() 填充当前绘图(路径)
  • stroke() 绘制已定义的路径
  • moveTo() 把路径移动到画布中的指定点,不创建线条
  • lineTo() 添加一个新点,然后在画布中创建从该点到最后指定点的线条
  • 开启和关闭路径
  • beginPath() 起始一条路径,或重置当前路径
  • closePath() 创建从当前点回到起始点的路径

绘制圆弧

  • arc() 创建弧/曲线(用于创建圆形或部分圆)

  • arcTo(x1,y1,x2,y2,r) 创建两切线之间的弧/曲线,点1坐标,点2坐标,半径

    ctx.beginPath();
    ctx.moveTo(200,300);
    ctx.arcTo(200,100,400,100,100)
    ctx.lineTo(400,100);
    ctx.stroke();
    
    //封装绘制圆角矩形的函数
        function roundRect(x,y,w,h,r){
            ctx.beginPath()
            ctx.moveTo(x,y+r)
            ctx.arcTo(x,y,x+w,y,r)
            ctx.arcTo(x+w,y,x+w,y+h,r)
            ctx.arcTo(x+w,y+h,x,y+h,r)
            ctx.arcTo(x,y+h,x,y,r)
            ctx.closePath()
            ctx.stroke()
        }
    
  • quadraticCurveTo(cx,cy,x,y) 创建二次贝塞尔曲线
    二次贝塞尔曲线需要两个点。第一个点是用于二次贝塞尔计算中的控制点,第二个点是曲线的结束点。曲线的开始点是当前路径中最后一个点。如果路径不存在,那么请使用 beginPath() 和 moveTo() 方法来定义开始点。

  • bezierCurveTo(c1x,c1y,c2x,c2y,x,y) 创建三次方贝塞尔曲线
    提示:三次贝塞尔曲线需要三个点。前两个点是用于三次贝塞尔计算中的控制点,第三个点是曲线的结束点。曲线的开始点是当前路径中最后一个点。如果路径不存在,那么请使用 beginPath() 和 moveTo() 方法来定义开始点。

  • clip() 从原始画布剪切任意形状和尺寸的区域

  • isPointInPath() 如果指定的点位于当前路径中,则返回 true,否则返回 false

// 二次方贝塞尔曲线
        ctx.beginPath()
        ctx.moveTo(50,50)
        ctx.quadraticCurveTo(150,200,300,50);
        ctx.stroke()

        //为了更好的理解绘制原理,这里我们将控制线也绘制出来
        ctx.beginPath()
        ctx.strokeStyle = "blue"
        ctx.lineWidth=1
        ctx.moveTo(50,50)
        ctx.lineTo(150,200)
        ctx.lineTo(300,50)
        ctx.stroke()

        //三次方贝塞尔曲线
        ctx.beginPath()
        ctx.lineWidth=3
        ctx.fillStyle = "orange"
        ctx.strokeStyle = "green"
        ctx.moveTo(350,50)
        ctx.bezierCurveTo(400,150,600,200,700,50);
        ctx.stroke()

        //为了更好的理解绘制原理,这里我们将控制线也绘制出来
        ctx.beginPath()
        ctx.strokeStyle = "blue"
        ctx.lineWidth=1
        ctx.moveTo(350,50)
        ctx.lineTo(400,150)
        ctx.moveTo(600,200)
        ctx.lineTo(700,50)
        ctx.stroke()

颜色、样式和阴影

  • fillStyle 设置或返回用于填充绘画的颜色、渐变或模式
  • strokeStyle 设置或返回用于笔触的颜色、渐变或模式
  • 阴影
    • shadowColor 设置或返回用于阴影的颜色
    • shadowBlur 设置或返回用于阴影的模糊级别
    • shadowOffsetX 设置或返回阴影距形状的水平距离
    • shadowOffsetY 设置或返回阴影距形状的垂直距离
  • 渐变
    • createLinearGradient(x0,y0,x1,y1) 创建线性渐变(用在画布内容上)
    • createRadialGradient(x0,y0,r0,x1,y1,r1) 创建放射状/环形的渐变(用在画布内容上)
    • addColorStop() 规定渐变对象中的颜色和停止位置
  • createPattern(image,"repeat|repeat-x|repeat-y|no-repeat")在指定的方向上重复指定的元素
    • createPattern() 方法在指定的方向内重复指定的元素。
    • 元素可以是图片、视频,或者其他 canvas 元素。
    • 被重复的元素可用于绘制/填充矩形、圆形或线条等等

CanvasPattern对象开始平铺图像的参考起点并不是我们当前绘制图形的左上角,而是整个canvas画布的左上角,确切地说,即canvas的起点坐标(0,0)。

注意:如果createPattern()方法的image参数值不是当前页面一个已经存在的Image对象或Canvas对象,那么我们需要等待浏览器将图片加载完毕后才能调用createPattern()方法及后续操作,否则将无法正确显示对应的图形。

// ctx.shadowColor = 'rgb(75, 71, 230)';
// ctx.shadowOffsetX = 5;
// ctx.shadowOffsetY = 5;
// ctx.shadowBlur = 10;
//
// ctx.fillRect(100,100,100,100);
//
// // var gradient = ctx.createLinearGradient(300,100,400,100);
// var gradient = ctx.createRadialGradient(350,150,10,350,150,100);
// gradient.addColorStop(0,'rgb(52, 213, 55)');
// gradient.addColorStop(0.25,'rgb(213, 96, 52)');
// gradient.addColorStop(0.5,'rgb(52, 203, 213)');
// gradient.addColorStop(0.75,'rgb(104, 52, 213)');
// gradient.addColorStop(1,'rgb(210, 213, 52)');
// ctx.fillStyle = gradient;
// ctx.fillRect(300,100,100,100);

var img = new Image();
img.src = './xj2.png';
img.onload = function () {
    // 创建CanvasPattern对象,指定上述图片进行水平的重复平铺
    var pattern = ctx.createPattern(img,"repeat");
    ctx.fillStyle= pattern;
    ctx.fillRect(0,0,500,800);
}

文本

  1. 属性
    • font 设置或返回文本内容的当前字体属性
    • textAlign 设置或返回文本内容的当前对齐方式
      • start 默认。文本在指定的位置开始。
      • end 文本在指定的位置结束。
      • center 文本的中心被放置在指定的位置。
      • left 文本左对齐。
      • right 文本右对齐。
    • textBaseline 设置或返回在绘制文本时使用的当前文本基线
      • top 文本基线是 em 方框的顶端。
      • bottom 文本基线是 em 方框的底端。
      • middle 文本基线是 em 方框的正中。
      • alphabetic 默认。文本基线是普通的字母基线。
      • ideographic 文本基线是表意基线。一般用于绘制中文或日文字符串。
      • hanging 文本基线是悬挂基线。一般用于绘制印度语字符串
    ```
    ctx.beginPath();
    ctx.textAlign = 'center';
    ctx.textBaseline = 'bottom';
    ctx.font = '50px 宋体';
    ctx.fillText('我',100,100);
    ctx.strokeText('我',200,200);
    document.write(ctx.measureText(ctx).width);
    ```
  • 方法
    • fillText() 在画布上绘制“被填充的”文本
    • strokeText() 在画布上绘制文本(无填充)
    • measureText() 返回包含指定文本宽度的对象 语法:context.measureText(text).width;

measureText的返回值是一个对象,但里面只有一个属性:width,本来文字的尺寸应该有width也有height,但canvas中的文字连行高都没有,所以measureText也没法得出高度。

measureText只是单纯的测量文字,与是否把文字写到canvas上无关。

转换

  • translate() 重新映射画布上的 (0,0) 位置(即移动坐标原点)
  • scale() 缩放当前绘图至更大或更小
    温馨提示:如果对绘图进行缩放,所有之后的绘图也会被缩放。定位也会被缩放。如果您 scale(2,2),那么绘图将定位于距离画布左上角两倍远的位置。
  • rotate() 旋转当前绘图
    注意参数单位为弧度。如需将角度转换为弧度,请使用 degrees*Math.PI/180 公式进行计算。
  • transform() 替换绘图的当前转换矩阵
  • setTransform() 将当前转换重置为单位矩阵。然后运行 transform()
//缩放\平移\旋转
ctx.translate(100,100);
ctx.scale(2,2);
ctx.rotate(15*Math.PI/180);

状态的保存和恢复

  1. save() 保存当前环境的状态
    ctx.save();// 保存当前绘图状态
  2. restore() 返回之前保存过的路径状态和属性
    ctx.restore();
    注意:可以多次保存,逐级恢复;最后保存的最先还原!restore总是还原离他最近的save点(已经还原的不能第2次还原到他)。
<script type="text/javascript">
var c = document.getElementById('canvas');
var ctx = c.getContext('2d');
ctx.lineWidth = 5;
ctx.fillStyle = 'rgb(76, 207, 106)';
ctx.strokeStyle = 'rgb(23, 26, 139)';

var i = 0;
var j=100;
var step=-1;
function test() {
    i++;
    if(j==200){
        step=-1
    }else if(j==1){
        step=1
    }
    j+=step;
    ctx.save()
    ctx.clearRect(0,0,c.width,c.height);
    ctx.scale(j/100,j/100);
    ctx.translate(c.width/2,c.height/2);
    ctx.rotate(i*15*Math.PI/180);
    ctx.translate(-50,-50);
    ctx.strokeRect(0,0,100,100);
    ctx.fillRect(0,0,100,100);
    ctx.restore()
}
setInterval('test()',10);
</script>
rect.gif

合成

  1. globalAlpha 设置或返回绘图的当前 alpha 或透明值
  • globalCompositeOperation 设置或返回新图像如何绘制到已有的图像上
    • source-over 默认。在目标图像上显示源图像。
    • source-atop 在目标图像顶部显示源图像。源图像位于目标图像之外的部分是不可见的。
    • source-in 在目标图像中显示源图像。只有目标图像内的源图像部分会显示,目标图像是透明的。
    • source-out 在目标图像之外显示源图像。只会显示目标图像之外源图像部分,目标图像是透明的。
    • destination-over 在源图像上方显示目标图像。
    • destination-atop 在源图像顶部显示目标图像。源图像之外的目标图像部分不会被显示。
    • destination-in 在源图像中显示目标图像。只有源图像内的目标图像部分会被显示,源图像是透明的。
    • destination-out 在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。
    • lighter 显示源图像 + 目标图像。这个值与顺序无关,如果源与目标重叠,就将两者的颜色值想加。得到的颜色值的最大取值为 255,结果就为白色。
    • copy 显示源图像。忽略目标图像。这个值与顺序无关,只绘制源,覆盖掉目标。
    • xor 使用异或操作对源图像与目标图像进行组合。这个值与顺序无关,只绘制出不重叠的源与目标区域。所有重叠的部分都变成透明的
      ctx.globalCompositeOperation = 'xor';

图像绘制

  1. drawImage(img,sx,sy,swidth,sheight,x,y,width,height) 向画布上绘制图像、画布或视频

        • img 规定要使用的图像、画布或视频。
        • sx 可选。开始剪切的 x 坐标位置。
        • sy 可选。开始剪切的 y 坐标位置。
        • swidth 可选。被剪切图像的宽度。
        • sheight 可选。被剪切图像的高度。
        • x 在画布上放置图像的 x 坐标位置。
        • y 在画布上放置图像的 y 坐标位置。
        • width 可选。要使用的图像的宽度。(伸展或缩小图像)
        • height 可选。要使用的图像的高度。(伸展或缩小图像)
    • drawImage(image,x,y) : 在canvas中(x,y)处绘制图片。
    • drawImage(image,x,y,width,height) : 在canvas中(x,y)处绘制图片,并将其缩放到指定的宽度和高度。
    • drawImage(image,sourceX,sourceY,sourceWidth,sourceHeight,x,y,width,height) :
      从图片中切割出一个矩形区域(sourceX,sourceY,sourceWidth,sourceHeight),缩放到指定的宽度和高度,并在canvas中(x,y)绘制出来。
    // 在图片未被加载钱不能对其绘制
    // window.onload=function () {
    //  ctx.drawImage(img,0,0);
    // }
    img.onload = function () {
        ctx.drawImage(img,0,0,100,100,0,0,100,100);
    }
    

像素操作

  1. 属性
    • width 返回 ImageData 对象的宽度(可以理解为一行像素的个数)
    • height 返回 ImageData 对象的高度(可以理解为一列像素的个数)
    • data 返回一个对象,其包含指定的 ImageData 对象的图像数据
      • 该对象包含每一个像素的四个rgba值,注意每个值都在0-255之间
      • 这个四个参数和CSS中讲的rgba颜色表示法原理相同,四个参数分别表示红、绿、蓝以及透明度。
      • 所不同的是这里的透明度取值也是0-255,255表示完全不透明,0表示完全透明
  • 方法
    • getImageData(x,y,w,h) 返回 ImageData 对象,该对象为画布上指定的矩形复制像素数据

    • putImageData(imgData,dx,dy,dirtyX,dirtyY,w,h) 把图像数据(从指定的 ImageData 对象)放回画布上
      首先讨论第一种最简单的putImageData用法,即putImageData(imgData,dirtyX,dirtyY),在解释其他参数

      • imgData 规定要放回画布的 ImageData 对象。
      • dx/dy ImageData 对象左上角的 x/y坐标,以像素计。即准备绘制图像的起点坐标.
      • [dirtyX,dirtyY,w,h]为一组可选参数,该参数确定了一个以dx和dy坐标原点的矩形,分别表示矩形的起点和宽高,该矩形把将要绘制的图像限定在矩形区域内.
      • 温馨提示:如果用绘入外部图片的办法测试该属性,在本地测试会出错,这是由于javaScript的同源策略对context.getImageDate的影响,该策略是基于浏览器的安全,禁用会造成安全隐患。可以通过搭建一个本地站点,将文档放到站点的方法测试。对于这一点在本课程中不做过多讲解。
    • createImageData() 创建新的、空白的 ImageData 对象

      • var imgData=context.createImageData(width,height);以指定的尺寸(以像素计)创建新的 ImageData 对象
      • var imgData=context.createImageData(imageData)创建与指定的另一个 ImageData 对象尺寸相同的新 ImageData 对象(不会复制图像数据)
      <script type="text/javascript">
      var c = document.getElementById('canvas');
      var ctx = c.getContext('2d');
      var img= new Image();
      img.onload = function () {
          ctx.drawImage(img,0,0,300,200);
      }
      img.src = './tooopen_sy_172649745666.jpg'
      
      function putImg() {
          var imgData = ctx.getImageData(0,0,300,200);
          ctx.putImageData(imgData,310,0,50,0,100,100);
      }
      
      // 反色绘制
      function fs() {
          ctx.clearRect(300,0,300,200);
          var imgData = ctx.getImageData(0,0,300,200);
          for (var i = 0; i < imgData.data.length; i+=4) {
              imgData.data[i+0] = 255-imgData.data[i+0];
              imgData.data[i+1] = 255-imgData.data[i+1];
              imgData.data[i+2] = 255-imgData.data[i+2];
              // imgData.data[i+3] = 255 - imgData.data[i+3];
          }
          ctx.putImageData(imgData,310,0);
      }
      
      // 滤镜
      function lj() {
          ctx.clearRect(300,0,300,200);
          var imgData = ctx.getImageData(0,0,300,200);
          for (var i = 0; i < imgData.data.length; i+=4) {
              imgData.data[i] = 0;
          }
          ctx.putImageData(imgData,310,0);
      }
      
    </script>
    ```
img.gif

canvas画布内容导出为图像

  1. toDataURL()这个方法能把画布里的图案转变成base64编码格式的png,然后返回 Data URL数据。
  • 温馨提示:以前多数浏览器不支持canvas中的内容直接右键保存为图片格式。但现在大多数浏览器都是支持的。

面向画布(Canvas)的JavaScript库

  1. EaselJS 是一个封装了 HTML5 画布(Canvas) 元素的 JavaScript 库。
  • jCanvaScript面向HTML5画布(canvas)的Javascript类库,它提供了许多方法用于简化处理HTML5画布(canvas)元素的内容,只要支持canvas和javascript的浏览器都可以使用它,包括iPhone、iPad和android等平台。
  • Processing.js是一个开放的编程语言,在不使用Flash或Java小程序的前提下,可以实现程序图像、动画和互动的应用。Processing.js是轻量,易于了解掌握的理想工具,可用于可视化的数据,创建用户界面和开发基于Web的游戏。
  • FABRIC.JS是一款简单而强大的JavaScript Canvas 库,提供了互动的对象模型,同时还包含 Canvas-to-SVG 解析器。
  • oCanvas是一个JavaScript框架,用于简化HTML5 Canvas标签的使用,可以利用对象来代替像素。 oCanvas 可以帮助你很容易的在 HTML5 的 Canvas 标签上创建对象,并且创建这些对象的动画。
  • jCanvas 就是一个 jQuery 的绘图插件,它封装了一些绘制图形的方法,只需编写几行代码即可生成图形。
  • RGraph是一个使用HTML5 Canvas标签实现的图表制作Library。利用该Library生成的Chart具有可交互性,当鼠标点击或移过时会显示相应的信息,可以动态加载Chart或对特殊点进行缩放。
  • Two.js 是面向现代 Web 浏览器的一个二维绘图 API。Two.js 可以用于多个场合:SVG,Canvas 和 WebGL,旨在使平面形状和动画的创建更方便,更简洁。
  • ......
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,907评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,546评论 1 289
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,705评论 0 238
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,624评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,940评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,371评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,672评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,396评论 0 195
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,069评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,350评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,876评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,243评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,847评论 3 231
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,004评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,755评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,378评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,266评论 2 259

推荐阅读更多精彩内容

  • 一:canvas简介 1.1什么是canvas? ①:canvas是HTML5提供的一种新标签 ②:HTML5 ...
    GreenHand1阅读 4,604评论 2 32
  • 一、canvas简介 1.1 什么是canvas?(了解) 是HTML5提供的一种新标签 Canvas是一个矩形区...
    Looog阅读 3,856评论 3 40
  • 一、简介 HTML5 中的定义:“它是依赖分辨率的位图画布,你可以在 canvas 上面绘制任何图形,甚至加载照片...
    destiny0904阅读 10,411评论 1 4
  • 神奇且强大的canvas 一.Canvas的基本介绍 1.什么是Canvas 定义:是HTML5提供的一种新标签,...
    Ainy尘世繁花终凋落阅读 10,358评论 1 18
  • 一、canvas简介 1.1 什么是canvas?(了解) 是HTML5提供的一种新标签 Canvas是一个矩形区...
    J_L_L阅读 1,450评论 0 4