ZetCode

JavaScript Canvas lineDashOffset 教程

最后修改于 2025 年 4 月 3 日

在本文中,我们探讨了 JavaScript 中的 Canvas lineDashOffset 属性。此属性允许创建动画虚线并控制虚线模式。掌握 lineDashOffset 对于创建动态视觉效果至关重要。

基本定义

lineDashOffset 属性指定从何处开始绘制线的虚线模式。它接受一个浮点数值,表示以像素为单位的偏移距离。正值会向前移动模式,负值会向后移动模式。

当与 setLineDash 结合使用时,lineDashOffset 通过随时间改变偏移量来实现动画效果。这会在虚线和边框中产生运动的错觉。该属性适用于所有描边操作。

基本 lineDashOffset 用法

本示例演示了如何创建带有偏移量的简单虚线。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Basic lineDashOffset</title>
</head>
<body>

<canvas id="myCanvas" width="300" height="200"></canvas>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    ctx.setLineDash([10, 5]);
    ctx.lineDashOffset = 5;
    ctx.strokeStyle = 'blue';
    ctx.lineWidth = 3;
    
    ctx.beginPath();
    ctx.moveTo(50, 100);
    ctx.lineTo(250, 100);
    ctx.stroke();
</script>

</body>
</html>

在这个基本示例中,我们创建了一个 canvas 元素并获取了它的 2D 上下文。我们使用 setLineDash 设置了 10px 虚线和 5px 间隙的虚线模式。

5px 的 lineDashOffset 将模式偏移到第一个虚线的一半处。这说明了偏移量如何影响虚线模式在线上的起始位置。

动画虚线

本示例展示了如何使用 lineDashOffset 动画化虚线。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Animated Dashed Line</title>
</head>
<body>

<canvas id="myCanvas" width="300" height="200"></canvas>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    let offset = 0;
    
    function animate() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        ctx.setLineDash([15, 5]);
        ctx.lineDashOffset = -offset;
        ctx.strokeStyle = 'red';
        ctx.lineWidth = 4;
        
        ctx.beginPath();
        ctx.moveTo(50, 100);
        ctx.lineTo(250, 100);
        ctx.stroke();
        
        offset++;
        if (offset > 20) offset = 0;
        
        requestAnimationFrame(animate);
    }
    
    animate();
</script>

</body>
</html>

此示例创建了一个动画,其中虚线似乎在移动。我们使用 requestAnimationFrame 来创建平滑的动画循环。

offset 变量在每一帧都会递增,并且我们将其负值应用于 lineDashOffset。当 offset 超过 20 时,它会重置为 0,从而创建一个无缝循环。该线似乎连续向右滚动。

虚线圆动画

本示例演示了如何使用 lineDashOffset 动画化虚线圆。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Dashed Circle Animation</title>
</head>
<body>

<canvas id="myCanvas" width="300" height="300"></canvas>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    let offset = 0;
    
    function animate() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        ctx.setLineDash([10, 5]);
        ctx.lineDashOffset = offset;
        ctx.strokeStyle = 'green';
        ctx.lineWidth = 5;
        
        ctx.beginPath();
        ctx.arc(150, 150, 100, 0, Math.PI * 2);
        ctx.stroke();
        
        offset += 0.5;
        if (offset > 15) offset = 0;
        
        requestAnimationFrame(animate);
    }
    
    animate();
</script>

</body>
</html>

在这里,我们动画化一个虚线圆以创建加载旋转器效果。lineDashOffset 以较慢的速度(每帧 0.5)递增,以实现平滑的运动。

随着虚线模式沿着圆周移动,圆似乎在旋转。此技术常用于加载指示器和进度动画。

多条动画线

本示例展示了多条具有不同虚线模式和偏移量的线。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Multiple Animated Lines</title>
</head>
<body>

<canvas id="myCanvas" width="400" height="300"></canvas>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    let offset1 = 0;
    let offset2 = 0;
    let offset3 = 0;
    
    function animate() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        // First line
        ctx.setLineDash([20, 10]);
        ctx.lineDashOffset = offset1;
        ctx.strokeStyle = 'blue';
        ctx.lineWidth = 3;
        ctx.beginPath();
        ctx.moveTo(50, 50);
        ctx.lineTo(350, 50);
        ctx.stroke();
        
        // Second line
        ctx.setLineDash([10, 5, 5, 5]);
        ctx.lineDashOffset = offset2;
        ctx.strokeStyle = 'red';
        ctx.lineWidth = 4;
        ctx.beginPath();
        ctx.moveTo(50, 150);
        ctx.lineTo(350, 150);
        ctx.stroke();
        
        // Third line
        ctx.setLineDash([5, 3]);
        ctx.lineDashOffset = offset3;
        ctx.strokeStyle = 'green';
        ctx.lineWidth = 2;
        ctx.beginPath();
        ctx.moveTo(50, 250);
        ctx.lineTo(350, 250);
        ctx.stroke();
        
        offset1 += 1;
        offset2 += 2;
        offset3 += 3;
        
        if (offset1 > 30) offset1 = 0;
        if (offset2 > 20) offset2 = 0;
        if (offset3 > 8) offset3 = 0;
        
        requestAnimationFrame(animate);
    }
    
    animate();
</script>

</body>
</html>

此示例创建了三条具有不同虚线模式的水平线。每条线都有自己的 offset 变量,以不同的速率递增。

第一条线使用了简单的虚线模式,第二条使用了更复杂的模式,第三条使用了非常短的模式。不同的动画速度创造了有趣的视觉效果。

交互式 lineDashOffset

本示例演示了通过鼠标与 lineDashOffset 进行交互控制。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Interactive lineDashOffset</title>
</head>
<body>

<canvas id="myCanvas" width="400" height="300"></canvas>
<p>Move mouse horizontally to change dash offset</p>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    canvas.addEventListener('mousemove', (e) => {
        const rect = canvas.getBoundingClientRect();
        const x = e.clientX - rect.left;
        const offset = x / 2;
        
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        ctx.setLineDash([15, 10, 5, 10]);
        ctx.lineDashOffset = offset;
        ctx.strokeStyle = 'purple';
        ctx.lineWidth = 4;
        
        ctx.beginPath();
        ctx.moveTo(50, 150);
        ctx.lineTo(350, 150);
        ctx.stroke();
        
        // Display current offset
        ctx.fillStyle = 'black';
        ctx.font = '16px Arial';
        ctx.fillText(`Offset: ${offset.toFixed(1)}`, 50, 50);
    });
    
    // Initial draw
    ctx.setLineDash([15, 10, 5, 10]);
    ctx.lineDashOffset = 0;
    ctx.strokeStyle = 'purple';
    ctx.lineWidth = 4;
    ctx.beginPath();
    ctx.moveTo(50, 150);
    ctx.lineTo(350, 150);
    ctx.stroke();
</script>

</body>
</html>

此示例通过将 lineDashOffset 与鼠标位置绑定,使其具有交互性。水平移动鼠标可以实时更改 offset 值。

当前的 offset 值以文本形式显示。这说明了 lineDashOffset 如何用于交互式图形和视觉反馈。

来源

MDN lineDashOffset 文档

在本文中,我们探讨了使用 lineDashOffset 创建动画和交互式虚线的各种技术。这个强大的属性为动态 canvas 图形提供了许多可能性。

作者

我叫 Jan Bodnar,是一名热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直撰写编程文章。迄今为止,我已撰写了 1400 多篇文章和 8 本电子书。我在教授编程方面拥有十多年的经验。

列出 所有 JS Canvas 教程