canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)

线的样式

线宽 lineWidth

lineWidth 是context对象的属性,用于描述线条的宽度,属性值为整数,默认值为1px。

  • strokeRect()方法绘制的矩形实际宽度是(width+lineWidth),实际高度是(height+lineWidth)
  • arc()方法绘制的圆形实际半径为(radius+lineWidth)。
             //lineWidth值为5
             cxt.lineWidth = 5;
             cxt.moveTo(20, 20);
             cxt.lineTo(180, 20);
             cxt.stroke();

             //lineWidth值为10
             cxt.beginPath();
             cxt.lineWidth = 10;
             cxt.moveTo(20, 70);
             cxt.lineTo(180, 70);
             cxt.stroke();

             //lineWidth值为15
             cxt.beginPath();
             cxt.lineWidth = 15;
             cxt.moveTo(20, 120);
             cxt.lineTo(180, 120);
             cxt.stroke();

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第1张图片

必须使用beginPath()方法来开始新的路径,才可以绘制一个新的lineWidth属性

             cxt.lineWidth = 5;
             cxt.arc(70, 70, 50, 0, -90 * Math.PI / 180, false);
             cxt.stroke();

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第2张图片

线帽 lineCap

lineCap 是context对象的属性,用于描述线条开始处和结尾处的线帽样式,取值如下:

  • butt (默认值) 无线帽
  • round 圆形线帽
  • square 正方形线帽
             cxt.lineWidth = 16;

             //lineCap值为默认值(butt)
             cxt.moveTo(20, 20);
             cxt.lineTo(180, 20);
             cxt.stroke();

             //lineCap值改为round
             cxt.beginPath();
             cxt.lineCap = "round";
             cxt.moveTo(20, 70);
             cxt.lineTo(180, 70);
             cxt.stroke();

             //lineCap值改为square
             cxt.beginPath();
             cxt.lineCap = "square";
             cxt.moveTo(20, 120);
             cxt.lineTo(180, 120);
             cxt.stroke();

必须使用beginPath()方法来开始新的路径,才可以绘制一个新的 lineCap 属性

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第3张图片

round和square值会使线条稍微变长一点,因为它们给线条增加了线帽部分。
canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第4张图片

  • 取值为round:每条线的头和尾都增加一个半圆,半圆的直径为线宽长度。
  • 取值为square:每条线的头和尾都增加一个长方形,长方形的长度为线宽的一半,高度保持为线宽长度。
             cxt.moveTo(50, 50);
             cxt.lineTo(100, 50);
             cxt.lineTo(50, 100);
             cxt.lineTo(100, 100);
             cxt.lineWidth = 12;
             cxt.lineCap = "round";
             cxt.stroke();

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第5张图片
lineCap属性只对线条的开始处和结尾处这两个地方起作用,而线段与线段交接的地方依然是“尖角”。

线的交点 lineJoin

lineJoin 是context对象的属性,用于描述两个线条交接处的样式,取值如下:

  • miter(默认值)尖角,线段在交接处延伸直至交于一点
  • round 圆角,圆角所在圆的直径等于线宽长度。
  • bevel 斜角,斜角所在正方形的对角线长等于线宽长度。
    canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第6张图片
             cxt.moveTo(50, 50);
             cxt.lineTo(100, 50);
             cxt.lineTo(50, 100);
             cxt.lineTo(100, 100);
             cxt.lineWidth = 12;
             cxt.lineJoin = "miter";
             cxt.stroke();

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第7张图片

 cxt.lineJoin = "round";

在这里插入图片描述

 cxt.lineJoin = "bevel";

在这里插入图片描述

虚线 setLineDash()

IE不支持
cxt.setLineDash(array);

array 是一个数组,如[10,5]表示的是“10px实线”和“5px空白”重复拼凑组合而成的线型。数组[10,5,5,5]表示的是“10px实线、5px空白、5px实线、5px空白”重复拼凑组合而成的线型。

             cxt.strokeStyle = "red";
             cxt.setLineDash([10,5]);
             cxt.strokeRect(50, 50, 80, 80);

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第8张图片

绘制文本

文本属性:

  • font 文本样式(含大小,粗细,字体等),和css用法一样。默认值为10px sans-serif。
