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

JS基于lerp的随机游走异常:点持续向左上角偏移求解

问题根源分析与修复

核心问题:变量操作逻辑混乱 + 未使用Lerp函数

你代码里的两个致命问题导致了点持续向左上角偏移:

  1. 绘制目标与修改目标不匹配:实际绘制的是pointEnd数组里的坐标,但只有向左(n=3)、向上(n=0)的操作是修改pointEnd,而向右(n=2)、向下(n=1)的操作修改的是point数组——但point从未被用来更新pointEnd,等于这两个方向的偏移完全没生效。
  2. Lerp函数未被调用:你定义了lerp函数,但整个代码里没有任何地方使用它来让pointEnd向point插值移动,等于point的修改完全是无效操作。

另外还有两个次要问题:

  • 计数数组初始化错误:count = Array.from(new Array(4).keys())生成的是[0,1,2,3],不是初始为0的计数数组,会导致分布统计从一开始就不准,应该用new Array(4).fill(0)。
  • 错误的动画循环:setInterval嵌套requestAnimationFrame会导致重复触发渲染,requestAnimationFrame本身会按浏览器帧率自动执行,不需要额外包裹定时器。

修复后的代码

JavaScript部分

const canvas = document.querySelector('#myCanvas');
const ctx = canvas.getContext('2d');

const width = canvas.clientWidth;
const height = canvas.clientHeight;

canvas.width = width;
canvas.height = height;

// 点的数量
const AMOUNT = 15;
// 屏幕中心坐标
const centerX = width / 2;
const centerY = height / 2;
// 点的大小
const SIZE = 8;
// Lerp插值速度
const LERP_SPEED = 0.05;

// 所有点的目标位置(随机游走的目标点)
let pointsTarget = Array.from({ length: AMOUNT }, () => [centerX, centerY]);
// 所有点的当前绘制位置(通过Lerp向目标点移动)
let pointsCurrent = Array.from({ length: AMOUNT }, () => [centerX, centerY]);

// 随机方向计数(初始化为0)
let count = new Array(4).fill(0);

function lerp(start, end, speed) {
  return start + (end - start) * speed;
}

function render() {
  // 清空画布
  ctx.fillStyle = 'rgba(255, 255, 255, 1)';
  ctx.fillRect(0, 0, width, height);

  // 遍历所有点
  for (let i = 0; i < AMOUNT; i++) {
    const target = pointsTarget[i];
    const current = pointsCurrent[i];

    // 更新当前位置:通过Lerp向目标点移动
    current[0] = lerp(current[0], target[0], LERP_SPEED);
    current[1] = lerp(current[1], target[1], LERP_SPEED);

    // 绘制当前点
    ctx.fillStyle = 'black';
    ctx.fillRect(current[0] - SIZE / 2, current[1] - SIZE / 2, SIZE, SIZE);

    // 生成随机方向(0:上, 1:下, 2:右, 3:左)
    const n = Math.floor(Math.random() * 4);
    count[n]++;

    // 更新目标点的位置
    switch(n) {
      case 0: target[1] -= 1; break; // 上
      case 1: target[1] += 1; break; // 下
      case 2: target[0] += 1; break; // 右
      case 3: target[0] -= 1; break; // 左
    }
  }

  // 统计并打印分布(放在循环外,避免每秒打印上千次)
  const sum = count.reduce((a, b) => a + b);
  console.log(count.map((val, i) => `${i}:${Math.round((val / sum) * 100)}%`).join(' | '));

  // 继续下一帧渲染
  requestAnimationFrame(render);
}

// 启动动画
requestAnimationFrame(render);

HTML部分

<canvas id="myCanvas" style="width: 800px; height: 600px; border: 1px solid #ccc;"></canvas>

修复说明

  1. 统一变量职责:将原有的points和pointsEnd改为pointsTarget(随机游走的目标点)和pointsCurrent(当前绘制的插值点),逻辑更清晰。
  2. 调用Lerp函数:每次渲染时用lerp更新当前点向目标点移动,实现平滑的游走效果。
  3. 修正方向操作:所有随机方向的修改都作用于pointsTarget,确保四个方向的偏移都能传递到最终绘制的点上。
  4. 修正计数初始化:用fill(0)初始化计数数组,保证分布统计准确。
  5. 优化动画循环:直接用requestAnimationFrame递归调用,避免冗余的定时器嵌套。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 09:15:34