用法
-
rect():指定矩形的轨迹
- 参数:左上角顶点的坐标
x、y
和矩形的宽高 - 说明:不会描边,需要自己手动调用
stroke
方法实现描边
- 参数:左上角顶点的坐标
-
strokeRect():直接绘制出一个描边的矩形
-
fillRect():直接绘制出一个填充的矩形
-
stroke():绘制描边的图形
-
stroke
内部不会自动将未闭合的区域闭合起来 - 如果需要闭合,可以通过
closePath()
来闭合
-
-
fill():绘制实心的图形
fill
方法内部会自动闭合区域(原理就跟closePath
一样) -
closePath:闭合区域
将终点和起点用一条线连接起来 -
设置颜色
-
strokeStyle
:设置描边图形的颜色 -
fillStyle
:设置填充图形的颜色 - 值是一个字符串的值,可以是任意颜色值(如:
"red", "#fff", "rgba(255,0,0,0.1)", "rgb(255,0,0)"
)
-
-
非零环绕规则
- 每一次
fill
方法内部绘制图形的时候都遵循非零环绕规则 - 通过非零环绕规则来判断该区域中的每一个像素点是否需要填充(在绘制多个图形的时候,多个图形有重合的区域,默认情况下,后绘制的就会覆盖之前绘制的部分)
- 规则内容:选定区域内部的某个点,往区域外部任意方向发一条射线,设置射线的起点为0,射线每一次与图形的轨迹相交,判断该轨迹是顺时针还是逆时针,如果是逆时针-1,顺时针+1,最终一起计算结果,如果最终计算结果为0该点不需要填充,不为0就是需要填充的
- 每一次
-
setLineDash():绘制虚线
- 参数是一个数组
- 数组中没有元素,那么绘制的就是实线
- 数组中1个元素([5]),表示实线和空白部分长度都为5
- 数组中2个元素([10,5]),表示实线部分长度为10,空白部分长度为5
- 数组中3个元素([10,5,5]),表示第一个实线部分长度为10,第一个空白部分长度为5,第二个实线长度为5,第二个空白长度为10,第三个实现长度为5,第三个空白长度位5,后面以此类推
-
clearRect:清除画布中指定的矩形区域
- 参数:跟
rect
方法相同 - 实现清空画布:
ctx.clearRect(0,0,canvas.width,canvas.height);
- 参数:跟
-
HTML 标签的一些属性很多时候会直接映射到该 DOM 元素中,作为这个对象的属性存在,就可以直接通过访问对象的属性来进行操作
canvas.width=200; console.log(canvas.width);
- 但是这种方式不能操作自定义属性,对于自定义属性只能通过
getAttribute / setAttribute
来进行操作
-
绘制文本
strokeText("文本内容", x轴, y轴)
-
fillText("文本内容", x轴, y轴)
- 文本是不会产生路径的,也不会因为状态的影响而造成混乱的结果
- 如果只需要绘制文本,不需要
beginPath
,当然在实际开发中保守起见还是习惯性的beginPath();
-
font
属性:设置文本的格式,比如font="30px Microsoft Yahei";
-
textAlign
:文本的水平对齐方式(默认值是start
: 左对齐)-
left
文本左对齐(文字的最左边靠着起点x轴所在) -
right
文本右对齐 -
center
文本居中对齐 -
start
相当于left
-
end
相当于right
-
-
textBaseLine
:文本的垂直对齐方式(默认值是alphabetic
)-
top
:文本基线在文本块的顶部。 -
hanging
:文本基线是悬挂基线。 -
middle
:文本基线在文本块的中间。(文字垂直居中) -
alphabetic
:文本基线是标准的字母基线(英语四线格的第三条线) -
bottom
:文本基线在文本块的底部。
-
-
measureText("文本内容")
- 返回一个对象,该对象中含有
width
属性表示文本的宽度 - 在计算的时候会根据当前设置过的字体大小和字体类型,动态分析出指定文字要占用多少宽度
- 返回一个对象,该对象中含有
-
绘制折线图以及折线图上面的点
- 绘制坐标线
- 绘制坐标轴上的文字
- 绘制点
ctx.fillRect(x-3, y-3, 6, 6);
- 将点连成线
ctx.moveTo(100, 100); ctx.lineTo(700, 500);
-
绘制圆弧
arc(圆心x,圆心y,半径,开始弧度,结束弧度,是否以逆时针方式绘制)
- 整个圆是
2 * Math.PI
的,0的位置位于圆心水平往右拉直线,Math.PI/2
就位于圆心的正下方 - 默认的绘制方式是:顺时针,可以通过
arc
方法的第6个参数传递值为true
表示逆时针方式绘制
-
创建图片
var img=document.createElement("img");
// or
var img=new Image();
img.src="";
-
drawImage(图片对象, sx, sy, sw, sh, x, y, width, height)
- 参数1:图片对象
- 将图片的以
sx, sy
点为顶点,宽度为sw
,高度为sh
的矩形区域内的部分绘制到canvas
的以x, y
为顶点,宽为width
,高为height
的区域内 - 保持纵横比:
- 注意:需要在图片加载完成之后,才能绘制该图片
-
ctx.translate(x, y)
:平移变换-
x
为正数表示canvas
顶点沿着x
轴向右移动,负数表示向左移动 -
y
为正数表示canvas
顶点沿着y
轴向下移动,负数表示向上移动 - 举例:
ctx.translate(100,200)
:坐标轴向右移动100px
,向下移动200px
-
-
伸缩变换
-
scale(1, 1)
:不伸缩 -
scale(0.5, 1)
:x轴压缩一半 -
scale(1, 0.5)
:y轴压缩一半
-
-
状态的保存与恢复
save()
restore()
-
时钟
- 绘制外层大圆
bigX, bigY, bigRadius
- 绘制刻度线
- 刻度线属性(长度、线宽)
- 整个表盘中具有60个刻度线,刻度线有大小两种,每5格就有一个粗刻度线
- 绘制刻度盘文字
文字属性(颜色、大小、字体类型) - 绘制指针
时针、分针、秒针的属性(长度、线宽、颜色)
- 绘制外层大圆
function Clock(opt){
//参数必填
if(!opt){ throw new Error("参数必填!"); }
//必填参数
var props = {canvas:"",radius:""};
for(var key in props){
if(!opt.hasOwnProperty(key)){
throw new Error("请填入"+key+"参数");
}
}
//选填参数
var defaultObj = {
clockX:400,
clockY:300,
smallLength:10,
smallWidth:4,
bigLength:25,
bigWidth:10
};
for(var key in defaultObj){
opt[key] = opt[key] || defaultObj[key];
}
for(var key in opt){
this[key] = opt[key]
}
this.ctx = this.canvas.getContext("2d");
this.startRad = -Math.PI/3;
this.init();
var self = this;
this.timer = setInterval(function () {
self.ctx.clearRect(0,0,self.canvas.width,self.canvas.height);
self.init();
},1000);
}
Clock.prototype = {
constructor:Clock,
init: function (){
//绘制表盘
this.drawBigCircle();
//绘制所有刻度线
this.drawTicks();
//绘制所有指针
this.drawPoints();
},
//绘制表盘
drawBigCircle: function () {
this.ctx.beginPath();
this.ctx.save();
this.ctx.arc(this.clockX,this.clockY,this.radius,0,2*Math.PI);
this.ctx.lineWidth = 10;
this.ctx.strokeStyle = "deepskyblue";
this.ctx.stroke();
this.ctx.restore();
},
//绘制所有刻度线
drawTicks: function () {
this.ctx.font = "24px 微软雅黑";
this.ctx.textAlign = "center";
this.ctx.textBaseline = "middle";
var singleRad = 2*Math.PI/60;
var length,width;
for(var i = 0;i < 60;i++){
var rad = this.startRad+singleRad*i;
if(i%5 == 0){
length = this.bigLength;
width = this.bigWidth;
//绘制表盘上数字
this.drawText(rad,length,i);
}else{
length = this.smallLength;
width = this.smallWidth;
}
//绘制单个刻度线
this.drawTick(rad,length,width);
}
},
//绘制单个刻度线
drawTick: function (rad,length,width) {
var radius = this.radius - 5;
this.ctx.lineWidth = width;
var x1 = this.clockX+Math.cos(rad)*(radius-length);
var y1 = this.clockY+Math.sin(rad)*(radius-length);
var x2 = this.clockX+Math.cos(rad)*radius;
var y2 = this.clockY+Math.sin(rad)*radius;
this.ctx.beginPath();
this.ctx.moveTo(x1,y1);
this.ctx.lineTo(x2,y2);
this.ctx.stroke();
},
//绘制所有指针
drawPoints: function () {
var date = new Date();
var hour = date.getHours();
hour = hour<12?hour:hour-12;
var minute = date.getMinutes();
var second = date.getSeconds();
var hourRad = hour*2*Math.PI/12+minute/60*2*Math.PI/12-Math.PI/2;
var minuteRad = minute*2*Math.PI/60-Math.PI/2;
var secondRad = second*2*Math.PI/60-Math.PI/2;
this.ctx.save();
//绘制时针
this.drawPoint("deepskyblue",60,8,hourRad);
//绘制分针
this.drawPoint("yellow",90,6,minuteRad);
//绘制秒针
this.drawPoint("red",120,4,secondRad);
this.ctx.restore();
},
//绘制单个指针
drawPoint: function (color,length,width,rad) {
this.ctx.beginPath();
this.ctx.strokeStyle = color;
this.ctx.lineWidth = width;
var x = this.clockX+Math.cos(rad)*length;
var y = this.clockY+Math.sin(rad)*length;
this.ctx.moveTo(this.clockX,this.clockY);
this.ctx.lineTo(x,y);
this.ctx.stroke();
},
//绘制表盘上数字
drawText: function (rad,length,i) {
var x = this.clockX+Math.cos(rad)*(this.radius-length-24);
var y = this.clockY+Math.sin(rad)*(this.radius-length-24);
this.ctx.fillText(i/5+1,x,y);
}
}
var canvas = document.querySelector("canvas");
var obj = {
canvas:canvas,
//表盘参数
clockX:400,
clockY:300,
radius:160,
//刻度参数
smallLength:10,
smallWidth:4,
bigLength:25,
bigWidth:10,
};
var clock1 = new Clock(obj);
理论与实践相结合
<canvas width="650" height="500"></canvas>
// 获取画布
var canvas = document.querySelector('canvas')
// 获取绘制的对象
var ctx = canvas.getContext('2d')
// 开始一条路径,或重置当前的路径
ctx.beginPath()
ctx.moveTo(50, 50)
ctx.lineTo(200, 100)
ctx.lineTo(50, 150)
// 闭合路径
ctx.closePath()
ctx.strokeStyle="red"
// 设置连接处样式,lineJoin: round、bevel、miter(默认)
ctx.lineJoin = "round"
ctx.lineWidth = 10
ctx.stroke()
// 渐变
// 起始位置的横纵坐标,结束位置的横纵坐标
var lgd = ctx.createLinearGradient(250, 100, 550, 100)
// 添加渐变的颜色,0 表示开始,1 表示结束
lgd.addColorStop(0, 'pink')
lgd.addColorStop(0.7, 'red')
lgd.addColorStop(0.9, 'yellow')
// 把渐变的方案给 strokeStyle
ctx.strokeStyle = lgd
ctx.beginPath()
ctx.moveTo(250, 100)
ctx.lineTo(550, 100)
ctx.stroke()
// 镜像渐变
// 起始位置的横纵坐标、半径,结束位置的横纵坐标、半径
var rgd = ctx.createRadialGradient(250, 250, 30, 250, 250, 100)
rgd.addColorStop(0, 'red')
rgd.addColorStop(1, 'yellow')
ctx.fillStyle = rgd
ctx.beginPath()
ctx.moveTo(150, 150)
ctx.lineTo(350, 150)
ctx.lineTo(350, 350)
ctx.lineTo(150, 350)
ctx.closePath()
// 填充
ctx.fill()
// 非零环绕
// 如果需要判断某一个区域是否需要填充颜色,就从该区域中随机的选取一个点。
// 从这个点拉一条直线出来, 一定要拉到图形的外面,此时以该点为圆心。
// 看穿过拉出的直线的线段,顺时针方向记为 +1, 逆时针方向记为 -1,最终看求和的结果。
// 如果是 0 就不填充,如果是非零就填充
ctx.beginPath()
ctx.strokeStyle = 'yellow'
// 顺时针
ctx.moveTo(450, 200)
ctx.lineTo(450, 300)
ctx.lineTo(550, 300)
ctx.lineTo(550, 200)
ctx.closePath()
// 逆时针
ctx.moveTo(400, 150)
ctx.lineTo(600, 150)
ctx.lineTo(600, 350)
ctx.lineTo(400, 350)
ctx.closePath()
ctx.stroke()
ctx.fillStyle = 'pink'
ctx.fill()
// 虚线
ctx.beginPath()
ctx.moveTo(50, 380)
ctx.lineTo(300, 380)
// 第一个参数代表线的长度,第二个参数代表空白部分的长度
ctx.setLineDash([20, 10])
// 线-空白-线-空白(循环)
// ctx.setLineDash([20, 5, 10])
ctx.strokeStyle = 'pink'
ctx.lineWidth = 2
ctx.stroke()
// 绘制移动的矩形
// 刚开始时矩形的横坐标
var x = 0
// 每次移动的步数
var step = 5
// 标记,当矩形移动到右侧后再回来
var i = 1
setInterval(() => {
// 清理画布
ctx.clearRect(0, 400, canvas.width, 50)
ctx.fillStyle = 'pink'
// 横纵坐标、宽、高
ctx.fillRect(x, 400, 50, 50)
ctx.stroke()
x += step * i
if (x > canvas.width - 50) {
i = -1
} else if (x <= 0) {
i = 1
}
}, 10);
// 绘制文本
ctx.beginPath()
// 设置文本的像素、字体
ctx.font = '50px 宋体'
// 设置文本的左右对齐方式: center、left、right
ctx.textAlign = 'center'
// 设置文本的上下对齐方式:top、bottom、middle、alphabetic(默认)
ctx.textBaseline = 'middle'
// 设置阴影颜色
ctx.shadowColor = 'red'
// 设置阴影偏移量
ctx.shadowOffsetX = 15
// 设置阴影模糊度
ctx.shadowOffsetY = 5
ctx.shadowBlur = 5
ctx.strokeStyle = 'black'
ctx.strokeText('好无聊', 100, 500)
网友评论