Multiple paths in QML Canvas Context2D

75 Views Asked by At

Is there any way to use multiple paths in the same canvas context like in HTML5 canvas? there's no Path2D object in qt/qml.

I need to draw a polygon from a point list and each vertex should have an ellipse, when trying to use the same path it gets messed up like this:

messed up polygon

I know i can do it with 2 for loops but the canvas is kinda slow already and with a different path each it would be even slower (point list can have hundreds of points), is there any other way of doing this without iterating twice through the point list?

Current code:

import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import QtQuick.Window

ApplicationWindow {
    id: main
    title: qsTr("Hello World")
    width: 800
    height: 800
    visible: true

    Canvas {
        id: poligono
        width: parent.width
        height: parent.height
        onPaint: {
            var points = backend.points();
            var limits = backend.limits();
            var ctx = getContext("2d");
            
            // ctx.lineWidth = 1;
            ctx.transform(1, 0, 0, -1, limits[0]+8, limits[1]+8);

            ctx.beginPath();
            for (let i = 0; i < points.length; i++) {
                if (i == 0) {
                    ctx.moveTo(points[i][0], points[i][1]);
                } else {
                    ctx.lineTo(points[i][0], points[i][1]);
                }
                
                ctx.ellipse(points[i][0], points[i][1], 5, 5);
            }

            ctx.closePath()
            ctx.stroke()
        }
    }
}
1

There are 1 best solutions below

1
folibis On BEST ANSWER

You can use that in a single loop without problem, it adds ellipses to the path as a closed subpath, for example:

Canvas {
        id: mycanvas
        anchors.fill: parent
        property int count: 20
        property list<point> points: {
            var arr = [];
            for(var i = 0;i < mycanvas.count;i++)
            {
                var x = Math.floor(Math.random() * mycanvas.width);
                var y = Math.floor(Math.random() * mycanvas.height);
                arr.push(Qt.point(x,y));
            }

            return arr;
        }

        onPaint: {
            var ctx = getContext("2d");
            ctx.lineWidth = 1;
            ctx.lineJoin = "round";
            ctx.strokeStyle = Qt.rgba(Math.random(), Math.random(), Math.random(), 1.0);
            ctx.fillStyle = Qt.rgba(Math.random(), Math.random(), Math.random(), 1.0);
            ctx.beginPath();
            ctx.moveTo(mycanvas.points[0].x, mycanvas.points[0].y);
            for(var i = 1;i < mycanvas.count;i++)
            {
                ctx.lineTo(mycanvas.points[i].x, mycanvas.points[i].y);
                ctx.ellipse(mycanvas.points[i].x - 10, mycanvas.points[i].y - 10, 20, 20);
                ctx.moveTo(mycanvas.points[i].x, mycanvas.points[i].y);
            }
            ctx.stroke();
            ctx.fill();
        }
    }