在 QT 项目中正确注入 JavaScript 函数

Properly inject JavaScript functions inside of the QT project

我在 html 和 JavaScript 中创建了下图,其中字母围绕图像的弧线弯曲。我正在尝试转换我编写的代码并正确地将函数注入到 QT 项目中。但是,由于 TypeError: Type 错误,我当前的实现不起作用。有人可以帮忙吗?

此外,如果可能的话:我想将字母旋转为垂直于圆弧而不是水平。

import QtQuick 2.15
import QtQuick.Window 2.15

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Canvas {
        anchors.fill: parent

        Image {
            id: abcBar
            source: "alphabetBar.png"
            visible: false
        }


        onPaint: {
            var ctx = getContext('2d');
            ctx.save();
            ctx.canvas.width = 160;
            ctx.canvas.height = 432;
            ctx.font = "18px Roboto";
            ctx.textAlign = "center";
            ctx.fillStyle = "#000000"

            const centerX = 10;
            const centerY = ctx.canvas.height / 2;
            const angle = Math.PI;
            const radius = 130
            ctx.fillStyle = "#000000"
            ctx.restore();


            ctx.save();
            ctx.drawImage(abcBar, 0, 0, ctx.canvas.width, ctx.canvas.height);
            console.log('loaded')
            ctx.restore();

            const args = {
                ctx,
                text: "A • D • G • J • M • P • S • V • Z",
                offset: 0,
                G1: {
                    x: 20,
                    y: 80,
                },
                G2: {
                    x: 190,
                    y: 230,
                },
                G3: {
                    x: 0,
                    y: 372
                },
            }
            textOnCurve(args);
        }
    }


    function textOnCurve({ ctx, text, offset, G1, G2, G3, G4}){

        const x1 = G1.x;
        const y1 = G1.y;
        const x2 = G2.x;
        const y2 = G2.y;
        const x3 = G3.x;
        const y3 = G3.y;
        const x4 = G3.x;
        const y4 = G3.y;

        ctx.save();
        ctx.textAlign = "center";

        var widths = [];
        for (var i = 0; i < text.length; i++)
        {
            widths[widths.length] = ctx.measureText(text[i]).width;
        }

        ctx.beginPath();
        var ch = curveHelper(x1, y1, x2, y2, x3, y3, x4, y4);
        ctx.stroke();

        var pos = offset;
        var cpos = 0;
        for (var j = 0; j < text.length; j++)
        {
            pos += widths[j] / 2;
            cpos = ch.forward(pos);
            ch.tangent(cpos);
            ctx.setTransform(ch.vect.x, ch.vect.y, -ch.vect.y, ch.vect.x, ch.vec.x, ch.vec.y);
            ctx.fillText(text[j], 0, 0);
            pos += widths[j] / 2;
        }
        ctx.restore();
    }

    function curveHelper(x1, y1, x2, y2, x3, y3, x4, y4)
    {
        var tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4;
        var a, b, c, u;
        var vec, currentPos, vec1, vect, quad, currentDist;
        vec = { x: 0, y: 0 } ;
        vec1 = { x: 0, y: 0 } ;
        vect = { x: 0, y: 0 } ;
        quad = false;
        currentPos = 0;
        currentDist = 0;
        if (x4 === undefined || x4 === null)
        {
            quad = true;
            x4 = x3;
            y4 = y3;
        }
        var estLen = Math.sqrt((x4 - x1)* (x4 - x1)+ (y4 - y1)* (y4 - y1));
        var onePix = 1 / estLen;

        function posAtC(c)
        {
            tx1 = x1; ty1 = y1;
            tx2 = x2; ty2 = y2;
            tx3 = x3; ty3 = y3;
            tx1 += (tx2 - tx1)* c;
            ty1 += (ty2 - ty1)* c;
            tx2 += (tx3 - tx2)* c;
            ty2 += (ty3 - ty2)* c;
            tx3 += (x4 - tx3)* c;
            ty3 += (y4 - ty3)* c;
            tx1 += (tx2 - tx1)* c;
            ty1 += (ty2 - ty1)* c;
            tx2 += (tx3 - tx2)* c;
            ty2 += (ty3 - ty2)* c;
            vec.x = tx1 + (tx2 - tx1)* c;
            vec.y = ty1 + (ty2 - ty1)* c;
            return vec;
        }

        function posAtQ(c)
        {
            tx1 = x1; ty1 = y1;
            tx2 = x2; ty2 = y2;
            tx1 += (tx2 - tx1)* c;
            ty1 += (ty2 - ty1)* c;
            tx2 += (x3 - tx2)* c;
            ty2 += (y3 - ty2)* c;
            vec.x = tx1 + (tx2 - tx1)* c;
            vec.y = ty1 + (ty2 - ty1)* c;
            return vec;
        }

        function forward(dist)
        {
            var step;
            helper.posAt(currentPos);
            while (currentDist < dist)
            {
                vec1.x = vec.x;
                vec1.y = vec.y;
                currentPos += onePix;
                helper.posAt(currentPos);
                currentDist += step = Math.sqrt((vec.x - vec1.x)* (vec.x - vec1.x)+ (vec.y - vec1.y)* (vec.y - vec1.y));
            }
                currentPos -= ((currentDist - dist)/ step)* onePix
                currentDist -= step;
                helper.posAt(currentPos);
                currentDist += Math.sqrt((vec.x - vec1.x)* (vec.x - vec1.x)+ (vec.y - vec1.y)* (vec.y - vec1.y));
                return currentPos;
        }

        function tangentQ(pos)
        {
            a = (1 - pos)* 2;
            b = pos * 2;
            vect.x = a * (x2 - x1)+ b * (x3 - x2);
            vect.y = a * (y2 - y1)+ b * (y3 - y2);
            u = Math.sqrt(vect.x * vect.x + vect.y * vect.y);
            vect.x /= u;
            vect.y /= u;
        }

        function tangentC(pos)
        {
            a = (1 - pos)
            b = 6 * a * pos;
            a *= 3 * a;
            c = 3 * pos * pos;
            vect.x = -x1 * a + x2 * (a - b)+ x3 * (b - c)+ x4 * c;
            vect.y = -y1 * a + y2 * (a - b)+ y3 * (b - c)+ y4 * c;
            u = Math.sqrt(vect.x * vect.x + vect.y * vect.y);
            vect.x /= u;
            vect.y /= u;
        }

        var helper = {
            vec: vec,
            vect: vect,
            forward: forward,
        }

        if (quad)
        {
            helper.posAt = posAtQ;
            helper.tangent = tangentQ;
        } else
        {
            helper.posAt = posAtC;
            helper.tangent = tangentC;
        }
            return helper
    }
}

第 35 行对 Image 的引用不起作用,因为它是 browser-specific JavaScript class,在 QML [=31] 中不可用=] 运行时。尽管看起来您注释掉的 QML 图像 class 应该在运行时可引用,但在 JavaScript 中没有任何 QML 组件像这样的 class 可以直接引用。

您需要移植代码才能使用 Canvas::loadImage(),如此处所述:

https://doc.qt.io/qt-5/qml-qtquick-canvas.html#loadImage-method

或者您可以取消注释您的 QML Image 对象并调用 Context2d::drawImage() 并将其 id 作为第一个参数,如下所述:

https://doc.qt.io/qt-5/qml-qtquick-context2d.html#drawImage-method-2

请注意,如果您这样做,图像将在 window 中出现两次,除非您在 QML 上设置 visible: false