Friday 30 October 2020

How can i fill color between 4 lines in canvas?

I am trying to fill color between lines in ionic. I want fill color between line when four line touch each other. For that i created a canvas demo with touch event.

html file:

 <canvas #canvasDraw width="300" height="300" (touchstart)="handleTouchStart($event)"
        (touchmove)="handleTouchmove($event)" 
        (touchend)="handleTouchEnd($event)">
        You need a browser that supports HTML5!
 </canvas>

ts file:

import { Component, ElementRef, ViewChild } from '@angular/core';

@Component({
    selector: 'app-home',
    templateUrl: 'home.page.html',
    styleUrls: ['home.page.scss'],
})
export class HomePage {
    @ViewChild('canvasDraw', { static: false }) canvas: ElementRef;

    canvasElement: any;
    lines: any[];
    isDown: boolean = false;
    startX: number;
    startY: number;
    nearest: any;
    offsetX: any;
    offsetY: any;

    constructor() {
    }

    ngAfterViewInit() {
        this.canvasElement = this.canvas.nativeElement;
        this.lines = [];
        this.lines.push({ x0: 75, y0: 25, x1: 125, y1: 25 });
        this.lines.push({ x0: 75, y0: 100, x1: 125, y1: 100 });
        this.lines.push({ x0: 50, y0: 35, x1: 50, y1: 85 });
        this.lines.push({ x0: 150, y0: 35, x1: 150, y1: 85 });
        this.draw();
        //this.reOffset();
        requestAnimationFrame(() => {
            this.reOffset()
        })
    }

    reOffset() {
        let BB = this.canvasElement.getBoundingClientRect();
        this.offsetX = BB.left;
        this.offsetY = BB.top;
    }

    // select the this.nearest line to the mouse
    closestLine(mx, my) {
        let dist = 100000000;
        let index, pt;
        for (let i = 0; i < this.lines.length; i++) {
            //
            let xy = this.closestXY(this.lines[i], mx, my);
            //
            let dx = mx - xy.x;
            let dy = my - xy.y;
            let thisDist = dx * dx + dy * dy;
            if (thisDist < dist) {
                dist = thisDist;
                pt = xy;
                index = i;
            }
        }
        let line = this.lines[index];
        return ({ pt: pt, line: line, originalLine: { x0: line.x0, y0: line.y0, x1: line.x1, y1: line.y1 } });
    }

    // linear interpolation -- needed in setClosestLine()
    lerp(a, b, x) {
        return (a + x * (b - a));
    }

    // find closest XY on line to mouse XY
    closestXY(line, mx, my) {
        let x0 = line.x0;
        let y0 = line.y0;
        let x1 = line.x1;
        let y1 = line.y1;
        let dx = x1 - x0;
        let dy = y1 - y0;
        let t = ((mx - x0) * dx + (my - y0) * dy) / (dx * dx + dy * dy);
        t = Math.max(0, Math.min(1, t));
        let x = this.lerp(x0, x1, t);
        let y = this.lerp(y0, y1, t);
        return ({ x: x, y: y });
    }

    // draw the scene
    draw() {
        let ctx = this.canvasElement.getContext('2d');
        let cw = this.canvasElement.width;
        let ch = this.canvasElement.height;
        ctx.clearRect(0, 0, cw, ch);
        // draw all lines at their current positions
        for (let i = 0; i < this.lines.length; i++) {
            this.drawLine(this.lines[i], 'black');
        }
        // draw markers if a line is being dragged
        if (this.nearest) {
            // point on line this.nearest to mouse
            ctx.beginPath();
            ctx.arc(this.nearest.pt.x, this.nearest.pt.y, 5, 0, Math.PI * 2);
            ctx.strokeStyle = 'red';
            ctx.stroke();
            // marker for original line before dragging
            this.drawLine(this.nearest.originalLine, 'red');
            // hightlight the line as its dragged
            this.drawLine(this.nearest.line, 'red');
        }        
    }

    drawLine(line, color) {
        let ctx = this.canvasElement.getContext('2d');
        ctx.beginPath();
        ctx.moveTo(line.x0, line.y0);
        ctx.lineTo(line.x1, line.y1);
        ctx.strokeStyle = color;
        ctx.stroke();
    }

    handleTouchStart(e) {
        // tell the browser we're handling this event
        let tch = e.touches[0];
        // tch.preventDefault();
        // tch.stopPropagation();
        // mouse position
        this.startX = tch.clientX - this.offsetX;
        this.startY = tch.clientY - this.offsetY;
        // find this.nearest line to mouse
        this.nearest = this.closestLine(this.startX, this.startY);
        this.draw();
        // set dragging flag
        this.isDown = true;
    }

    handleTouchEnd(e) {
        // tell the browser we're handling this event
        let tch = e.touches[0];
        // tch.preventDefault();
        // tch.stopPropagation();
        // clear dragging flag
        this.isDown = false;
        this.nearest = null;
        this.draw();
    }

    handleTouchmove(e) {
        if (!this.isDown) { return; }
        // tell the browser we're handling this event
        let tch = e.touches[0];
        // tch.preventDefault();
        // tch.stopPropagation();
        // mouse position
        const mouseX = tch.clientX - this.offsetX;
        const mouseY = tch.clientY - this.offsetY;
        // calc how far mouse has moved since last mousemove event
        let dx = mouseX - this.startX;
        let dy = mouseY - this.startY;
        this.startX = mouseX;
        this.startY = mouseY;
        // change this.nearest line vertices by distance moved
        let line = this.nearest.line;
        line.x0 += dx;
        line.y0 += dy;
        line.x1 += dx;
        line.y1 += dy;
        // redraw
        this.draw();

        let ctx = this.canvasElement.getContext('2d');
        ctx.beginPath();
        ctx.rect(line.x0, line.y0, line.x1, line.y1);
        ctx.fillStyle = "red";
        ctx.fill();
    }

}

enter image description here

How to fill color when four line touch or connect?



from How can i fill color between 4 lines in canvas?

No comments:

Post a Comment