javascript - 如何以最佳性能用可变大小的圆圈填充 Canvas 文本?

标签 javascript canvas geometry

我目前想用可变大小的圆圈填充给定的文本(实际上......它是任何图像)。

到目前为止,我将文本写入 <canvas> ,然后我通过以下方式获取图像数据:ctx.getImageData(0, 0, w, h) ,然后我开始循环遍历数组,从 imageData 中查找像素。

我面临这个问题,但我不明白为什么:(

  • 它太慢了(对于大文本),我该如何提高它的性能?
  • 是否有任何我可以使用的现有算法以便我可以研究它?
  • 如果我使用更大的 Canvas getImageData()从,性能太差,没有完成。

这是我到目前为止的代码:http://codepen.io/Goodwine/pen/xDvLk

function circleCanvas(ctx, minR, maxR, padding) {
  var c = $('<canvas>')[0].getContext('2d');
  var img = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
  var h = c.canvas.height = img.height;
  var w = c.canvas.width = img.width;

  var ban = [];
  for (var i = 0; i < img.data.length; i += 4) {
    if (img.data[i] != 100 || isBanned(ban, i, w))
      continue;
    var r = parseInt((Math.random() * 10000) % (maxR - minR) + minR);
    var x = Math.floor(i % (w * 4) / 4) + r;
    var y = Math.floor(i / (w * 4)) + r;
    drawCircle(c, x, y, r);
    ban.push({xi: x - r - padding, yi: y - r - padding, xf: x + r + padding, yf: y + r + padding});
  }
  return c;
}

.

// this function is used because I didn't find how else to improve performance
// it checks if there is a point in a "banned" range, and it ignores it in
// case it does.
function isBanned(ban, p, w) {
  var x = Math.floor(p % (w * 4) / 4);
  var y = Math.floor(p / (w * 4));
  for (var i in ban) {
    if (x >= ban[i].xi && x <= ban[i].xf && y >= ban[i].yi && y <= ban[i].yf)
      return true;
  }
  return false;
}

最佳答案

作为开始,您可以通过以下几种方法来优化代码:

  1. 向路径添加弧线并在末端填充而不是填充,每次都设置颜色。
  2. 使用 Uint32Arrays 迭代和检测像素
  3. 将 ban() 区域替换为计数器的增量

例如,您可以通过以下方式添加圈子:

function addCircle(ctx, x, y, r) {
  ctx.moveTo(x + r, y);
  ctx.arc(x, y, r, 0, 2*Math.PI);
}

然后使用 Uint32Array 迭代循环:

function circleCanvas(ctx, minR, maxR, padding) {

  var h = ctx.canvas.height;
  var w = ctx.canvas.width;
  var img = ctx.getImageData(0, 0, w, h);

  /// use an Uint32 buffer instead
  var buffer = new Uint32Array(img.data.buffer);

  /// create new path here
  ctx.beginPath();

  var ban = [];  /// I'm ignoring this in this example
  var skipLines; 

  for (var i = 0; i < buffer.length; i++) {
    if (buffer[i] === 0)
      continue;

    var r = (Math.random() * (maxR - minR) + minR)|0;
    var x = i % w;
    var y = Math.floor(i / w);

    addCircle(ctx, x, y, r);

    i += r * 2;
    if (x === 0) {
      skipLines = (r * 2 * Math.random() + r)|0;
      i += skipLines * w;
    }
  }

  /// fill at end
  ctx.fillStyle = '#000';
  ctx.fill();
}

<强> See update here

关于javascript - 如何以最佳性能用可变大小的圆圈填充 Canvas 文本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21343818/

相关文章:

Java快速查找点是否落在国家(多边形)内的方法

javascript - 如何在 Canvas 中绘制圆的下半部分

javascript - 在 javascript 中倒计时到明天的日期?

javascript - 如何影响jquery中具有相似(唯一)id的另一个div

javascript - 正则表达式匹配邮政编码和第一个字符

python - 如何使用canvasvg库

JavaScript Canvas 尺寸

Javascript 像素操作 : These aren't my colors

javascript - 如何获得FCM token ?

javascript - 在给定时间内在谷歌地图上动画半径增长/缩小圆