2017-09-16 36 views
0

我爲顏色簡單的腳本像素和所有的近旁像素搭配同色系慢腳本

<!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我得到了交叉原點錯誤

該代碼是簡單的遞歸函數,可以改變點擊像素的顏色並在近像素上發射,直到像素顏色不同於杉木ST
但我不明白爲什麼第3次有這樣的響應速度慢後第4次是0滯後....

+0

我現在發現的低性能的線是'P = c.getImageData(X,Y,1,1)。數據;'後被稱爲X倍的更快 – Trigun

回答

1

您應該緩存孔圖像的imageData,並與數據,而不是工作每調用selectArea調用getImageData。你也可以考慮實現迭代,以防止最大的調用堆棧錯誤。

下面是一個例子:

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>

+0

謝謝:-)我今天發現了帆布標籤,並且是我的第一次嘗試:-)不知道我可以使用getimagedata獲取全部區域..谷歌搜索指出我getImageData,我是使用:-) – Trigun