WXL
5 天以前 2140c5aae2032673cef7055df9738b9bacf37816
components/signature-panel/index.vue
@@ -150,8 +150,13 @@
// Canvas上下文
let ctx = null;
let isDrawing = false;
let lastX = 0;
let lastY = 0;
let lastDrawPoint = null; // 上次绘制到的位置(用于线段连接)
// 渲染控制(解决低性能机型 draw 异步导致丢帧断点)
let needsRender = false; // 是否有待渲染的指令
let renderLoop = null; // 渲染循环定时器
let isRendering = false; // 是否正在执行 draw
let renderTimeout = null; // draw 超时保护
// 配置
const colors = ['#000000', '#FF0000', '#0000FF', '#4CAF50'];
@@ -180,7 +185,9 @@
// 初始化Canvas
const initCanvas = () => {
  console.log('初始化Canvas...');
  console.log('Canvas尺寸:', props.canvasWidth, 'x', props.canvasHeight);
  // 停止可能存在的渲染循环
  stopRenderLoop();
  
  // 清空已有上下文
  ctx = null;
@@ -223,21 +230,24 @@
    return;
  }
  
  console.log('触摸开始:', e.touches[0]);
  isDrawing = true;
  hasDrawing.value = true;
  
  const touch = e.touches[0];
  lastX = touch.x;
  lastY = touch.y;
  lastDrawPoint = { x: touch.x, y: touch.y };
  
  // 开始新路径
  // 起笔画一个圆点(解决点击不画的问题)
  ctx.beginPath();
  ctx.moveTo(lastX, lastY);
  ctx.draw(true);
  ctx.arc(touch.x, touch.y, currentWidth.value / 2, 0, 2 * Math.PI);
  ctx.setFillStyle(currentColor.value);
  ctx.fill();
  needsRender = true;
  // 启动渲染循环
  startRenderLoop();
};
// 触摸移动
// 触摸移动(每次直接画线段,用渲染循环控制 draw 频率)
const onTouchMove = (e) => {
  if (!isDrawing || !ctx) return;
  
@@ -245,20 +255,62 @@
  const x = touch.x;
  const y = touch.y;
  
  // 绘制线条
  // 立即画线段(指令加入队列,不调 draw)
  ctx.beginPath();
  ctx.moveTo(lastDrawPoint.x, lastDrawPoint.y);
  ctx.lineTo(x, y);
  ctx.setStrokeStyle(currentColor.value);
  ctx.setLineWidth(currentWidth.value);
  ctx.setLineCap('round');
  ctx.setLineJoin('round');
  ctx.stroke();
  ctx.draw(true);
  
  // 更新最后位置
  lastX = x;
  lastY = y;
  lastDrawPoint = { x, y };
  needsRender = true;
};
// 启动渲染循环(定时批量调用 draw,避免每次 touchmove 都 draw 导致丢帧)
const startRenderLoop = () => {
  if (renderLoop) return;
  renderLoop = setInterval(() => {
    if (needsRender && !isRendering) {
      needsRender = false;
      isRendering = true;
      ctx.draw(true, () => {
        isRendering = false;
      });
      // 超时保护:防止 draw 回调不执行导致卡死
      if (renderTimeout) clearTimeout(renderTimeout);
      renderTimeout = setTimeout(() => {
        isRendering = false;
      }, 50);
    }
  }, 16);
};
// 停止渲染循环
const stopRenderLoop = () => {
  if (renderLoop) {
    clearInterval(renderLoop);
    renderLoop = null;
  }
  if (renderTimeout) {
    clearTimeout(renderTimeout);
    renderTimeout = null;
  }
  isRendering = false;
};
// 触摸结束
const onTouchEnd = () => {
  console.log('触摸结束');
  isDrawing = false;
  // 停止渲染循环
  stopRenderLoop();
  // 确保最后的指令被渲染
  if (needsRender) {
    needsRender = false;
    ctx.draw(true);
  }
};
// 选择颜色
@@ -284,7 +336,9 @@
    return;
  }
  
  console.log('清空画布');
  // 停止渲染循环
  stopRenderLoop();
  needsRender = false;
  
  // 清空画布
  ctx.setFillStyle('#FFFFFF');