我制作了一个简单的脚本来为像素和所有附近的像素着色
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="http://code.jquery.com/jquery-latest.js"></script>
<title>
Click foto
</title>
<style type="text/css">
/*<![CDATA[*/
html, body{
height: 100%;
}
/*]]>*/
</style>
</head>
<body>
<div id="canvasDiv">
</div>
</body>
<script>
var canvasDiv = document.getElementById('canvasDiv');
canvas = document.createElement('canvas');
canvas.setAttribute('width', 500);
canvas.setAttribute('height', 500);
canvas.setAttribute('id', 'canvas');
$(canvasDiv).prepend(canvas);
if(typeof G_vmlCanvasManager != 'undefined') {
canvas = G_vmlCanvasManager.initElement(canvas);
}
var context = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function() {
$(canvas).attr({width : this.width, height: this.height});
context.drawImage(imageObj,0,0);
};
imageObj.src = 'cartina_italia.png';
$('#canvas').click(function(e){
console.time('click');
mouseX = e.pageX - this.offsetLeft;
mouseY = e.pageY - this.offsetTop;
c = this.getContext('2d');
p = c.getImageData(mouseX, mouseY, 1, 1).data;
hex = ("000000" + rgbToHex(p[0], p[1], p[2])).slice(-6);
console.timeEnd('click');
console.time('selectArea');
selectArea(mouseX,mouseY,c,hex);
console.timeEnd('selectArea');
});
function selectArea(x,y,c,color){
if (x>=0 && y>=0){
p = c.getImageData(x, y, 1, 1).data;
hex =("000000" + rgbToHex(p[0], p[1], p[2])).slice(-6);
if (color==hex){
c.fillStyle = "rgba(255,0,0,0.1)";
c.fillRect( x, y, 1, 1 );
selectArea(x+1,y,c,color);
selectArea(x-1,y,c,color);
selectArea(x,y+1,c,color);
selectArea(x,y-1,c,color);
}
}
}
function rgbToHex(r, g, b) {
if (r > 255 || g > 255 || b > 255)
throw "Invalid color component";
return ((r << 16) | (g << 8) | b).toString(16);
}
</script>
</html>
我正在测试该文件:
http://mappa.italiachecambia.org/assets/homemap/cartina_italia.png
前3次,我单击一个要着色的区域时,我的响应速度很慢(1000-5000ms),后3次该函数在50ms内结束我无法使用jsfiddle来显示问题BC我得到跨域错误
该代码是简单的递归函数,可更改所单击像素的颜色并在附近像素上启动,直到像素颜色与第一个不同为止。
但我不明白为什么前3次反应如此缓慢,而第4次反应却有0滞后...。
最佳答案
您应该缓存孔图像的imageData并使用该数据,而不是在每个getImageData
调用中调用selectArea
。您也可以考虑实现迭代,以防止出现最大的调用堆栈错误。
这是一个例子:
var ExtendedCanvas = (function() {
var context, data, canvas;
function ExtendedCanvas(selector, imageSrc) {
var wrapper = document.querySelector(selector);
this.element = canvas = document.createElement('canvas');
context = this.element.getContext('2d');
loadImage.call(this, imageSrc, function(image) {
canvas.setAttribute('width', image.width);
canvas.setAttribute('height', image.height);
context.drawImage(image,0,0);
data = context.getImageData(0,0,canvas.width, canvas.height);
});
wrapper.appendChild(this.element);
}
function loadImage(src, cb) {
var image = new Image();
var canvas = this.element;
image.onload = function() {
cb(this);
}
image.crossOrigin = 'Anonymous';
image.src = src;
}
ExtendedCanvas.prototype.getPixelIndex = function(x, y) {
return (Math.floor(y) * canvas.width + Math.floor(x)) * 4;
}
ExtendedCanvas.prototype.getPixelColor = function(x, y) {
var index = this.getPixelIndex(x, y);
var d = data.data;
var r = d[index];
var g = d[index + 1];
var b = d[index + 2];
var a = d[index + 3];
return [r, g, b, a];
}
ExtendedCanvas.prototype.setPixelColor = function(x, y, color) {
var index = this.getPixelIndex(x, y);
var d = data.data;
d[index] = color[0];
d[index + 1] = color[1];
d[index + 2] = color[2];
d[index + 3] = color[3];
}
ExtendedCanvas.prototype.fill = function(x, y, fillColor) {
if(x < 0 || y < 0 || x > canvas.width || y > canvas.height) {
return;
}
fillColor = fillColor || [0,0,0,255];
var stack = [];
var color = this.getPixelColor(x, y).join();
if(color === fillColor) {
return;
}
stack.push([x, y]);
context.fillStyle = fillColor;
if(color === fillColor.join()) {
return;
}
while(stack.length > 0) {
var position = stack.pop();
var posX = position[0];
var posY = position[1];
var posColor = this.getPixelColor(posX, posY).join();
if(posColor === color) {
this.setPixelColor(posX, posY, fillColor);
stack.push([posX, posY + 1]);
stack.push([posX, posY - 1]);
stack.push([posX + 1, posY]);
stack.push([posX - 1, posY]);
}
}
context.putImageData(data, 0, 0);
}
return ExtendedCanvas;
})();
document.addEventListener('DOMContentLoaded', function() {
var c = new ExtendedCanvas('#canvasWrapper', 'https://i.imgur.com/QWaKVGO.png');
c.element.addEventListener('click', function(e) {
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
c.fill(x, y);
});
});
<div id="canvasWrapper"></div>