HTML Canvas fill with diagonal lines

Viewed 25

Good Evening, I'm working on a project where I need to create MSPaint clone, with one little functionality more. It must have a function that works almost like fill (bucket) but filling area matching pixels with diagonal lines (picture below) instead of filling all of them.

shape filled with diagonal lines

Here is codepen: https://codepen.io/Kamskyy/pen/eYrRxRB

Below is my working function code for filling - how can I modify it to draw diagonal lines instead?

function actionFill(startX,startY,currentColor) {
    //get imageData
    let colorLayer = offScreenCTX.getImageData(0, 0, offScreenCVS.width, offScreenCVS.height);

    let startPos = (startY*offScreenCVS.width + startX) * 4;

    //clicked color
    let startR = colorLayer.data[startPos]; 
    let startG = colorLayer.data[startPos+1];   
    let startB = colorLayer.data[startPos+2];
    let startA = colorLayer.data[startPos+3];
    
    //exit if color is the same
    if (currentColor.r === startR && currentColor.g === startG && currentColor.b === startB && currentColor.a === startA) {
        return;
    }
    //Start with click coords
    let pixelStack = [[startX,startY]];
    let newPos, x, y, pixelPos, reachLeft, reachRight;
    floodFill();
    function floodFill() {
        newPos = pixelStack.pop();
        x = newPos[0];
        y = newPos[1];

        //get current pixel position
        pixelPos = (y*offScreenCVS.width + x) * 4;
        // Go up as long as the color matches and are inside the canvas
        while(y >= 0 && matchStartColor(pixelPos)) {
            y--;
            pixelPos -= offScreenCVS.width * 4;
        }
        //Don't overextend
        pixelPos += offScreenCVS.width * 4;
        y++;
        reachLeft = false;
        reachRight = false;
        // Go down as long as the color matches and in inside the canvas
        while(y < offScreenCVS.height && matchStartColor(pixelPos)) {
            
            colorPixel(pixelPos);

            if(x > 0) {
                if(matchStartColor(pixelPos - 4)) {
                    if(!reachLeft) {
                        //Add pixel to stack
                        pixelStack.push([x - 1, y]);
                        reachLeft = true;
                    }
                } else if(reachLeft) {
                    reachLeft = false;
                }
            }
        
            if(x < offScreenCVS.width-1) {
                if(matchStartColor(pixelPos + 4)) {
                    if(!reachRight) {
                        //Add pixel to stack
                        pixelStack.push([x + 1, y]);
                        reachRight = true;
                    }
                } else if(reachRight) {
                    reachRight = false;
                }
            }
            y++;        
            pixelPos += offScreenCVS.width * 4;
        }
        
        if (pixelStack.length) {
            floodFill();
            // window.setTimeout(floodFill, 100);
        }
    }

    //render floodFill result
    offScreenCTX.putImageData(colorLayer, 0, 0);

    //helpers
    function matchStartColor(pixelPos) {
        let r = colorLayer.data[pixelPos];  
        let g = colorLayer.data[pixelPos+1];    
        let b = colorLayer.data[pixelPos+2];
        let a = colorLayer.data[pixelPos+3];
        return (r === startR && g === startG && b === startB && a === startA);
    }

    function colorPixel(pixelPos) {
        colorLayer.data[pixelPos] = currentColor.r;
        colorLayer.data[pixelPos+1] = currentColor.g;
        colorLayer.data[pixelPos+2] = currentColor.b;
        //not ideal
        colorLayer.data[pixelPos+3] = currentColor.a;
    }
}

0 Answers
Related