高分辨率imac-webView上的画布绘制滞后



我正在尝试使用鼠标移动事件模拟钢笔绘图工具。

elCanvas.on("mousedown", function(e){
            moving = true;
            var position = getPos(e);
            points = [];
            points.push(position);
            ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
            ctx.beginPath();
            ctx.moveTo(position.x, position.y);
}
elCanvas.on("mousemove", function(e){
            if (moving) {
                var curr = getPos(e);
                points.push(curr);
                ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
                var p1 = points[0];
                var p2 = points[1];
                ctx.beginPath();
                ctx.moveTo(p1.x, p1.y);
                for (var i = 1, len = points.length; i < len; i++) {
                     var midPoint = midPointBtw(p1, p2);
                     ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y);
                     p1 = points[i];
                     p2 = points[i + 1];
                }
                ctx.lineTo(p1.x, p1.y);
                ctx.stroke();
}

现在这个代码在Safari中运行良好。但是鼠标在mac上的webView中严重滞后。我目前正在用iMac 5K显示屏测试它。

还有一件事我注意到了,代码在提供了更新的webView类OSX(WKWebView)的情况下运行良好(没有延迟)。但它有一个64位的要求。

所以我希望它能在带有4k或5k显示器的mac-webview上工作。

此外,我正在将结果与www.awwapp.com进行比较,后者在相同的webView中使用相同的设置效果良好。

注意:整点重绘逻辑对我来说是必要的,以保证平滑。如果我们在每一个动作后都盲目地划动,就会导致绘制粗糙。由于这段代码在Safari中运行良好,我主要担心的是为什么它在webView中运行缓慢?

这可以在不清除画布的情况下执行相同的操作,并且应该会执行得更好。

更新

添加了一个动画循环以使用requestAnimationFrame绘制点。这可能会带来额外的加速。您可以切换动画循环以查看它是否会产生影响。

var elCanvas = document.getElementById('can');
var ctx = elCanvas.getContext('2d');
var moving = false;
var points = [];
function getPos(evt) {
  var rect = elCanvas.getBoundingClientRect();
  return {
    x: evt.clientX - rect.left,
    y: evt.clientY - rect.top
  };
}
function midPointBtw(p1, p2) {
  return {
    x: p1.x + (p2.x - p1.x) / 2,
    y: p1.y + (p2.y - p1.y) / 2
  };
}
elCanvas.addEventListener("mousedown", function(e) {
  moving = true;
  var position = getPos(e);
  points = [];
  points.push(position);
  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  ctx.beginPath();
  ctx.moveTo(position.x, position.y);
});
elCanvas.addEventListener("mousemove", function(e) {
  if (moving) {
    // collect point
    var curr = getPos(e);
    points.push(curr);
    if (ani_status == "off") {
      // no animaion loop.. draw here.
      draw();
    } else {
      requestAnimationFrame(draw);
    }
  }
});
  
function draw() {
    if (points.length < 2) return;
    // Draw all the points we've collected since the last draw.
    var p1 = points[0];
    var p2 = points[1];
    ctx.beginPath();
    ctx.moveTo(p1.x, p1.y);
    for (var i = 1, len = points.length; i < len; i++) {
      var midPoint = midPointBtw(p1, p2);
      ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y);
      p1 = points[i];
      p2 = points[i + 1];
    }
  
    ctx.lineTo(p1.x, p1.y);
    ctx.stroke();
  
    // Keep the last point for next draw.
    points = [points[points.length-1]]
}
var ani_status = "off";
function toggleAni(value) {
  ani_status = value;
}
#can {
  border: 1px solid #777777;
}
<form>
animation-loop<br>
on<input type=radio name=ani-loop value='on'
onclick='toggleAni(this.value)'>
off<input type=radio name=ani-loop value='off' checked onclick='toggleAni(this.value)'></form>
<canvas id='can' width=600 height=400></canvas>

最新更新