context.font = "font-style font-weight font-size/line-height font-family";
cxt.font = "bold 30px 微软雅黑";
  • fillStyle 填充样式
  • strokeStyle 描边样式

文本方法:

  • strokeText() 绘制描边文字
  • fillText() 绘制填充文字
  • measureText() 获取文本长度,单位为px(实际是占据空间矩形的长度)
// text 为目标文本
var length = cxt.measureText(text).width;

描边文本(空心文本)

strokeText(text , x , y , maxWidth)
  • text 文本内容
  • x 文本最左侧的坐标
  • y 文本最下方的坐标
  • maxWidth (可选) 文本最大宽度,若文本超出最大宽度,会强制压缩
var text = "绿叶学习网";
cxt.font = "bold 30px 微软雅黑";
cxt.strokeStyle = "purple";
cxt.strokeText(text, 30, 60);

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第9张图片
cxt.strokeText(text,30,60)改为cxt.strokeText(text,30,60,100)后,文本会压缩
在这里插入图片描述

填充文本

fillText(text , x , y , maxWidth)
  • text 文本内容
  • x 文本最左侧的坐标
  • y 文本最下方的坐标
  • maxWidth (可选) 文本最大宽度,若文本超出最大宽度,会强制压缩
var text = "绿叶学习网";
cxt.font = "bold 30px 微软雅黑";
cxt.fillStyle = "purple";
cxt.fillText(text,30,60);

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第10张图片
cxt.fillText(text,30,60) 改为cxt.fillText(text,30,60,100) 会压缩文字
在这里插入图片描述

文本水平居中

var text = "绿叶学习网";
cxt.font = "20px bold";
var textWidth = cxt.measureText(text).width;
var canvasWidth = cnv.width;
var xPosition = canvasWidth / 2 - textWidth / 2;

cxt.fillStyle = "purple";
cxt.fillText(text, xPosition, 50);

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第11张图片

文本水平对齐方式 textAlign (用得少)

—— left 左对齐-在指定的横坐标的左侧开始
—— right 右对齐-在指定的横坐标的右侧结束
—— start 与阅读方向开始位置对齐(左到右阅读环境中,表现为左对齐)
—— end 与阅读方向结束位置对齐(左到右阅读环境中,表现为右对齐)
—— center 文本的中心被放置在指定的横坐标

//在横坐标150处绘制一条竖线
cxt.strokeStyle = "purple";
cxt.moveTo(150, 0);
cxt.lineTo(150, 200);
cxt.stroke();

cxt.font = "15px Arial";

cxt.textAlign = "start";
cxt.fillText("textAlign取值为start", 150, 30);
cxt.textAlign = "left";
cxt.fillText("textAlign取值为left", 150, 60);
cxt.textAlign = "end";
cxt.fillText("textAlign取值为end", 150, 90);
cxt.textAlign = "right";
cxt.fillText("textAlign取值为right", 150, 120);
cxt.textAlign = "center";
cxt.fillText("textAlign取值为center", 150, 150);

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第12张图片

文本垂直对齐方式 textBaseline (用得少)

  • alphabetic 文本基线是普通英文字母的基线
  • top 文本基线是em方框的顶端
  • middle 文本基线是em方框的中心
  • bottom 文本基线是em方框的底端
//在纵坐标100处绘制一条横线
cxt.strokeStyle = "purple";
cxt.moveTo(0, 100);
cxt.lineTo(300, 100);
cxt.stroke();

cxt.font = "20px Arial";
cxt.textBaseline = "alphabetic";
cxt.fillText("alphabetic", 10, 100);
cxt.textBaseline = "top";
cxt.fillText("top", 110, 100);
cxt.textBaseline = "middle";
cxt.fillText("middle", 160, 100);
cxt.textBaseline = "bottom";
cxt.fillText("bottom", 230, 100);

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第13张图片

操作图片

图片渲染

cxt.drawImage(image ,dx , dy);
  • image 为页面中的img元素,或js创建的image对象
  • dx,dy 为图片左上角的坐标
    canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第14张图片
