此系列教程层层递进,建议按顺序阅读
圆 arc()
cxt.beginPath();
cxt.arc(x,y,半径,开始角度,结束角度, anticlockwise);
cxt.closePath();
120*Math.PI/180 //120°
150*Math.PI/180 //150°
//半圆
cxt.beginPath();
cxt.arc(80, 80, 50, 0, 180*Math.PI/180, true);
cxt.closePath();
//描边
cxt.strokeStyle = "HotPink";
cxt.stroke();
//整圆
cxt.beginPath();
cxt.arc(120, 80, 50, 0, 360*Math.PI/180, true);
cxt.closePath();
//描边
cxt.strokeStyle = "HotPink";
cxt.stroke();
cxt.beginPath();
cxt.arc(70, 70, 50, 0, -90 * Math.PI / 180, true);
cxt.closePath();
cxt.strokeStyle = "HotPink";
cxt.stroke();
cxt.arc(70, 70, 50, 0, -90 * Math.PI / 180, false);
//半圆
cxt.beginPath();
cxt.arc(80, 80, 50, 0, 180 * Math.PI / 180, true);
cxt.closePath();
//填充
cxt.fillStyle = "HotPink";
cxt.fill();
//整圆
cxt.beginPath();
cxt.arc(120, 80, 50, 0, 360 * Math.PI / 180, true);
cxt.closePath();
//填充
cxt.fillStyle = "#9966FF";
cxt.fill();
弧线
方法一 arc() 绘制
//状态描述
cxt.beginPath();
cxt.arc(x,y,半径,开始角度,结束角度, anticlockwise);
//描边
cxt.strokeStyle = "颜色值";
cxt.stroke();
和圆一样,使用arc(),但不需要关闭路径! (即没有 cxt.closePath())
cxt.beginPath();
cxt.arc(70, 70, 50, 0, -90 * Math.PI / 180, true);
cxt.stroke();
stroke()和fill()这两个方法只能绘制当前路径,不能同时绘制几个路径。
//绘制一条直线
cxt.moveTo(20,20);
cxt.lineTo(70,20);
cxt.stroke();
//绘制圆弧+直线
cxt.beginPath();
cxt.arc(70,70,50,0,-90*Math.PI/180,true);
cxt.moveTo(120,70);
cxt.lineTo(120,120);
cxt.stroke();
//绘制一条直线
cxt.moveTo(20,20);
cxt.lineTo(70,20);
// cxt.stroke(); 注释掉之后,此直线不会绘制
//绘制圆弧+直线
cxt.beginPath();
cxt.arc(70,70,50,0,-90*Math.PI/180,true);
cxt.moveTo(120,70);
cxt.lineTo(120,120);
cxt.stroke();
方法二 arcTo() 绘制
cxt.arcTo(cx,cy,x2,y2,radius);
一般由moveTo()或lineTo()提供开始点
cxt.moveTo(20,20);
cxt.lineTo(70,20);
cxt.arcTo(120,20,120,70,50);
cxt.lineTo(120,120);
cxt.stroke();
cxt.moveTo(20,20);
// cxt.lineTo(70,20); 注释掉后,仍会画直线!
cxt.arcTo(120,20,120,70,50);
cxt.lineTo(120,120);
cxt.stroke();
圆角矩形
方法一 直线和弧线拼接
cxt.moveTo(40,20);
cxt.lineTo(160,20);
cxt.arcTo(180,20,180,40,20);
cxt.moveTo(180,40);
cxt.lineTo(180,110);
cxt.arcTo(180,130,160,130,20);
cxt.moveTo(160,130);
cxt.lineTo(40,130);
cxt.arcTo(20,130,20,110,20);
cxt.moveTo(20,110);
cxt.lineTo(20,40);
cxt.arcTo(20,20,40,20,20);
cxt.stroke();
方法二 封装一个专门绘制圆角矩形的函数
/*
* createRoundedRect()用于绘制圆角矩形
* width、height:分别表示长和宽
* r:表示圆角半径
* offsetX、offsetY:分别表示左上角顶点坐标
*/
function createRoundedRect(cxt, width, height, r, offsetX, offsetY) {
cxt.beginPath();
cxt.moveTo(offsetX + r, offsetY);
cxt.lineTo(offsetX + width - r, offsetY);
cxt.arcTo(offsetX + width, offsetY, offsetY + width, offsetY + r, r);
cxt.lineTo(offsetX + width, offsetY + height - r);
cxt.arcTo(offsetX + width, offsetY + height, offsetX + width - r, offsetY + height, r);
cxt.lineTo(offsetX + r, offsetY + height);
cxt.arcTo(offsetX, offsetY + height, offsetX, offsetY + height - r, r);
cxt.lineTo(offsetX, offsetY + r);
cxt.arcTo(offsetX, offsetY, offsetX + r, offsetY, r);
cxt.closePath();
}
createRoundedRect(cxt, 100, 100, 20, 20, 20);
cxt.fillStyle = "HotPink";
cxt.fill();
曲线
从理论上来说,任何复杂的图形都可以用贝塞尔曲线绘制出来
二次贝塞尔曲线
二次贝塞尔曲线有一个控制点,只能向一个方向弯曲
cxt.quadraticCurveTo(cx , cy , x2,y2);
一般由moveTo()或lineTo()提供开始点
cxt.moveTo(30, 120);
cxt.quadraticCurveTo(100, 20, 160, 120);
cxt.stroke();
实战范例:气泡
cxt.moveTo(75, 25);
cxt.quadraticCurveTo(25, 25, 25, 62);
cxt.quadraticCurveTo(25, 100, 50, 100);
cxt.quadraticCurveTo(50, 120, 30, 125);
cxt.quadraticCurveTo(60, 120, 65, 100);
cxt.quadraticCurveTo(125, 100, 125, 62);
cxt.quadraticCurveTo(125, 25, 75, 25);
cxt.stroke();
三次贝塞尔曲线
三次贝塞尔曲线有两个控制点,可以绘制出波浪线
cxt.bezierCurveTo(cx1 , cy1 , cx2 , cy2 , x , y);
一般由moveTo()或lineTo()提供开始点
//绘制三次贝塞尔曲线
cxt.moveTo(20, 80);
var cx1 = 20;
var cy1 = 20;
var cx2 = 120;
var cy2 = 120;
var endX = 120;
var endY = 60;
cxt.bezierCurveTo(cx1, cy1, cx2, cy2, endX, endY);
cxt.stroke();
实战范例:心形
cxt.moveTo(75, 40);
cxt.bezierCurveTo(75, 37, 70, 25, 50, 25);
cxt.bezierCurveTo(20, 25, 20, 62.5, 20, 62.5);
cxt.bezierCurveTo(20, 80, 40, 102, 75, 120);
cxt.bezierCurveTo(110, 102, 130, 80, 130, 62.5);
cxt.bezierCurveTo(130, 62.5, 130, 25, 100, 25);
cxt.bezierCurveTo(85, 25, 75, 37, 75, 40);
cxt.stroke();
实战范例:N叶草
/*
* createLeaf()用于绘制N叶草
* n:n片
* dx、dy:叶子中心位置的坐标
* size:控制叶子的大小
* length:控制叶子长度
*/
function createLeaf(cxt, n, dx, dy, size, length) {
cxt.beginPath();
cxt.moveTo(dx, dy + size);
var degree = 2 * Math.PI / n;
for (var i = 1; i < n + 1; i++) {
//计算控制点的坐标
var cx1 = Math.sin((i - 1) * degree) * length + dx;
var cy1 = Math.cos((i - 1) * degree) * length + dy;
var cx2 = Math.sin(i * degree) * length + dx;
var cy2 = Math.cos(i * degree) * length + dy;
//计算结束点的坐标
var x = Math.sin(i * degree) * size + dx;
var y = Math.cos(i * degree) * size + dy;
cxt.bezierCurveTo(cx1, cy1, cx2, cy2, x, y);
}
cxt.closePath();
}
createLeaf(cxt, 4, cnv.width/2, cnv.height/2, 20, 80);
//定义填充颜色为浅绿色
cxt.fillStyle = "#00FF99";
cxt.fill();
扇形
封装绘制扇形的函数 createSector
function createSector(cxt, x, y, r, angle1, angle2) {
cxt.beginPath();
cxt.moveTo(x, y);
cxt.arc(x, y, r, angle1 * Math.PI / 180, angle2 * Math.PI / 180, false);
cxt.closePath();
}
createSector(cxt, cnv.width / 2, cnv.height / 2, 50, 30, 120);
cxt.fillStyle = "HotPink";
cxt.fill();