ZetCode

HTML5 画布形状

最后修改于 2023 年 7 月 17 日

在本部分 HTML5 画布教程中,我们创建了一些基本和更高级的几何形状。

矩形

第一个程序绘制了两个矩形。

rectangles.html
<!DOCTYPE html>
<html>
<head>
<title>HTML5 canvas rectangles</title>
<script>
    function draw() {
        
        var canvas = document.getElementById('myCanvas');
        var ctx = canvas.getContext('2d');

        ctx.fillStyle = 'gray';
        ctx.fillRect(10, 10, 60, 60);
        ctx.fillRect(100, 10, 100, 60);
    }
</script>
</head>

<body onload="draw();">
    <canvas id="myCanvas" width="350" height="250">
    </canvas>
</body>
</html> 

示例使用 drawRect 方法绘制矩形。

ctx.fillStyle = 'gray';

矩形的内部以灰色填充。

ctx.fillRect(10, 10, 60, 60);
ctx.fillRect(100, 10, 100, 60);

fillRect 方法用于绘制正方形和矩形。前两个参数是形状的 x 和 y 坐标。最后两个参数是形状的宽度和高度。

Rectangles
图示:矩形

基本形状

在下面的程序中,我们绘制了一些基本形状。

shapes.html
<!DOCTYPE html>
<html>
<head>
<title>HTML5 canvas shapes</title>
<script>
    function draw() {
        
        var canvas = document.getElementById('myCanvas');
        var ctx = canvas.getContext('2d');

        ctx.fillStyle = 'gray';
        ctx.fillRect(10, 10, 60, 60);
        ctx.fillRect(100, 10, 90, 60);
        
        ctx.beginPath();
        ctx.arc(250, 40, 32, 0, 2*Math.PI);
        ctx.fill(); 
        
        ctx.beginPath();
        ctx.moveTo(10, 160);
        ctx.lineTo(90, 160);
        ctx.lineTo(50, 110);
        ctx.closePath();
        ctx.fill();         
        
        ctx.save();
        ctx.scale(2, 1);
        ctx.beginPath();
        ctx.arc(72, 130, 25, 0, 2*Math.PI);
        ctx.fill();
        ctx.restore();
        
        ctx.beginPath();
        ctx.arc(250, 120, 40, 0, Math.PI);
        ctx.fill();                 
    }
</script>
</head>

<body onload="draw();">
<canvas id="myCanvas" width="350" height="350">
</canvas>
</body>

</html> 

画布上绘制了六种不同的形状。

ctx.fillStyle = 'gray';

形状将以灰色填充。

ctx.fillRect(10, 10, 60, 60);
ctx.fillRect(100, 10, 90, 60);

矩形使用 fillRect 方法绘制。矩形是唯一一个不使用 beginPath 方法初始化的形状。

ctx.beginPath();
ctx.arc(250, 40, 32, 0, 2*Math.PI);
ctx.fill(); 

圆使用 arc 方法绘制。该方法将一个弧添加到创建的路径中。前两个参数定义了弧的中心点的 x 和 y 坐标。接下来的两个参数指定了弧的起始角和结束角。角度以弧度定义。最后一个参数是可选的;它指定了绘制弧的方向。默认方向是顺时针。

ctx.beginPath();
ctx.moveTo(10, 160);
ctx.lineTo(90, 160);
ctx.lineTo(50, 110);
ctx.closePath();
ctx.fill(); 

使用 moveTolineTo 方法,我们绘制了一个三角形。closePath 方法会将画笔移回到当前子路径的起点。在我们的例子中,它完成了三角形的形状。

ctx.save();
ctx.scale(2, 1);
ctx.beginPath();
ctx.arc(72, 130, 25, 0, 2*Math.PI);
ctx.fill();
ctx.restore();

椭圆形是通过缩放圆形绘制的。这些操作放在 saverestore 方法之间,这样缩放操作就不会影响后续的绘图。

ctx.beginPath();
ctx.arc(250, 120, 40, 0, Math.PI);
ctx.fill(); 

最后一个形状,一个半圆,是使用 arc 方法绘制的。

Basic shapes
图:基本形状

饼图

饼图是一种圆形图表,分为多个扇形以说明数字比例。