//创建image对象
var image = new Image();
image.src = "images/princess.png";
// 必须等图片加载完后,再进行渲染
image.onload = function () {
    cxt.drawImage(image, 40, 20);
}

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第15张图片

<img id="pic" src="images/princess.png" alt=""/>
/*隐藏HTML中的img元素*/
#pic{display:none;}
var image = $$("pic");
cxt.drawImage(image, 40, 20);

图片取自页面中的img元素时,图片已完成了加载,所以无需添加 image.onload 等待加载。此时一般会用CSS隐藏图片,避免图片在页面中显示多次图片。

图片缩放

常用于Canvas游戏开发

cxt.drawImage(image , dx , dy ,dw , dh)
  • image 为页面中的img元素,或js创建的image对象
  • dx, dy 为图片左上角的坐标
  • dw , dh 为图片的宽度和高度
    canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第16张图片
var image = new Image();
image.src = "images/princess.png";
image.onload = function () {
    cxt.drawImage(image, 40, 20, 60, 60);
}

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第17张图片

图片裁剪(矩形裁剪)

此方法可以将部分图像复制到画布,类似于CSSSprite技术,从而使得图片只需要加载一次即可,这样极大地提高了速度(常用于Canvas游戏开发)。

cxt.drawImage(image , sx , sy , sw, sh , dx , dy , dw , dh)
  • image 为页面中的img元素,或js创建的image对象
  • sx, sy 为源图片截取部分的左上角坐标
  • sw , sh 为源图片截取部分的宽度和高度
  • dx, dy 为canvas中图片左上角的坐标
  • dw , dh 为canvas中图片的宽度和高度
    canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第18张图片
var image = new Image();
image.src = "images/princess.png";
image.onload = function () {
    cxt.drawImage(image, 0, 0, 80, 80, 40, 20, 80, 80);
}

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第19张图片

图片切割 clip()(自定义形状的裁剪)

//第1步,绘制基本图形,用来切割
cxt.beginPath();
cxt.arc(70, 70, 50, 0, 360 * Math.PI / 180, true);
cxt.closePath();
cxt.stroke();

//第2步,使用clip()方法,使得切割区域为上面绘制的基本图形
cxt.clip();

//第3步,绘制一张图片
var image = new Image();
image.src = "images/princess.png";
image.onload = function () {
    cxt.drawImage(image, 10, 20);
}

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第20张图片

图片平铺

var pattern = cxt.createPattern(image , type);
cxt.fillStyle = pattern;
cxt.fillRect();
  • type 来指定平铺方式
    —— repeat (默认值) 在水平方向和垂直方向同时平铺
    —— repeat-x 只在水平方向平铺
    —— repeat-y 只在垂直方向平铺
    —— no-repeat 只显示一次

createPattern()方法不仅可以用于平铺图片,还可以用于平铺其他canvas元素或者平铺video元素(即视频),使用图片会有一定的加载时间,因此在实际开发中,对于一些基本的背景图案,会使用Canvas来绘制。

             var myImg = new Image();
             myImg.src = "images/flower.png";

             myImg.onload = function () {
                 var pattern = cxt.createPattern(myImg, "repeat");
                 cxt.fillStyle = pattern;
                 cxt.fillRect(0, 0, cnv.width, cnv.height);
             }

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第21张图片

var pattern = cxt.createPattern(myImg, "repeat-x");

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第22张图片

var pattern = cxt.createPattern(myImg, "repeat-y");

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第23张图片

  • 平铺 canvas
//创建canvas元素
var bgCanvas = document.createElement("canvas");
bgCanvas.width = 20;
bgCanvas.height = 20;

//在新创建的canvas中画一个圆
var bgCxt = bgCanvas.getContext("2d");
bgCxt.beginPath();
bgCxt.arc(10, 10, 10, 0, 360 * Math.PI / 180, true);
bgCxt.closePath();
bgCxt.fillStyle = "HotPink";
bgCxt.fill();

//平铺canvas
var pattern = cxt.createPattern(bgCanvas, "repeat-x");
cxt.fillStyle = pattern;
cxt.fillRect(0, 0, 200, 200);

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第24张图片

用图片填充文字(用得少)

//创建image对象
var image = new Image();
image.src = "images/princess.png";

