ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

javaScript系列 [14]-Canvas绘图(图像)

2022-01-01 17:35:52  阅读:249  来源: 互联网

标签:Canvas 14 img javaScript ctx 画布 图像 var 255


本文将介绍Canvas画布图像绘制相关的技术细节。

Canvas画布图像绘制基础

**核心API**

绘制图像

语法

  • ctx.drawImage(image,dx,dy);
  • ctx.drawImage(image,dx,dy,dw,dh);
  • ctx.drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh);

作用 该方法可以将一幅图像绘制到Canvas画布中(源图像 - 目标图像)。
参数

  • dx        目标图像的原点坐标(X轴)
  • dy        目标图像的原点坐标(Y轴)
  • sx         源图像的原点坐标(X轴)
  • sy         源图像的原点坐标(Y轴)
  • sh         源图像的大小(高度)
  • sw        源图像的大小(宽度)
  • dw       目标图像的大小(宽度)
  • dh        目标图像的大小(高度)
  • image       绘制到canvas上面的图像(HTMLImageElement)

说明

[1] drawImage方法的第一个参数可以是HTMLImageElement类型的图像或HTMLCanvasElement类型的Canvas对象
    或者HTMLVideoElement类型的视频对象。
[2] drawImage方法可以将一幅图像(Canvas对象 」视频帧)的整体或部分绘制到Canvas中,在绘制到画布的时候可以
    任意指定绘制的位置以及缩放的比例。

图示

示例-01

<canvas id="canvas" width="800" height="1000"></canvas>

<script>

  //[1] 获取画布和对应的上下文
  var ctx  = document.getElementById("canvas").getContext("2d");

  //[2] 创建Image图像并设置数据源
  var img  = new Image();
  img.src = "PQ.png";
  img.alt = "我是一头小猪,我全家都是猪~";

  //[3] 监听图片加载完毕,绘制图片到画布
  img.onload = function(){

    //演示001
    //把图片绘制到Canvas画布上,绘制参考的原点坐标为(0,0),等比例缩放图片大小至宽高均为200
    ctx.drawImage(img,0,0,200,200)

    //演示002
    //剪切(剪切起点的参考坐标为[150,0])图片的一部分(右半边)绘制到画布上,绘制参考的原点坐标为(205,0)
    ctx.drawImage(img,150,0,150,300,205,0,150,300)

    //演示003
    //把图片(300 * 300)绘制到画布的指定位置,绘制参考的原点坐标为(360,0)
    ctx.drawImage(img,360,0);
  }
  
</script>

示例-02

<canvas id="canvas" width="2000" height="800"></canvas>

<script>

  //[1] 获取页面中的Canvas和对应的上下文
  var ctx  = document.getElementById("canvas").getContext("2d");

  //[2] 创建Image图像并设置数据源
  var img  = new Image();
  img.src  = "hero.png";

  //[3] 定义变量(源图片的宽度、高度、等分数量)
  var width  = 1620,height = 240,equalDivisionCount = 7;

  //[4] 监听Image图像的加载
  img.onload = function(){

    //[5] 等Image图像加载完成后先把完整的图像绘制到画布
    ctx.drawImage(img,0,0)

    //[6] 通过定时器来控制图像的绘制(动画)
    var i = 0;
    var timer = setInterval(function () {

      ctx.canvas.width = 2000;
      ctx.drawImage(
          img,
          width * i/equalDivisionCount,0,
          width/equalDivisionCount,height,
          width * i/equalDivisionCount,0,
          width/equalDivisionCount,height
      );
      i++;

      if(i == 7)
      {
        clearInterval(timer);
        ctx.drawImage(img,0,0)
      }
    },200);
  }
</script>

把Canvas画布转换为图像

语法 canvas.toDataURL()
作用 该方法用于将Canvas画布的内容转换为图像。
示例

<canvas id="canvas" width="200" height="200"></canvas>
<img src="" alt="">

