【问题标题】:canvas drawing Lag on High resolution imac webView高分辨率imac webView上的画布绘制滞后
【发布时间】:2016-04-19 11:56:11
【问题描述】:

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

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 中运行缓慢?

【问题讨论】:

  • 你有性能损失。为什么要在每个mousemove 上的所有点之间绘制所有曲线?您只需要在最后一点和新点之间绘制曲线
  • 那是因为如果我们在每个点之后盲目地描边,就会导致绘制粗糙。如此处所示perfectionkills.com/exploring-canvas-drawing-techniques 并且此代码在 safari 下运行良好。所以我认为webView代码也有改进的机会。

标签: javascript macos performance webview


【解决方案1】:

这在不清除画布的情况下做同样的事情,应该会更好。

更新

添加了一个动画循环以使用 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>

【讨论】:

  • 这行得通!那么,canvas clearing 成本高昂吗?或者这只是高分辨率的情况?
  • @Vrishank 我不认为清除画布的成本太高,但清除和重新绘制所有点的组合是。我添加了一个动画循环,你可以测试看看是否有帮助。
  • 我现在面临另一个问题。我认为它的范围有所不同,所以我将其发布为新问题。 stackoverflow.com/questions/36768997/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多