image.onload = function () {
    var text = "绿叶学习网";
    cxt.font = "bold 22px 微软雅黑";
    var pattern = cxt.createPattern(image, "no-repeat");
    cxt.fillStyle = pattern;
    cxt.fillText(text, 10, 50);
}

在这里插入图片描述

用图片填充图形

//创建image对象
var image = new Image();
image.src = "images/princess.png";

image.onload = function () {
    cxt.beginPath();
    cxt.arc(50, 50, 50, 0, 360 * Math.PI / 180, false);
    cxt.closePath();
    var pattern = cxt.createPattern(image, "no-repeat");
    cxt.fillStyle = pattern;
    cxt.fill();
}

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第25张图片

图片特效

更高级的图片处理,如调整图片亮度、变黑白图片等需要对图片进行像素级处理,基本流程为:

  1. 获取图片的像素信息

    var imgData = cxt.getImageData(x , y , width , height); 
    var data = imgData.data;
    

    —— x,y 为目标图片区域左上角的坐标
    —— widht ,height 为图片区域的宽和高

    此处的 imgData 是一个canvasPixelArray对象,其有属性 data,属性值为[r1,g1,b1,a1,r2,g2,b2,a2,……] 格式的描述一张图片像素数据的数组。imgData.data 数组中每四个数存储着1个像素的rgba颜色值,这四个数分别是该像素的红(r)、绿(g)、蓝(b)、透明度(a)。

    imgData.data.length 即图片像素的总量。

  2. 修改图片的像素信息
    即对 imgData.data 数组进行遍历处理,如颜色反转:

    for (var i = 0; i < data.length; i += 4) 
    {
       data[i + 0] = 255 - data[i + 0];
       data[i + 1] = 255 - data[i + 1];
       data[i + 2] = 255 - data[i + 2];
    }
    
  3. 通过新像素信息渲染图片

    cxt.putImageData(image , x , y); 
    

    —— image 为 canvasPixelArray对象(修改后的图片像素信息)
    —— x,y 为图片渲染时的左上角坐标

调整亮度(变亮变暗)

实现算法:
将红、绿、蓝三个通道值,分别同时加上一个正值或负值。

             var image = new Image();
             image.src = "images/princess.png";

             image.onload = function () {
                 cxt.drawImage(image, 10, 10);
                 var imgData = cxt.getImageData(10, 10, 120, 120);
                 var data = imgData.data;
                 //遍历每个像素
                 for (var i = 0; i < data.length; i += 4) {
                      var a = 50;
                      data[i + 0] += a;
                      data[i + 1] += a;
                      data[i + 2] += a;
                 }
                 //在指定位置输出图片
                 cxt.putImageData(imgData, 140, 10);
             }

a = 50 变亮的效果:
canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第26张图片
a = -50 变暗的效果:
canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第27张图片

调整透明度

cxt.globalAlpha用于调整整个Canvas的透明度,这里只是希望将图片透明化

实现算法:
将每一个像素的透明度乘以n,n的取值范围为0.0~1.0

             var image = new Image();
             image.src = "images/princess.png";

             image.onload = function () {
                 cxt.drawImage(image, 10, 10);
                 var imgData = cxt.getImageData(10, 10, 120, 120);
                 var data = imgData.data;
                 //遍历每个像素
                 for (var i = 0; i < data.length; i += 4) {
                      data[i + 3] = data[i + 3] * 0.3;
                 }
                 //在指定位置输出图片
                 cxt.putImageData(imgData, 140, 10);
             }

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第28张图片

颜色反转(底片)

即图片颜色颠倒,效果类似相机的底片。

实现算法:
红、绿、蓝这三个通道的像素取各自的相反值,也就是(255-原值)

             var image = new Image();
             image.src = "images/princess.png";

             image.onload = function () {
                 cxt.drawImage(image, 10, 10);
                 var imgData = cxt.getImageData(10, 10, 120, 120);
                 var data = imgData.data;
                 //遍历每个像素
                 for (var i = 0; i < data.length; i += 4) {
                       data[i + 0] = 255 - data[i + 0];
                       data[i + 1] = 255 - data[i + 1];
                       data[i + 2] = 255 - data[i + 2];
                 }
                 //在指定位置输出图片
                 cxt.putImageData(imgData, 140, 10);
             }

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第29张图片