<script>

  //[1] 获取页面中的img标签
  var oImage = document.getElementsByTagName("img")[0];
  //[2] 获取页面中的canvas标签
  var canvas = document.getElementById("canvas");
  //[3] 获取画布的上下文对象
  var ctx    = canvas.getContext("2d");
  
  //[4] 创建Image图片对象
  var img    = new Image();
  //[5] 设置Image图像的数据源
  img.src    = "PQ.png";
  //[6] 监听Image图像的加载
  img.onload = function () {
    
    //[7] 把图像绘制到Canvas画布中
    ctx.drawImage(img, 0,0,200,200);
    
    //[8] 把画布转换为图像保存并显示
    oImage.src = canvas.toDataURL();
  }
  
</script>

**备注** Canvas标签对象的toDataURL方法把画布转换为Base64表示的图像,关于Base64编码相关的知识点可以参考[数据安全系列 Base64](http://wendingding.com/2018/07/31/%E6%95%B0%E6%8D%AE%E5%AE%89%E5%85%A8%E7%B3%BB%E5%88%97%20Base64/)。

**操作图像像素的方法** **getImageData**

语法 ctx.getImageData(dx,dy,w,h)
作用 获取(复制)Canvas画布上指定矩形区域的像素数据。

putImageData

语法 ctx.putImageData(imgData,dx,dy,[dirtyX],[dirtyY],[dirtyWidth],[dirtyHeight]);
作用 该方法用于将指定ImageData对象的图像数据放回到画布上。
参数

  • imgData         规定要放回画布的ImageData对象
  • dx                   绘制到画布的位置(X坐标),以像素计
  • dy                   绘制到画布的位置(Y坐标),以像素计
  • dirtyX            部分截取imageData对象的位置(X坐标),默认为0。
  • dirtyY            部分截取imageData对象的位置(Y坐标),默认为0。
  • dirtyWidth           部分截取imageData对象的大小(宽度),默认为整幅图像的宽度。
  • dirtyHeight           部分截取imageData对象的大小(高度),默认为整幅图像的高度。

说明 putImageData()方法的后四个参数是可选的,在调用时要么传递3个参数要么传递7个参数。
示例

<canvas id="canvas" width="1000" height="400"></canvas>
<script>

  //[1] 获取页面中的Canvas画布
  var canvas = document.getElementById("canvas");
  //[2] 获取Cnavas的上下文对象
  var ctx    = canvas.getContext("2d");

  //[3] 在画布指定位置绘制一个填空矩形
  ctx.fillStyle="#f9f";
  ctx.fillRect(10,10,100,50);

  //演示001
  //[4] 获取画布中指定矩形区域的图像数据,然后再放到画布的指定位置(相当于复制)
  ctx.putImageData(ctx.getImageData(10,10,100,50),120,10);
  ctx.putImageData(ctx.getImageData(10,10,100,50),230,10,0,0,50,50);

  //[5] 创建Image图像
  var img = new Image();
  //[6] 设置Image图像的数据源
  img.src = "Yu.jpg";
  
  //[7] 监听Image图像的加载
  img.onload = function () {
    
    //[8] 把图像绘制到Canvas画布中
    ctx.drawImage(img,10,70,100,60);

    //演示002
    //[9] 获取画布中指定矩形区域的图像数据,然后再放到画布的指定位置(测试参数)
    var imgData = ctx.getImageData(10,70,100,60);
    /*
    * 3个参数的情况
    * 第一个参数:imageData对象
    * 第二个参数:绘制到画布的位置(X)
    * 第三个参数:绘制到画布的位置(Y)
    * */
    ctx.putImageData(imgData,120,70);

    /*
    * 7个参数的情况
    * 第一个参数:imageData对象
    * 第二个参数:绘制到画布的位置(X)
    * 第三个参数:绘制到画布的位置(Y)
    * 第四个参数:部分截取imageData对象的位置(X)
    * 第五个参数:部分截取imageData对象的位置(Y)
    * 第六个参数:部分截取imageData对象的大小(宽度)
    * 第七个参数:部分截取imageData对象的大小(高度)
    * */

    ctx.putImageData(imgData,230,70,50,0,100,60);
    ctx.putImageData(imgData,340,70,0,30,100,60);
    ctx.putImageData(imgData,450,70,0,0,100,30);
    ctx.putImageData(imgData,560,70,0,0,100,60);
  }

</script>

**注意** 在指定Canvas偏移量的时候,需要以CSS像素为单位,然而在指定图像数据中矩形区域时需要以设置像素为单位。此外,需要注意putImageData的后四个参数确定的区域被称为`脏矩形(dirty rectangle)`,当浏览器将脏矩形赋值到Canvas画布的时候,会默认将设备像素转换为CSS像素。

ImageData对象

在上文中介绍的getImageData()方法,其返回的是ImageData类型的对象,该对象包含widthheight以及data等三个属性。其中width代表的是以设备像素(device pixel)为单位的图像数据宽度,而height相应的代表着数据的高度,此外data是包含着各个设备像素数值的数组。

ImageData对象中,data属性所包含的每个数组元素,均对应表示图像数据中的相应像素值,每个像素中都存在四方面的信息,分别代表当前像素的颜色(RGB - Red 」Green 」Blue)和透明度(A - alpha)。这些信息都使用包含8个二进制位(2的八次方)的整数来表示,取值范围为 0 ~ 255

也就是说,

ImageData.data[0]代表的是红色数值,
ImageData.data[1]代表的是绿色数值,
ImageData.data[2]代表的是蓝色数值,
ImageData.data[3]代表的是透明度数值。

循环往复(如果数据数组的长度为n,那么`ImageData.data[n-4]`代表红色数值,其它的类推)。

createImageData方法

语法

  • ctx.createImageData(w,h);
  • ctx.createImageData(imageDataOther);

作用 该方法根据指定的宽高(目标对象的宽高)来创建新的空白的ImageData对象。
参数

  • w 指定的宽度。
  • h 指定的高度。
  • imageDataOther 参考的图像数据。

示例-01

<canvas id="canvas" width="600" height="400"></canvas>

<script>

  //[1] 获取页面中的Canvas画布和对应的上下文
  var canvas = document.getElementById("canvas");
  var ctx    = canvas.getContext("2d");

  //[2] 创建ImageData对象
  var imageData = ctx.createImageData(2,2);
  console.log(imageData);
  /*
   * data: Uint8ClampedArray(16) [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
   * height: 2
   * width:  2
   */

  //[3] 在画布中绘制红色矩形
  ctx.fillStyle = "red";
  ctx.fillRect(0,0,20,20);

  //[4] 获取画布中指定区域的图像数据
  imageData = ctx.getImageData(0,0,2,2);
  console.log(imageData);
  /*
   * data: Uint8ClampedArray(16) [255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,255]
   * height: 2
   * width:  2
   */

</script>

新对象的默认像素值transparent black,表示为(0, 0 , 0 , 0)。其中前三项代表的是颜色,最后一项代表的是透明度,color/alpha以数组形式存在,而数组的大小为ImageData对象的四倍。

示例说明

在上面的代码中ctx.createImageData(2,2)表示要创建2 * 2区域的空白ImageData对象。
调用方法后得到的ImageData对象拥有 2 * 2 = 4个像素,每个像素由数组中的四个元素表示。

打印ImageData属性得到的结果([4])显示为:
data:Uint8ClampedArray(16) [255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,255]
我们观察下标0~3的这组数据:255,0,0,255,尝试给出标注结果为255(Red),0(Green),0(Blue),255(alpha)

通过上面的分析,在掌握ImageData内部表示结构后,我们发现通过代码完全可以精准的控制图像的任何一个像素的显示,包括该像素的RGB颜色和透明度均可以控制,结合相应的算法和计算公式就可以简单的实现任何滤镜效果。

示例-02

<canvas id="canvas" height="400" width="600"></canvas>

<script>

  //[1] 获取画布和绘图上下文
  var canvas  = document.getElementById("canvas");
  var ctx     = canvas.getContext("2d");

  //[2] 创建ImageData对象(10 * 10)
  var imgData = ctx.createImageData(10,10);

  //[3] 设置ImageData图像使用红色填充
  var length  = imgData.data.length;
  for (var i = 0; i<length; i+=4)
  {
    imgData.data[i+0] = 255;
    imgData.data[i+1] = 0;
    imgData.data[i+2] = 0;
    imgData.data[i+3] = 255;
  }

  //[4] 把图像数据绘制到画布上面
  ctx.putImageData(imgData,0,0);

</script>

标签:Canvas,14,img,javaScript,ctx,画布,图像,var,255
来源: https://www.cnblogs.com/wendingding/p/15755707.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有