I have a problem with the curves in my path. I think it comes from the starting point x and starting point y. these have no curves. I had previously added an extra path and then tried to manipulate it together with startX and startY. However, that didn’t work and I had the same result. Maybe someone can give me a working hint. So it’s actually just about the two points that are “pointy”.
import QtQuick
import QtQuick.Controls
import QtQuick.Shapes
import QtQuick.Effects
import QtQuick.Layouts
import QtQuick.Timeline 1.0
import QtMultimedia
import QtCore
Item {
id: polarChart
width: 300
height: 300
layer.smooth: false
property real caloriesPercent: 0.9
property real carbsPercent: 0.64
property real proteinPercent: 0.6
property real fatPercent: 0.8
EllipseItem {
id: backgroundEllipse
anchors.fill: parent
strokeStyle: 0
gradient: RadialGradient {
centerX: backgroundEllipse.width; centerY: backgroundEllipse.height
centerRadius: backgroundEllipse.height;
focalX: centerX; focalY: centerY
GradientStop { position: 0; color: Constants.colors.light500 }
GradientStop { position: 1; color: Constants.colors.dark300 }
}
layer.enabled: true
layer.effect: MultiEffect {
autoPaddingEnabled: true
blurMax: 32
blur: 1
blurEnabled: true
}
}
EllipseItem {
anchors.fill: parent
anchors.margins: (ellipseChartLayer.width/12)
antialiasing: true
layer.mipmap: true
strokeStyle: 0
gradient: RadialGradient {
centerX: backgroundEllipse.width; centerY: backgroundEllipse.height
centerRadius: backgroundEllipse.height;
focalX: centerX; focalY: centerY
GradientStop { position: 0.5; color: Constants.colors.dark300 }
GradientStop { position: 1; color: Constants.colors.dark100 }
}
layer.enabled: true
layer.smooth: true
layer.effect: MultiEffect {
shadowOpacity: 0.3
shadowHorizontalOffset: -5
shadowVerticalOffset: -5
autoPaddingEnabled: true
shadowColor: Constants.colors.dark400
shadowBlur: 0.6
shadowScale: 1.02
shadowEnabled: true
}
}
Item {
id: innerItem
anchors.fill: parent
Repeater {
model: [{name:"Fat"},
{name: "Calories"},
{name: "Carbs"},
{name: "Protein"}, ]
Label {
color: Constants.colors.dark500
text: modelData.name
rotation: index * 90
anchors.fill: parent
anchors.margins: -24
horizontalAlignment: Text.AlignHCenter
}
}
Item {
id: ellipseChartLayer
width: 250
height: 250
anchors.centerIn: parent
property real cx: ellipseChartLayer.width / 2
property real cy: ellipseChartLayer.height / 2
property real a: ellipseChartLayer.width / 2
property real b: ellipseChartLayer.height / 2
function pointAtAngle(angle) {
var radiant = angle * Math.PI / 180;
var x = cx + a * Math.cos(radiant);
var y = cy + b * Math.sin(radiant);
return { x: x, y: y };
}
Repeater {
id: repeater
model: 4
EllipseItem {
anchors.fill: parent
antialiasing: true
anchors.margins: index * (ellipseChartLayer.width/8)
strokeWidth: 1
fillColor: "transparent"
strokeColor: Constants.colors.dark500
}
}
}
Shape {
id: polarChartControls
width: ellipseChartLayer.width
height: ellipseChartLayer.height
anchors.centerIn: ellipseChartLayer
ShapePath {
id: caloriesPath
strokeColor: Constants.colors.dark500
startX: ellipseChartLayer.cx; startY: ellipseChartLayer.cy
PathLine { x: ellipseChartLayer.pointAtAngle(0).x ; y: ellipseChartLayer.pointAtAngle(0).y }
}
ShapePath {
id: bottomRightPath
strokeColor: "transparent"
startX: ellipseChartLayer.cx; startY: ellipseChartLayer.cy
PathLine { x: ellipseChartLayer.pointAtAngle(45).x ; y: ellipseChartLayer.pointAtAngle(45).y }
}
ShapePath {
id: carbsPath
strokeColor: Constants.colors.dark500
startX: ellipseChartLayer.cx; startY: ellipseChartLayer.cy
PathLine { x: ellipseChartLayer.pointAtAngle(90).x; y: ellipseChartLayer.pointAtAngle(90).y }
}
ShapePath {
id: bottomLeftPath
strokeColor: "transparent"
startX: ellipseChartLayer.cx; startY: ellipseChartLayer.cy;
PathLine { x: ellipseChartLayer.pointAtAngle(135).x ; y: ellipseChartLayer.pointAtAngle(135).y }
}
ShapePath {
id: proteinPath
strokeColor: Constants.colors.dark500
startX: ellipseChartLayer.cx; startY: ellipseChartLayer.cy;
PathLine { x: ellipseChartLayer.pointAtAngle(180).x; y: ellipseChartLayer.pointAtAngle(180).y }
}
ShapePath {
id: topLeftPath
strokeColor: "transparent"
startX: ellipseChartLayer.cx; startY: ellipseChartLayer.cy;
PathLine { x: ellipseChartLayer.pointAtAngle(225).x ; y: ellipseChartLayer.pointAtAngle(225).y }
}
ShapePath {
id: fatPath
strokeColor: Constants.colors.dark500
startX: ellipseChartLayer.cx; startY: ellipseChartLayer.cy
PathLine { x: ellipseChartLayer.pointAtAngle(270).x ; y: ellipseChartLayer.pointAtAngle(270).y }
}
ShapePath {
id: topRightPath
strokeColor: "transparent"
startX: ellipseChartLayer.cx; startY: ellipseChartLayer.cy
PathLine { x: ellipseChartLayer.pointAtAngle(315).x ;y: ellipseChartLayer.pointAtAngle(315).y }
}
}
Shape {
id: polarItem
width: ellipseChartLayer.width
height: ellipseChartLayer.height
anchors.centerIn: ellipseChartLayer
layer.enabled: true
layer.effect: MultiEffect {
shadowEnabled: true
}
ShapePath {
id: xOpart
miterLimit: 12
simplify: true
strokeWidth: 4
capStyle: Qt.RoundCap
joinStyle: Qt.RoundJoin
strokeColor: Constants.colors.dark100
fillGradient: LinearGradient {
x1: 0; y1: 0
x2: polarItem.width; y2: polarItem.height
GradientStop { position: 0; color: Constants.colors.blue }
GradientStop { position: 1; color: Constants.colors.dark100 }
}
strokeStyle: ShapePath.SolidLine
Behavior on startX { NumberAnimation{ duration: 300 } }
Behavior on startY { NumberAnimation{ duration: 300 } }
PathCurve {
id: bottomRightLine
Behavior on x{ NumberAnimation{ duration: 300 } }
Behavior on y { NumberAnimation{ duration: 300 } }
Component.onCompleted: {
x = bottomRightPath.pointAtPercent(polarChart.caloriesPercent > polarChart.carbsPercent ?
polarChart.carbsPercent/2 : polarChart.caloriesPercent/2).x;
y = bottomRightPath.pointAtPercent(polarChart.caloriesPercent > polarChart.carbsPercent ?
polarChart.carbsPercent/2 : polarChart.caloriesPercent/2).y
}
}
PathCurve {
id: carbsLine
Behavior on x{ NumberAnimation{ duration: 300 } }
Behavior on y { NumberAnimation{ duration: 300 } }
Component.onCompleted: {
x = carbsPath.pointAtPercent(polarChart.carbsPercent).x;
y = carbsPath.pointAtPercent(polarChart.carbsPercent).y
}
}
PathCurve {
id: bottomLeftLine
Behavior on x{ NumberAnimation{ duration: 300 } }
Behavior on y { NumberAnimation{ duration: 300 } }
Component.onCompleted: {
x = bottomLeftPath.pointAtPercent(polarChart.carbsPercent > polarChart.proteinPercent ?
polarChart.proteinPercent/2 : polarChart.carbsPercent/2).x;
y = bottomLeftPath.pointAtPercent(polarChart.carbsPercent > polarChart.proteinPercent ?
polarChart.proteinPercent/2 : polarChart.carbsPercent/2).y
}
}
PathCurve {
id: proteinLine
Behavior on x{ NumberAnimation{ duration: 300 } }
Behavior on y { NumberAnimation{ duration: 300 } }
Component.onCompleted: {
x = proteinPath.pointAtPercent(polarChart.proteinPercent).x;
y = proteinPath.pointAtPercent(polarChart.proteinPercent).y
}
}
PathCurve {
id: topLeftLine
Behavior on x{ NumberAnimation{ duration: 300 } }
Behavior on y { NumberAnimation{ duration: 300 } }
Component.onCompleted: {
x = topLeftPath.pointAtPercent(polarChart.proteinPercent > polarChart.fatPercent ?
polarChart.fatPercent/2 : polarChart.proteinPercent/2).x;
y = topLeftPath.pointAtPercent(polarChart.proteinPercent > polarChart.fatPercent ?
polarChart.fatPercent/2 : polarChart.proteinPercent/2).y
}
}
PathCurve {
id: fatLine
Behavior on x{ NumberAnimation{ duration: 300 } }
Behavior on y { NumberAnimation{ duration: 300 } }
Component.onCompleted: {
x = fatPath.pointAtPercent(polarChart.fatPercent).x;
y = fatPath.pointAtPercent(polarChart.fatPercent).y
}
}
PathCurve {
id: topRightLine
Behavior on x{ NumberAnimation{ duration: 300 } }
Behavior on y { NumberAnimation{ duration: 300 } }
Component.onCompleted: {
x = topRightPath.pointAtPercent(polarChart.fatPercent > polarChart.caloriesPercent ?
polarChart.caloriesPercent/2 : polarChart.fatPercent/2).x;
y = topRightPath.pointAtPercent(polarChart.fatPercent > polarChart.caloriesPercent ?
polarChart.caloriesPercent/2 : polarChart.fatPercent/2).y
}
}
// startX: 20; startY: 20
// PathLine { x: carbsPath.pointAtPercent(0.5).x; y: carbsPath.pointAtPercent(0.5).y }
// PathLine { x: proteinPath.pointAtPercent(0.5).x; y: proteinPath.pointAtPercent(0.5).y }
// PathLine { x: fatPath.pointAtPercent(0.75).x; y: fatPath.pointAtPercent(0.75).y }
Component.onCompleted: {
startX = caloriesPath.pointAtPercent(polarChart.caloriesPercent).x;
startY = caloriesPath.pointAtPercent(polarChart.caloriesPercent).y;
}
}
}
}
Timeline {
id: timeline
animations: [
TimelineAnimation {
id: timelineAnimation
running: true
loops: Animation.Infinite
duration: 30000
to: 1600
from: 0
}
]
keyframeGroups: [
KeyframeGroup {
target: innerItem
property: "rotation"
Keyframe { frame: 0; value: 0 }
Keyframe { frame: 200; value: 90; easing.type: Easing.OutElastic }
Keyframe { frame: 400; value: 90 }
Keyframe { frame: 600; value: 180; easing.type: Easing.OutElastic }
Keyframe { frame: 800; value: 180 }
Keyframe { frame: 1000; value: 270; easing.type: Easing.OutElastic }
Keyframe { frame: 1200; value: 270 }
Keyframe { frame: 1400; value: 360; easing.type: Easing.OutElastic }
}
]
startFrame: 0
endFrame: 1600
enabled: true
}
}