更好的微調功能。
雖然給出答案的作品它包含了potencial危險的漏洞,創建一個新的畫布,而不是裁剪現有帆布(鏈接區域搜索)是有點低效。
如果您對畫布有其他參考,這是很常見的,因爲通常有兩個對畫布的引用,例如canvas
和ctx.canvas
,創建第二個畫布會有問題。關閉可能會導致難以刪除引用,並且如果封閉結束了某個事件,則可能永遠無法刪除該引用。
的缺陷是當畫布不包含像素。允許將畫布設置爲零大小(canvas.width = 0; canvas.height = 0;
不會引發錯誤),但某些函數不能接受零作爲參數,並且會引發錯誤(例如ctx.getImageData(0,0,ctx.canvas.width,ctx.canvas.height);
是常見做法,但如果畫布沒有大小則會引發錯誤) 。由於這與調整大小沒有直接關係,因此這種潛在的崩潰可以被忽略,並進入生產代碼。
鏈接的搜索檢查每個搜索的所有像素,包括一個簡單的break
當發現邊緣會改善搜索時,仍然有平均更快的搜索。同時在兩個方向上搜索,上下左右都會減少迭代次數。而不是爲每個像素測試計算每個像素的地址,您可以通過遍歷索引來提高性能。例如data[idx++]
比data[x + y * w]
一個更強大的解決方案快得多。
以下函數將使用兩遍搜索從適當位置的畫布裁剪透明邊,同時考慮第一遍的結果以減少第二遍的搜索區域。
如果沒有像素,它將不裁剪畫布,但會返回false
以便採取行動。如果畫布包含像素,它將返回true
。
在剪切到位時,不需要更改對畫布的任何引用。
// ctx is the 2d context of the canvas to be trimmed
// This function will return false if the canvas contains no or no non transparent pixels.
// Returns true if the canvas contains non transparent pixels
function trimCanvas(ctx) { // removes transparent edges
var x, y, w, h, top, left, right, bottom, data, idx1, idx2, found, imgData;
w = ctx.canvas.width;
h = ctx.canvas.height;
if (!w && !h) { return false }
imgData = ctx.getImageData(0, 0, w, h);
data = new Uint32Array(imgData.data.buffer);
idx1 = 0;
idx2 = w * h - 1;
found = false;
// search from top and bottom to find first rows containing a non transparent pixel.
for (y = 0; y < h && !found; y += 1) {
for (x = 0; x < w; x += 1) {
if (data[idx1++] && !top) {
top = y + 1;
if (bottom) { // top and bottom found then stop the search
found = true;
break;
}
}
if (data[idx2--] && !bottom) {
bottom = h - y - 1;
if (top) { // top and bottom found then stop the search
found = true;
break;
}
}
}
if (y > h - y && !top && !bottom) { return false } // image is completely blank so do nothing
}
top -= 1; // correct top
found = false;
// search from left and right to find first column containing a non transparent pixel.
for (x = 0; x < w && !found; x += 1) {
idx1 = top * w + x;
idx2 = top * w + (w - x - 1);
for (y = top; y <= bottom; y += 1) {
if (data[idx1] && !left) {
left = x + 1;
if (right) { // if left and right found then stop the search
found = true;
break;
}
}
if (data[idx2] && !right) {
right = w - x - 1;
if (left) { // if left and right found then stop the search
found = true;
break;
}
}
idx1 += w;
idx2 += w;
}
}
left -= 1; // correct left
if(w === right - left + 1 && h === bottom - top + 1) { return true } // no need to crop if no change in size
w = right - left + 1;
h = bottom - top + 1;
ctx.canvas.width = w;
ctx.canvas.height = h;
ctx.putImageData(imgData, -left, -top);
return true;
}
@ K3N編輯解釋了爲什麼它不是重複的。請重新打開。 – WackGet
但是,重新打開後,您只需使用您從該方法獲得的座標,然後使用drawImage()將新的畫布移至區域。 – K3N