黑白效果(灰度图)

指将彩色图片转换成黑白图片。

实现算法:
首先取红、绿、蓝三个通道的平均值,也就是(data[i+0]+data[i+1]+data[i+2])/3。然后data[i+0]、data[i+1]和data[i+2]全部保存为这个平均值。

             var image = new Image();
             image.src = "images/princess.png";

             image.onload = function () {
                 cxt.drawImage(image, 10, 10);
                 var imgData = cxt.getImageData(10, 10, 120, 120);
                 var data = imgData.data;
                 //遍历每个像素
                 for (var i = 0; i < data.length; i += 4) {
                      var average = (data[i + 0] + data[i + 1] + data[i + 2] + data[i + 3]) / 3;
                      data[i + 0] = average;  //红
                      data[i + 1] = average;  //绿
                      data[i + 2] = average;  //蓝
                 }
                 //在指定位置输出图片
                 cxt.putImageData(imgData, 140, 10);
             }

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第30张图片
效果优化——加权平均

             var image = new Image();
             image.src = "images/princess.png";

             image.onload = function () {
                 cxt.drawImage(image, 10, 10);
                 var imgData = cxt.getImageData(10, 10, 120, 120);
                 var data = imgData.data;
                 //遍历每个像素
                 for (var i = 0; i < data.length; i += 4) {
                      var grayscale = data[i] * 0.3 + data[i + 1] * 0.6 + data[i + 2] * 0.1;
                      data[i + 0] = grayscale;  //红
                      data[i + 1] = grayscale;  //绿
                      data[i + 2] = grayscale;  //蓝
                 }
                 //在指定位置输出图片
                 cxt.putImageData(imgData, 140, 10);
             }

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第31张图片

复古

使得图片有一种古旧效果。

实现算法:
将红、绿、蓝三个通道,分别取这三个值的某种加权平均值。

             var image = new Image();
             image.src = "images/princess.png";

             image.onload = function () {
                 cxt.drawImage(image, 10, 10);
                 var imgData = cxt.getImageData(10, 10, 120, 120);
                 var data = imgData.data;
                 //遍历每个像素
                 for (var i = 0; i < data.length; i += 4) {
                      var r = data[i + 0];
                      var g = data[i + 1];
                      var b = data[i + 2];

                      data[i + 0] = r * 0.39 + g * 0.76 + b * 0.18;
                      data[i + 1] = r * 0.35 + g * 0.68 + b * 0.16;
                      data[i + 2] = r * 0.27 + g * 0.53 + b * 0.13;
                 }
                 //在指定位置输出图片
                 cxt.putImageData(imgData, 140, 10);
             }

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第32张图片

红色蒙版

让图片呈现一种偏红的效果

实现算法:
将红通道(r)赋值为红、绿、蓝这三个的平均值,并且将绿通道、蓝通道都赋值为0。

同样的方式可以实现类似效果的绿色蒙版、蓝色蒙版等。

             var image = new Image();
             image.src = "images/princess.png";

             image.onload = function () {
                 cxt.drawImage(image, 10, 10);
                 var imgData = cxt.getImageData(10, 10, 120, 120);
                 var data = imgData.data;
                 //遍历每个像素
                 for (var i = 0; i < data.length; i += 4) {
                      var r = data[i + 0];
                      var g = data[i + 1];
                      var b = data[i + 2];

                      var average = (r + g + b) / 3;
                      data[i + 0] = average;
                      data[i + 1] = 0;
                      data[i + 2] = 0;
                 }
                 //在指定位置输出图片
                 cxt.putImageData(imgData, 140, 10);
             }

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第33张图片

创建像素区域 createImageData()

cxt.createImageData(sw,sh);      //第1种格式

sw,sh 为像素区域的宽和高

cxt.createImageData(imageData);  //第2种格式

imageData为一个像素对象,最终像素区域的宽高和这个像素对象相同

