UNPKG

painterro

Version:
188 lines (158 loc) 5.84 kB
import ColorPicker, { HexToRGB, rgbToHex } from './colorPicker'; export default class PaintBucket { constructor(main) { this.main = main; this.canvasWidth = 600; this.canvasHeight = 420; this.el = this.main.toolContainer; this.input = this.el.querySelector('.ptro-text-tool-input'); } init() { this.ctx = this.main.ctx; this.canvas = this.main.canvas; this.colorLayerData = this.ctx.getImageData(0, 0, this.canvasWidth, this.canvasHeight); this.drawingAreaX = 0; this.drawingAreaY = 0; this.canvasWidth = this.canvas.width this.canvasHeight = this.canvas.height this.drawingAreaWidth = this.canvasWidth; this.drawingAreaHeight = this.canvasHeight; } handleMouseDown(event) { const mainClass = event.target.classList[0]; const scale = this.main.getScale(); if (mainClass === 'ptro-crp-el') { this.init(); this.colorLayerData = this.ctx.getImageData(0, 0, this.canvasWidth, this.canvasHeight); if (!this.active) { this.input.innerHTML = '<br>'; this.pendingClear = true; } this.active = true; const cord = [ (event.clientX - this.main.elLeft()) + this.main.scroller.scrollLeft, (event.clientY - this.main.elTop()) + this.main.scroller.scrollTop, ]; const cur = { x: cord[0] * scale, y: cord[1] * scale, }; this.paintAt(cur.x, cur.y); } } paintAt(startX, startY) { startX = Math.round(startX); startY = Math.round(startY - 1); startX = (startX > 0) ? startX : 0; startY = (startY > 0) ? startY : 0; // get clicked on color this.getClickedOnColor(startX, startY); var pixelPos = (startY * this.canvasWidth + startX) * 4; var pixelColor = this.getPixelColor(this.colorLayerData, pixelPos); var r = pixelColor.r; var g = pixelColor.g; var b = pixelColor.b; var a = pixelColor.a; const curColor = HexToRGB( this.main.colorWidgetState.fill.palleteColor ); this.color = this.main.colorWidgetState.fill.palleteColor; if (r === curColor.r && g === curColor.g && b === curColor.b) { // Return because trying to fill with the same color return; } this.floodFill(startX, startY, r, g, b); this.ctx.putImageData(this.colorLayerData, 0, 0); this.main.worklog.captureState(); } // returns true if the current pixel's color matches the clicked on color. matchStartColor(pixelPos) { var pixelColor = this.getPixelColor(this.colorLayerData, pixelPos); var v = this.matchClickedColor(pixelColor.r, pixelColor.g, pixelColor.b, pixelColor.a); return v; } matchClickedColor(r, g, b, a) { const limit = this.main.params.bucketSensivity; var matchedR = (Math.abs(r - this.clickedOnColor.r) < limit); var matchedG = (Math.abs(g - this.clickedOnColor.g) < limit); var matchedB = (Math.abs(b - this.clickedOnColor.b) < limit); var matchedA = (Math.abs(a - this.clickedOnColor.a) < limit); var v = (matchedR && matchedG && matchedB && matchedA); return v; } getClickedOnColor(x, y) { var pixelPos = (y * this.canvasWidth + x) * 4; var pixelColor = this.getPixelColor(this.colorLayerData, pixelPos); this.clickedOnColor = {r: pixelColor.r, g: pixelColor.g, b: pixelColor.b, a: pixelColor.a}; } floodFill(startX, startY, startR, startG, startB) { // console.log('flood: ' + startX + ' ' + startY + ' ' + startR + ' ' + startG + ' ' + startB); var newPos, x, y, pixelPos, reachLeft, reachRight, drawingBoundLeft = this.drawingAreaX, drawingBoundTop = this.drawingAreaY, drawingBoundRight = this.drawingAreaX + this.drawingAreaWidth - 1, drawingBoundBottom = this.drawingAreaY + this.drawingAreaHeight - 1, pixelStack = [[startX, startY]]; while (pixelStack.length) { newPos = pixelStack.pop(); x = newPos[0]; y = newPos[1]; // Get current pixel position pixelPos = (y * this.canvasWidth + x) * 4; const curColor = HexToRGB(this.color); // Go up as long as the color matches and are inside the canvas while (y >= drawingBoundTop && this.matchStartColor(pixelPos)) { y -= 1; pixelPos -= this.canvasWidth * 4; } pixelPos += this.canvasWidth * 4; y += 1; reachLeft = false; reachRight = false; // Go down as long as the color matches and in inside the canvas while (y <= drawingBoundBottom && this.matchStartColor(pixelPos)) { y += 1; this.colorPixel(pixelPos, curColor.r, curColor.g, curColor.b); if (x > drawingBoundLeft) { if (this.matchStartColor(pixelPos - 4)) { if (!reachLeft) { // Add pixel to stack pixelStack.push([x - 1, y]); reachLeft = true; } } else if (reachLeft) { reachLeft = false; } } if (x < drawingBoundRight) { if (this.matchStartColor(pixelPos + 4)) { if (!reachRight) { // Add pixel to stack pixelStack.push([x + 1, y]); reachRight = true; } } else if (reachRight) { reachRight = false; } } pixelPos += this.canvasWidth * 4; } } } colorPixel(pixelPos, r, g, b, a) { this.colorLayerData.data[pixelPos] = r; this.colorLayerData.data[pixelPos + 1] = g; this.colorLayerData.data[pixelPos + 2] = b; this.colorLayerData.data[pixelPos + 3] = a !== undefined ? a : 255; } getPixelColor(ctx, pixelPos) { var r = ctx.data[pixelPos]; var g = ctx.data[pixelPos + 1]; var b = ctx.data[pixelPos + 2]; var a = ctx.data[pixelPos + 3]; return {r: r, g: g, b: b, a: a}; } }