“油箱”,加满圆圈
使用复合模式:
- 使用半径 x2 作为高度(或宽度)
- 绘制并填充完整的圆
- 使用复合模式
destination-out
- 在顶部画一个填充的矩形,表示高度的百分比
主要代码是:
var o = radius * 2, // diameter => width and height of rect
h = o - (o * percent / 100); // height based on percentage
ctx.beginPath();
ctx.arc(x, y, radius, 0, 6.28);
ctx.fill();
ctx.globalCompositeOperation = "destination-out";
ctx.fillRect(x - radius, y - radius, o, h); // this will remove a part of the top
演示
var ctx = document.querySelector("canvas").getContext("2d"),
pst = 0, dlt = 2;
ctx.fillStyle = "#28f";
function drawCircle(ctx, x, y, radius, percent) {
var o = radius * 2,
h = o - (o * percent / 100);
ctx.globalCompositeOperation = "source-over"; // make sure we have default mode
ctx.beginPath(); // fill an arc
ctx.arc(x, y, radius, 0, 6.28);
ctx.fill();
ctx.globalCompositeOperation = "destination-out"; // mode to use for next op.
ctx.fillRect(x - radius, y - radius, o, h); // "clear" part of arc
ctx.globalCompositeOperation = "source-over"; // be polite, set default mode back
}
(function loop() {
ctx.clearRect(0,0,300,150);
drawCircle(ctx, 70, 70, 60, pst);
pst += dlt;
if (pst <= 0 || pst >= 100) dlt = -dlt;
requestAnimationFrame(loop);
})();
<canvas></canvas>
饼型
- 移动到圆心
- 添加圆弧,这将创建一条从圆心到圆弧起点的线
- 关闭路径,这将创建一条从弧的末端回到中心的线,并填充
(提示:fill() 确实不需要closePath(),因为fill() 会隐式关闭路径,但如果您想改为使用stroke(),则需要它。
最重要的部分是:
ctx.beginPath();
ctx.moveTo(x, y);
ctx.arc(x, y, radius, 0, 2 * Math.PI * percent / 100);
//ctx.closePath(); // for stroke, not needed for fill
ctx.fill();
演示
var ctx = document.querySelector("canvas").getContext("2d"),
pst = 0, dlt = 2;
ctx.fillStyle = "#28f";
function drawPie(ctx, x, y, radius, percent) {
ctx.beginPath();
ctx.moveTo(x, y);
ctx.arc(x, y, radius, 0, 2 * Math.PI * percent /100);
ctx.fill();
}
(function loop() {
ctx.clearRect(0,0,300,150); drawPie(ctx, 70, 70, 60, pst);
pst += dlt; if (pst <= 0 || pst >= 100) dlt = -dlt;
requestAnimationFrame(loop);
})();
<canvas></canvas>
轮廓圆:
几乎与饼类型相同,但有以下变化:
- 以角度 0(或您要开始的角度)移动到圆弧的外边缘
- 向路径添加圆弧
- 描边(记得设置
lineWidth,见下方演示)
基本部分:
ctx.beginPath();
ctx.moveTo(x + radius, y); // cos(0) for x = 1, so just use radius, sin(0) = 0
ctx.arc(x, y, radius, 0, 2 * Math.PI * percent /100);
ctx.stroke();
您可以使用旋转变换调整间隙点或使用三角法计算实际点。
演示
var ctx = document.querySelector("canvas").getContext("2d"),
pst = 0, dlt = 2;
ctx.strokeStyle = "#28f";
ctx.lineWidth = 8;
function drawWedge(ctx, x, y, radius, percent) {
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.arc(x, y, radius, 0, 2 * Math.PI * percent /100);
ctx.stroke();
}
(function loop() {
ctx.clearRect(0,0,300,150); drawWedge(ctx, 70, 70, 60, pst);
pst += dlt; if (pst <= 0 || pst >= 100) dlt = -dlt;
requestAnimationFrame(loop);
})();
<canvas></canvas>
使用不同的起点
您可以使用旋转变换或使用三角函数手动计算点来更改圆弧的起点。
要手动计算这些,您可以这样做(以弧度表示的角度):
x = radius * Math.cos(angleInRad); // end point for x
y = radius * Math.sin(angleInRad); // end point for y
只需将总角度与起始角度相加即可得到终点。
360° 弧度 = 2 x PI,所以如果你想用度为单位的角度,请使用以下方法进行转换:
angleInRad = angleInDeg * Math.PI / 180;
演示,使用 transfrom 和逆时针模式旋转
var ctx = document.querySelector("canvas").getContext("2d"),
pst = 0, dlt = 2;
ctx.strokeStyle = "#28f";
ctx.lineWidth = 8;
function drawWedge(ctx, x, y, radius, percent) {
ctx.translate(x, y); // translate to rotating pivot
ctx.rotate(Math.PI * 0.5); // rotate, here 90° deg
ctx.translate(-x, -y); // translate back
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.arc(x, y, radius, 0, 2 * Math.PI * percent /100);
ctx.stroke();
ctx.setTransform(1,0,0,1,0,0); // reset transform
}
(function loop() {
ctx.clearRect(0,0,300,150); drawWedge(ctx, 70, 70, 60, pst);
pst += dlt; if (pst <= 0 || pst >= 100) dlt = -dlt;
requestAnimationFrame(loop);
})();
<canvas></canvas>