我目前想用可变大小的圆圈填充给定文本(实际上......它是任何图像)。
到目前为止,我将文本写入<canvas>
,然后我使用:ctx.getImageData(0, 0, w, h)
获取图像数据,然后我开始循环遍历数组,寻找imageData中的像素。
我正面临这些问题,我不明白为什么:(
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;
}
答案 0 :(得分:2)
以下是一些优化代码的方法,作为开头:
Uint32Arrays
迭代并检测像素例如,您可以通过以下方式添加圈子:
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 强>
答案 1 :(得分:2)
让文字填充随机圆圈的更快方法是使用随机圆圈创建图案,并使用此图案填充文本。
模式创建非常快,只能进行一次
在循环期间,只需使用此模式填充文本(无需重新绘制圆圈)。
我做了一个小型演示,你可以改变模式甚至动画,所以你可以看到它很快。