I have written some Javascript code and tested it with the HTML5 Canvas and Qt's QML 2D Canvas. To my surprise they behave quite different and I don't understand why. The HTML5 code makes the rectangle rotate in a spiral like motion, while the QML code make it rotate and move in the x-direction.
HTML5/Javascipt code:
<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" width="1000" height="500" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var xOffset = 50
var yOffset = 50
var xLength = 100
var yLength = 100
var xCenter = xOffset + xLength / 2
var yCenter = yOffset + yLength / 2
var angle = 0
function rotateSquare(xCenter, xCenter, width, height, angleIncrement)
{
ctx.save()
ctx.translate(xCenter, yCenter)
ctx.rotate(angle * Math.PI / 180)
ctx.translate(-xCenter, -yCenter)
ctx.clearRect(xOffset, yOffset, width, height)
var newAngle
newAngle = angle + angleIncrement
newAngle %= 360
var increment = deltaAngle(newAngle, angle)
ctx.translate(xCenter, yCenter)
ctx.rotate(increment * Math.PI / 180)
ctx.translate(-xCenter, -yCenter)
ctx.fillRect(xOffset++, yOffset, width, height)
angle = newAngle
ctx.restore()
}
function deltaAngle(current, previous)
{
if (current >= previous)
{
return current - previous
}
else
{
return (360 + current) - previous
}
}
setInterval( "rotateSquare(xCenter, yCenter, xLength, yLength, 1)", 20 );
</script>
</body>
</html>
QML code:
import QtQuick 2.5
import QtQuick.Window 2.2
Window {
id: root
visible: true
minimumHeight: 600
minimumWidth: 800
property int xOffset: 50
property int yOffset: 50
property int xLength: 100
property int yLength: 100
property var ctx
property int xCenter: xOffset + xLength / 2
property int yCenter: yOffset + yLength / 2
property int angle: 0 //Degrees
Timer {
interval: 20;
repeat: true;
running: true;
onTriggered: {
graphCanvas.requestPaint()
}
}
Canvas {
id: graphCanvas
anchors.fill: parent
renderTarget: Canvas.Image
renderStrategy: Canvas.Cooperative
onPaint: {
ctx.fillStyle = "steelblue"
rotateSquare(xCenter, yCenter, xLength, yLength, 1)
}
function rotateSquare(xCenter, yCenter, width, height, angleIncrement)
{
ctx.save()
ctx.translate(xCenter, yCenter)
ctx.rotate(angle * Math.PI / 180)
ctx.translate(-xCenter, -yCenter)
ctx.clearRect(xOffset, yOffset, width, height)
var newAngle
newAngle = angle + angleIncrement
newAngle %= 360
var increment = deltaAngle(newAngle, angle)
ctx.translate(xCenter, yCenter)
ctx.rotate(increment * Math.PI / 180)
ctx.translate(-xCenter, -yCenter)
ctx.fillRect(xOffset++, yOffset, width, height)
angle = newAngle
ctx.restore()
}
function deltaAngle(current, previous)
{
if (current >= previous)
{
return current - previous
}
else
{
return (360 + current) - previous
}
}
Component.onCompleted: ctx = getContext("2d")
}
}
To get same effect as in HTML, modify your component initialization to be:
Component.onCompleted: {
ctx = getContext("2d")
xCenter = xOffset + xLength / 2
yCenter = yOffset + yLength / 2
}
In QML, when you say:
property int xCenter: xOffset + xLength / 2
you create a property binding - whenever xOffset or xLength changes, xCenter changes as well, and you do modify xOffset in your rendering code, so it results in effect different from your JavaScript - where xCenter is computed once and never changes.
The code I've give programmatically assigns a value to xCenter property, and that clears any bindings it might have, so it no longer changes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With