createImageData()和putImageData()配合使用是对一个区域进行像素操作的。只有使用createImageData()创建了一个区域,才可以对该区域进行相应的像素操作。

             var imgData = cxt.createImageData(100, 100);
             var data = imgData.data;
             for (var i = 0; i < 100 * 100 * 4; i += 4) {
                  data[i + 0] = 0;
                  data[i + 1] = 0;
                  data[i + 2] = 255;
                  data[i + 3] = 255;
             }
             cxt.putImageData(imgData, 20, 20);

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第34张图片

             var image = new Image();
             image.src = "images/princess.png";

             image.onload = function () {
                 cxt.drawImage(image, 0, 0, 60, 60);
                 //获取一个图片的imgData
                 var imgData1 = cxt.getImageData(0, 0, 60, 60);
                 //利用这个图片的imgData作为参数
                 var imgData2 = cxt.createImageData(imgData1);
                 var data = imgData2.data;
                 for (var i = 0; i < imgData2.width * imgData2.height * 4; i += 4) {
                       data[i + 0] = 0;
                       data[i + 1] = 0;
                       data[i + 2] = 255;
                       data[i + 3] = 255;
                  }
                  cxt.putImageData(imgData2, 80, 0);
             }

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第35张图片

变换元素

变换可用于图形,也可以用于图片和文字。
变换的本质都是通过“变换矩阵transform()”实现的,涉及到线性代数,平时并不会用,不必深究,简单了解即可:

  • translate(e,f)等价于transform(1,0,0,1,e,f)。
  • scale(a,d)等价于transform(a,0,0,d,0,0)。
  • rotate(θ)等价于transform(cosθ,sinθ,-sinθ,cosθ,0,0)。

setTransform() 与 transform() 用法相同,只是transform() 是在变换后的基础上继续变换,而setTransform() 会重置图形的状态,再进行变换。

             var cnv = $$("canvas");
             var cxt = cnv.getContext("2d");

             cxt.fillStyle = "yellow";
             cxt.fillRect(0, 0, 100, 50)

             cxt.setTransform(1, 0.5, -0.5, 1, 30, 10);
             cxt.fillStyle = "red";
             cxt.fillRect(0, 0, 100, 50);

             cxt.setTransform(1, 0.5, -0.5, 1, 30, 10);
             cxt.fillStyle = "blue";
             cxt.fillRect(0, 0, 100, 50);

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第36张图片
将 setTransform 改为 transform 后效果为
canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第37张图片

平移 translate()

本质是移动了整个坐标轴

cxt.translate(x,y);
  • x 为x轴方向的移动距离,单位px,为正,则是向右移动,为负,则向左移动
  • y 为y轴方向的移动距离,单位px,为正,则是向下移动,为负,则向上移动
DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
   <title>title>
   <meta charset="utf-8" />
   <script type="text/javascript">
        function $$(id) {
             return document.getElementById(id);
        }
        window.onload = function () {
             var cnv = $$("canvas");
             var cxt = cnv.getContext("2d");

             //绘制初始图形
             cxt.fillStyle = "HotPink";
             cxt.fillRect(30, 30, 50, 50);

             $$("btn").onclick = function () {
                  // 清空canvas
                  cxt.clearRect(0, 0, cnv.width, cnv.height);
                  cxt.translate(10, 10);
                  cxt.fillStyle = "HotPink";
                  // 重绘
                  cxt.fillRect(30, 30, 50, 50);
             }
        }
   script>
head>
<body>
   <canvas id="canvas" width="200" height="150" style="border:1px dashed gray;">canvas><br />
   <input id="btn" type="button" value="移动"/>
body>
html>

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第38张图片

缩放 scale ()

cxt.scale(x,y); 
  • x 为x轴方向的缩放倍数
  • y 为y轴方向的缩放倍数
    x,y 的值为0~1时为缩小,大于1时为放大,也可以为负,但基本不用。
    使用 scale 缩放时,图形的左上角坐标、宽度和高度、线条宽度都会同步缩放,若不是预期效果,记得进行相应的处理!
DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>title>
    <meta charset="utf-8" />
    <script type="text/javascript">
      function $$(id) {
        return document.getElementById(id);
      }
      window.onload = function () {
        var cnv = $$("canvas");
        var cxt = cnv.getContext("2d");

        //绘制初始图形
        cxt.fillStyle = "HotPink";
        cxt.fillRect(30, 30, 50, 50);

        //图形放大
        $$("btn-big").onclick = function () {
          // 清空canvas
          cxt.clearRect(0, 0, cnv.width, cnv.height);
          cxt.scale(1.5, 1.5);
          cxt.fillStyle = "HotPink";
          //  添加平移,抵消左上角坐标的放大
          cxt.translate(-10, -10);
          cxt.fillRect(30, 30, 50, 50);
        };

        //图形缩小
        $$("btn-small").onclick = function () {
          // 清空canvas
          cxt.clearRect(0, 0, cnv.width, cnv.height);
          cxt.scale(0.5, 0.5);
          cxt.fillStyle = "HotPink";
          //  反向平移,抵消左上角坐标的縮小
          cxt.translate(30, 30);
          cxt.fillRect(30, 30, 50, 50);
        };
      };
    script>
  head>
  <body>
    <canvas
      id="canvas"
      width="200"
      height="150"
      style="border: 1px dashed gray"
    >canvas
    ><br />
    <input id="btn-big" type="button" value="放大" />
    <input id="btn-small" type="button" value="缩小" />
  body>
html>

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第39张图片

旋转 rotate()

cxt.rotate(angle); 
  • angle 为图形旋转的角度,取值为-Math.PI2~Math.PI2。当angle>0时,图形顺时针旋转;当angel<0时,图形逆时针旋转。
120*Math.PI/180  //120°
150*Math.PI/180  //150°

默认情况下,rotate()方法的旋转中心就是原点坐标(0,0)

cxt.fillStyle = "HotPink";
cxt.fillRect(30, 30, 50, 50);

$$("btn").onclick = function () {
	 cxt.rotate(-30 * Math.PI / 180);   //逆时针旋转30°
	 cxt.fillStyle = "LightSkyBlue ";
	 cxt.fillRect(30, 30, 50, 50); //注意,这里仍然是fillRect(30, 30, 50, 50) 
}

改变旋转中心

先使用translate(x,y),然后再使用rotate()方法

             var i = 0;
             var rectWidth = 100;
             var rectHeight = 50;
             setInterval(function () {
                  i++;
                  cxt.clearRect(0, 0, cnv.width, cnv.height);
                  cxt.save();
                  cxt.translate(cnv.width / 2, cnv.height / 2); //将坐标移动到中心
                  cxt.rotate(Math.PI * (i / 100));           //累进旋转
                  cxt.fillStyle = "HotPink";
                  cxt.fillRect(-rectWidth / 2, -rectHeight / 2, rectWidth, rectHeight); //填充矩形
                  cxt.restore();
             }, 10);

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第40张图片
使用translate()方法结合图形的长宽将旋转中心移动到图形中心上。
本例中,将矩形的中心与画布的中心重合,是为了方便操作。

实战范例 1 —— 内卷花纹

             cxt.translate(150, 0);
             cxt.fillStyle = "rgba(255,0,0,0.25)";
             for (var i = 0; i < 50; i++) {
                   cxt.translate(25, 25);      //图形平移
                   cxt.scale(0.95, 0.95);      //图形缩放
                   cxt.rotate(Math.PI / 10);   //图形旋转
                   cxt.fillRect(0, 0, 100, 50);
             }

canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_第41张图片

实战范例 2 —— 彩虹

//定义数组,存储7种颜色
             var colors = ["red", "orange", "yellow", "green", "blue", "navy", "purple"];
             cxt.lineWidth = 12;
             cxt.translate(50,0); 

             //循环绘制圆弧
             for (var i = 0; i < colors.length; i++) {
                  //每次向下移动10px
                  cxt. translate(0,10); 
                  //定义颜色
                  cxt.strokeStyle = colors[i];
                  //绘制圆弧
                  cxt.beginPath();
                  cxt.arc(50, 100, 100, 0, 180 * Math.PI / 180, true);
                  cxt.stroke();
             }
```![在这里插入图片描述](https://img-blog.csdnimg.cn/00258c688cd24e07be5544a4429c24be.png)

你可能感兴趣的:(#,HTML,#,已归档链接,canvas)