I created the below image in html and JavaScript where the alphabets curve around the arc of the image. I am trying to convert the code I wrote and properly inject the functions inside of a QT project. However, my current implementation does not work due TypeError: Type errors. Can someone help with this?
Also if possible: I would like to rotate the alphabets to be vertical to the arc instead of horizontal.
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
}
}
CodePudding user response:
The reference to Image on line 35 is not going to work because it is a browser-specific JavaScript class which is not available in the QML JavaScript runtime. Even though it seems like the QML Image class you have commented out should be referencable in the runtime, no QML components are directly referencable in JavaScript as classes like this.
You will need to port your code to use Canvas::loadImage() as documented here:
https://doc.qt.io/qt-5/qml-qtquick-canvas.html#loadImage-method
Or you can uncomment your QML Image object and call Context2d::drawImage() with its id as the first argument as documented here:
https://doc.qt.io/qt-5/qml-qtquick-context2d.html#drawImage-method-2
Note, if you do that, the Image will appear twice in the window unless you set visible: false on the QML one.