piechart.html
<!DOCTYPE html>
<html>
<head>
<title>HTML5 canvas pie chart</title>
<style>
    canvas {background: #bbb}
</style>
<script>
    function draw() {
        
        var canvas = document.getElementById('myCanvas');
        var ctx = canvas.getContext('2d');

        var beginAngle = 0;
        var endAngle = 0;
        var data = [170, 60, 45]; 
        var total = 0; 
        var colours = ["#95B524", "#AFCC4C", "#C1DD54"];
        const SPACE = 10;
        
        for (var i = 0; i < data.length; i++) {
          total += data[i];
        }

        ctx.strokeStyle = 'white';
        ctx.lineWidth = 2;
        
        for (var j = 0; j < data.length; j++) {
            
            endAngle = beginAngle + (Math.PI * 2 * (data[j] / total));
            ctx.fillStyle = colours[j];
            ctx.beginPath();
            ctx.moveTo(canvas.width/2, canvas.height/2);
            ctx.arc(canvas.width/2, canvas.height/2, canvas.height/2 - SPACE, 
                beginAngle, endAngle, false);
            ctx.closePath();
            ctx.fill();
            ctx.stroke();
            beginAngle = endAngle;
        }               
    }
</script>
</head>
<body onload="draw();">
    <canvas id="myCanvas" width="350" height="300">
    </canvas>
</body>
</html> 

示例绘制了一个饼图。它有三个扇区,以不同深浅的绿色填充。

<style>
    canvas {background: #bbb}
</style>

为了让图表的白色轮廓清晰可见,我们将画布的背景颜色更改为灰色。

var data = [170, 60, 45];

这是饼图说明的数据。

const SPACE = 10;

SPACE 常量是饼图到画布边界的距离。

endAngle = beginAngle + (Math.PI * 2 * (data[j] / total));

该公式计算当前绘制扇形的结束角度。

ctx.moveTo(canvas.width/2, canvas.height/2);
ctx.arc(canvas.width/2, canvas.height/2, canvas.height/2 - SPACE, 
    beginAngle, endAngle, false);
ctx.closePath();

使用三个方法绘制当前扇形:moveToarcclosePath

ctx.fill();
ctx.stroke();

我们同时绘制了形状的内部和轮廓。

beginAngle = endAngle;

对于下一个扇形,最后一个结束角度成为起始角度。

Pie chart
图:饼图

星形

以下示例创建了一个星形。

star.html
<!DOCTYPE html>
<html>
<head>
<title>HTML5 canvas star shape</title>
<script>
    function draw() {
        
        var canvas = document.getElementById('myCanvas');
        var ctx = canvas.getContext('2d');

        ctx.fillStyle = 'gray';

        var points = [ [ 0, 85 ], [ 75, 75 ], [ 100, 10 ], [ 125, 75 ], 
            [ 200, 85 ], [ 150, 125 ], [ 160, 190 ], [ 100, 150 ], 
            [ 40, 190 ], [ 50, 125 ], [ 0, 85 ] ];
        
        var len = points.length;

        ctx.beginPath();
        ctx.moveTo(points[0][0], points[0][1]);
        
        for (var i = 0; i < len; i++) {
            ctx.lineTo(points[i][0], points[i][1]);
        }        
        
        ctx.fill(); 

    }
</script>
</head>

<body onload="draw();">
    <canvas id="myCanvas" width="350" height="250">
    </canvas>
</body>
</html> 

星形由一系列点创建。

var points = [ [ 0, 85 ], [ 75, 75 ], [ 100, 10 ], [ 125, 75 ], 
    [ 200, 85 ], [ 150, 125 ], [ 160, 190 ], [ 100, 150 ], 
    [ 40, 190 ], [ 50, 125 ], [ 0, 85 ] ];

这是星形的坐标。

ctx.moveTo(points[0][0], points[0][1]);        

我们使用 moveTo 方法移动到形状的初始坐标。

for (var i = 0; i < len; i++) {
    ctx.lineTo(points[i][0], points[i][1]);
}    

在这里,我们使用 lineTo 方法连接星形的所有坐标。

ctx.fill(); 

fill 方法使用定义的(灰色)颜色填充星形的内部。

Star
图:星形

三个圆

可以使用复合(compositing)来创建新形状。复合是决定画布上形状混合方式的规则。

three_circles.html
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Canvas three circles</title>
<script>
    function draw() {
        
        var canvas = document.getElementById('myCanvas');
        var ctx = canvas.getContext('2d');
        
        ctx.lineWidth = 3;
        
        ctx.fillStyle = 'gray';
        ctx.beginPath();
        ctx.arc(90, 90, 60, 0, 2*Math.PI);
        ctx.stroke();
                
        ctx.beginPath();
        ctx.arc(120, 150, 60, 0, 2*Math.PI);
        ctx.stroke();

        ctx.beginPath();
        ctx.arc(150, 100, 60, 0, 2*Math.PI);
        ctx.stroke();        

        ctx.globalCompositeOperation='destination-out';

        ctx.beginPath();
        ctx.arc(90, 90, 60, 0, 2*Math.PI);
        ctx.fill();
                
        ctx.beginPath();
        ctx.arc(120, 150, 60, 0, 2*Math.PI);
        ctx.fill();

        ctx.beginPath();
        ctx.arc(150, 100, 60, 0, 2*Math.PI);
        ctx.fill();
    }
</script>
</head>

<body onload="draw();">
    <canvas id="myCanvas" width="400" height="350">
    </canvas>
</body>
</html> 

该示例通过组合三个圆的轮廓来创建一个形状。这三个圆会重叠。

ctx.beginPath();
ctx.arc(90, 90, 60, 0, 2*Math.PI);
ctx.stroke();

画布上绘制了一个圆。

ctx.globalCompositeOperation='destination-out';

复合操作设置为 destination-out。在此模式下,当源和目标不重叠时,目标将显示在所有地方。在其他所有地方,将显示透明度。

ctx.beginPath();
ctx.arc(90, 90, 60, 0, 2*Math.PI);
ctx.fill();

现在,相同的圆以灰色填充。新的绘图将在重叠的地方擦除现有绘图。结果是,只剩下轮廓。

Three circles
图示:三个圆

在本部分 HTML5 画布教程中,我们涵盖了一些 HTML5 画布中的基本和更高级的形状。