线的样式
线宽 lineWidth
lineWidth 是context对象的属性,用于描述线条的宽度,属性值为整数,默认值为1px。
//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();
必须使用beginPath()方法来开始新的路径,才可以绘制一个新的lineWidth属性
cxt.lineWidth = 5;
cxt.arc(70, 70, 50, 0, -90 * Math.PI / 180, false);
cxt.stroke();
线帽 lineCap
lineCap 是context对象的属性,用于描述线条开始处和结尾处的线帽样式,取值如下:
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 属性
cxt.moveTo(50, 50);
cxt.lineTo(100, 50);
cxt.lineTo(50, 100);
cxt.lineTo(100, 100);
cxt.lineWidth = 12;
cxt.lineCap = "round";
cxt.stroke();
lineCap属性只对线条的开始处和结尾处这两个地方起作用,而线段与线段交接的地方依然是“尖角”。
线的交点 lineJoin
lineJoin 是context对象的属性,用于描述两个线条交接处的样式,取值如下:
cxt.moveTo(50, 50);
cxt.lineTo(100, 50);
cxt.lineTo(50, 100);
cxt.lineTo(100, 100);
cxt.lineWidth = 12;
cxt.lineJoin = "miter";
cxt.stroke();
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);
绘制文本
文本属性:
10px sans-serif。
context.font = "font-style font-weight font-size/line-height font-family";
cxt.font = "bold 30px 微软雅黑";
文本方法:
// text 为目标文本
var length = cxt.measureText(text).width;
描边文本(空心文本)
strokeText(text , x , y , maxWidth)
var text = "绿叶学习网";
cxt.font = "bold 30px 微软雅黑";
cxt.strokeStyle = "purple";
cxt.strokeText(text, 30, 60);
cxt.strokeText(text,30,60)改为cxt.strokeText(text,30,60,100)后,文本会压缩
填充文本
fillText(text , x , y , maxWidth)
var text = "绿叶学习网";
cxt.font = "bold 30px 微软雅黑";
cxt.fillStyle = "purple";
cxt.fillText(text,30,60);
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);
文本水平对齐方式 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);
文本垂直对齐方式 textBaseline (用得少)
//在纵坐标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);
操作图片
图片渲染
cxt.drawImage(image ,dx , dy);
//创建image对象
var image = new Image();
image.src = "images/princess.png";
// 必须等图片加载完后,再进行渲染
image.onload = function () {
cxt.drawImage(image, 40, 20);
}
<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)
var image = new Image();
image.src = "images/princess.png";
image.onload = function () {
cxt.drawImage(image, 40, 20, 60, 60);
}
图片裁剪(矩形裁剪)
此方法可以将部分图像复制到画布,类似于CSSSprite技术,从而使得图片只需要加载一次即可,这样极大地提高了速度(常用于Canvas游戏开发)。
cxt.drawImage(image , sx , sy , sw, sh , dx , dy , dw , dh)
var image = new Image();
image.src = "images/princess.png";
image.onload = function () {
cxt.drawImage(image, 0, 0, 80, 80, 40, 20, 80, 80);
}
图片切割 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);
}
图片平铺
var pattern = cxt.createPattern(image , type);
cxt.fillStyle = pattern;
cxt.fillRect();
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);
}
var pattern = cxt.createPattern(myImg, "repeat-x");
var pattern = cxt.createPattern(myImg, "repeat-y");
//创建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);
用图片填充文字(用得少)
//创建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();
}
图片特效
更高级的图片处理,如调整图片亮度、变黑白图片等需要对图片进行像素级处理,基本流程为:
获取图片的像素信息
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 即图片像素的总量。
修改图片的像素信息
即对 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(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);
}
调整透明度
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);
}
颜色反转(底片)
即图片颜色颠倒,效果类似相机的底片。
实现算法:
红、绿、蓝这三个通道的像素取各自的相反值,也就是(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);
}
黑白效果(灰度图)
指将彩色图片转换成黑白图片。
实现算法:
首先取红、绿、蓝三个通道的平均值,也就是(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);
}
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);
}
复古
使得图片有一种古旧效果。
实现算法:
将红、绿、蓝三个通道,分别取这三个值的某种加权平均值。
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);
}
红色蒙版
让图片呈现一种偏红的效果
实现算法:
将红通道(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);
}
创建像素区域 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);
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);
}
变换元素
变换可用于图形,也可以用于图片和文字。
变换的本质都是通过“变换矩阵transform()”实现的,涉及到线性代数,平时并不会用,不必深究,简单了解即可:
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);
将 setTransform 改为 transform 后效果为
平移 translate()
本质是移动了整个坐标轴
cxt.translate(x,y);
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>
缩放 scale ()
cxt.scale(x,y);
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>
旋转 rotate()
cxt.rotate(angle);
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);
使用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);
}
实战范例 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)