I have a Qml Canvas Item where in, the height of canvas item keeps varying based on the input dynamically. Below is my code
Item {
id: barGraph
property int highestRange: 200
property int rangeVal: (RangeModel.rangeValue === "---") ? highestRange : RangeModel.rangeValue
property int totalHeight: 450
property int canvasHeight: (rangeVal * totalHeight) / highestRange
height: 700
width: 500
x: 120
y: 145
Canvas {
id: mycanvas
height: canvasHeight
width: 16
onPaint: {
var context = getContext("2d");
var startX = mycanvas.x;
var startY = mycanvas.y;
context.lineWidth = 0.5;
context.strokeStyle = "white";
context.beginPath();
context.moveTo(startX, startY);
context.lineTo(startX,(mycanvas.height - 10));
context.lineTo(mycanvas.width, mycanvas.height);
context.lineTo(mycanvas.width, startY + 10);
context.lineTo(mycanvas.width / 2, startY);
context.closePath(); // base drawn automatically
context.fill();
context.stroke();
}
}}
The output of this code look like this :
The problem with this code is, whenever the height of the canvas changes dynamically it actually resizes from the below position as shown in the image
I actually need this to be resized from the Y top position and keeping the below position unmovable which I am unable to achieve through this code.
Any support is much appreciated here.
I am guessing your requirement is to use the Canvas
object to build an isometric bar chart application?
I have refactored a BarGraph.qml
and replaced Canvas
with Shape
, ShapePath
, and PathLine
.
I removed the unnecessary Item
parent and made Shape
the parent and made everything size accordingly.
There is a mistake in your code. You set startX
and startY
to be relative to canvas.x
and canvas.y
. This is problematic, since if canvas.x
and canvas.y
is non-zero your usage of startX
and startY
later will only move the components further.
Instead, all coordinates within your shape must tree the top-left corner of your canvas as (0, 0) regardless of where it is.
To make things position on the bottom, it is based on:
y: parent.height - height
parent.height
refers to the height of the page and height
refers to the height of the BarGraph
. By assigning this value to y
it will make the BarGraph
appear anchored to the bottom instead of the top of the page. Additional math is added later to create the isometric look.
To mock some data up, I use an array of numbers which I feed into the Repeater. This will allow me to create multiple instances of BarGraph
and use the numbers via modelData
.
As added bonus, I added a fill color to the BarGraph
and made the fill color gradually change from "blue" to "white".
import QtQuick
import QtQuick.Controls
Page {
background: Rectangle { color: "black" }
Repeater {
model: [ 100, 150, 200, 250, 300, 100, 150, 200, 250, 300 ]
BarGraph {
x: index * 30 + 100
y: parent.height - height - 200 + index * 15
fillColor: Qt.lighter(Qt.color("blue"), 1.0 + (index % 10) / 10.0)
height: modelData
}
}
BarXYAxis {
}
}
// BarGraph.qml
import QtQuick
import QtQuick.Shapes
Shape {
id: shape
width: 20
height: 250
property alias strokeColor: shapePath.strokeColor
property alias strokeWidth: shapePath.strokeWidth
property alias fillColor: shapePath.fillColor
ShapePath {
id: shapePath
startX: 0; startY: 0
strokeColor: "white"
strokeWidth: 1.0
fillColor: "blue"
PathLine { x: 0; y: shape.height - 10 }
PathLine { x: shape.width; y: shape.height }
PathLine { x: shape.width; y: 10 }
PathLine { x: shape.width / 2; y: 0 }
PathLine { x: 0; y: 0 }
}
}
// BarXYAxis.qml
import QtQuick
import QtQuick.Shapes
Item {
id: axis
anchors.fill: parent
Shape {
anchors.fill: parent
visible: parent.height - 200 > 30
ShapePath {
startX: 80; startY: 30
strokeColor: "white"
strokeWidth: 1.0
fillColor: "transparent"
PathLine { x: 80; y: parent.height - 200 }
}
}
Shape {
anchors.fill: parent
ShapePath {
startX: 80; startY: parent.height - 200
strokeColor: "white"
strokeWidth: 1.0
fillColor: "transparent"
PathLine { x: 410; y: parent.height - 35 }
}
}
Repeater {
model: Math.floor((axis.height - 230) / 20)
Shape {
x: 70
y: axis.height - 222 - index * 20
ShapePath {
startX: 0; startY: 0
strokeColor: "white"
strokeWidth: 1.0
fillColor: "transparent"
PathLine { x: 4; y: 2 }
}
}
}
}
You can Try it Online!