在 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
。
我在 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
。