You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

HTML Canvas的setLineDash函数失效问题求助

Canvas中ctx.setLineDash设置道路虚线不显示问题

问题描述

我在学习Free Code Camp的JavaScript自动驾驶课程(进度约41分50秒)时遇到了问题:尝试用ctx.setLineDash([20,20])绘制道路内部的虚线,但添加该语句后线条完全不显示。原本绘制实线一切正常,我也试过把这条语句放在beginPath()之后等不同位置,都没有效果。

现有代码

Road.js

class Road {
  constructor(x, width, laneCount = 3) {
    this.x = x;
    this.width = width;
    this.laneCount = laneCount;
    this.left = x - width / 2;
    this.right = x + width / 2;
    const infinity = 1000000000;
    this.top = -infinity;
    this.bottom = infinity;
  }

  draw(ctx) {
    ctx.lineWidth = 5;
    ctx.strokeStyle = "white";

    for (let i = 0; i <= this.laneCount; i++) {
      const x = lerp(
        this.left,
        this.right,
        i/this.laneCount
      )
      if (i > 0 && i < this.laneCount) {
        ctx.setLineDash([20,20]);
      } else {
        ctx.setLineDash([])
      }
      ctx.beginPath();
      ctx.moveTo(x, this.top);
      ctx.lineTo(x, this.bottom);
      ctx.stroke();
    }
  }
}

function lerp(A, B, t) {
  return A + (B-A)*t;
}

main.js

const canvas = document.getElementById("myCanvas");
canvas.height = window.innerHeight;
canvas.width = 200;
const ctx = canvas.getContext("2d");
const road = new Road(canvas.width / 2, canvas.width * 0.9, 4);

animate();

function animate() {
  canvas.height = window.innerHeight;
  road.draw(ctx);
  requestAnimationFrame(animate);
}

HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link rel="stylesheet" href="style.css">
  <title>Self-Driving Car</title>
</head>
<body>
  <canvas id="myCanvas"></canvas>
  <script src="road.js"></script>
  <script src="main.js"></script>
</body>
</html>

CSS

body {
  margin: 0;
  background: darkgrey;
  overflow: hidden;
  text-align: center;
}

#myCanvas {
  background: lightgray;
}

解决方案

问题根源是你设置的top和bottom值过大(10亿像素),虚线的循环周期(20像素实线+20像素空白)会导致当前画布可见区域刚好落在虚线的空白段,因此看不到线条。

修复方法

选择以下任意一种即可:

  1. 缩小道路上下边界范围:不要用无限大的值,基于画布高度设置足够覆盖可见区域的范围。修改Road类构造函数:

    constructor(x, width, laneCount = 3) {
      this.x = x;
      this.width = width;
      this.laneCount = laneCount;
      this.left = x - width / 2;
      this.right = x + width / 2;
      // 用画布高度的倍数替代无限大值
      const extendHeight = window.innerHeight * 2;
      this.top = -extendHeight;
      this.bottom = extendHeight;
    }
    
  2. 调整虚线偏移量:强制让虚线从可见区域开始绘制,在设置setLineDash后添加偏移控制:

    if (i > 0 && i < this.laneCount) {
      ctx.setLineDash([20,20]);
      ctx.lineDashOffset = -window.scrollY; // 动态匹配滚动位置,或设为0固定偏移
    } else {
      ctx.setLineDash([]);
    }
    

另外,建议将setLineDash放在beginPath之后,更符合Canvas绘制逻辑:

ctx.beginPath();
if (i > 0 && i < this.laneCount) {
  ctx.setLineDash([20,20]);
} else {
  ctx.setLineDash([]);
}
ctx.moveTo(x, this.top);
ctx.lineTo(x, this.bottom);
ctx.stroke();

修改后即可正常显示虚线。

内容的提问来源于stack exchange,提问作者ResistingGuide4

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 12:43:31