Proper shadow drop on rotation

Multi tool use
Multi tool use


Proper shadow drop on rotation



I am trying to create a rotatable triangle that will always cast a shadow on its base. So far I was able to create the code for making and rotating the triangle but the shadow part is problematic. Here is my minimal code example:


import QtQuick 2.9
import QtQuick.Window 2.2
import QtGraphicalEffects 1.0

Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")

Rectangle
{
id: rectMain
anchors.centerIn: parent
width: parent.width
height: parent.height
color: "white"

Canvas
{
anchors.fill: parent

// set properties with default values
property real hFactor: 1 // height factor
property real trbase: 200
property color strokeColor: "black"
property color fillColor: "yellow"
property int lineWidth: 1
property real alpha: 1
property real rotAngle: 0
property real parentWidth: parent.width; // try
property real parentHeight: parent.height;

onStrokeColorChanged: requestPaint();
onFillColorChanged: requestPaint();
onLineWidthChanged: requestPaint();

onPaint:
{
hFactor = Math.abs(hFactor)

var ctx = getContext("2d") // get context to draw with
ctx.clearRect(0, 0, width, height); // remove what is painted so far
ctx.lineWidth = lineWidth
ctx.strokeStyle = strokeColor
ctx.fillStyle = fillColor
ctx.globalAlpha = alpha

ctx.save();
ctx.beginPath();
ctx.translate(parentWidth / 2, parentHeight / 2);
ctx.rotate((Math.PI / 180) * rotAngle);
ctx.moveTo(0, 0);

// drawing part, first calculate height using Pythagoras equation
var trheight = Math.sqrt(Math.pow(trbase, 2) - Math.pow(trbase / 2, 2));
trheight = trheight * hFactor;
var hfBase = trbase * hFactor;
ctx.lineTo(hfBase / -2, trheight); // left arm
ctx.lineTo(hfBase / 2, trheight); // right arm

ctx.closePath(); // base drawn automatically
ctx.fill();
ctx.stroke();
ctx.restore();
}

DropShadow
{
anchors.fill: parent
horizontalOffset: 0
verticalOffset: 3
radius: 3
samples: 7
color: "#80000000"
source: parent
}
}
}
}



I am facing the following problems:



The parser gives me some errors about ShaderEffectSource, that recursive property has to be set, but I dont know whos property is that.


ShaderEffectSource


recursive


Starting M:bitbucketqtworkspacebuild-mwe-Desktop_Qt_5_11_0_MinGW_32bit-Debugdebugmwe.exe...
QML debugging is enabled. Only use this in a safe environment.
ShaderEffectSource: 'recursive' must be set to true when rendering recursively.
ShaderEffectSource: 'recursive' must be set to true when rendering recursively.
ShaderEffectSource: 'recursive' must be set to true when rendering recursively.
ShaderEffectSource: 'recursive' must be set to true when rendering recursively.
QObject::disconnect: No such signal QObject::screenChanged(QScreen*) in itemsqquickscreen.cpp:476
M:/bitbucket/qtworkspace/build-mwe-Desktop_Qt_5_11_0_MinGW_32bit-Debug/debug/mwe.exe exited with code 0



Somewhere in the web I have found a bug report that DropShadow property source cannot accept parent but since Canvas cannot be assigned with id, I am not sure how to do it. Other than this, the shadow renders correctly for rotAngle at 0 degrees:


source


parent


id


rotAngle



enter image description here



It doesnt rotate correctly after adding some angle, for example 45 degrees:



enter image description here



It seems to me that the shadow is not being rotated together with the polygon. Can this be adjusted? The last thing is: How to hide shadow behind the polygon? At the moment its interfering with it.



I am not sure either the parser error is connected or not, thats why I have added it together here. I would appreciate all help regarding this case.




1 Answer
1



since Canvas cannot be assigned with id



Why Canvas can't be assigned with id?


Canvas


id



The following code won't have that warning.


Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")

Rectangle
{
id: rectMain
anchors.centerIn: parent
width: parent.width
height: parent.height
color: "white"

Canvas
{
id: canvas
anchors.fill: parent

// set properties with default values
property real hFactor: 1 // height factor
property real trbase: 200
property color strokeColor: "black"
property color fillColor: "yellow"
property int lineWidth: 1
property real alpha: 1
property real rotAngle: 0
property real parentWidth: parent.width; // try
property real parentHeight: parent.height;

onStrokeColorChanged: requestPaint();
onFillColorChanged: requestPaint();
onLineWidthChanged: requestPaint();

onPaint:
{
hFactor = Math.abs(hFactor)

var ctx = getContext("2d") // get context to draw with
ctx.clearRect(0, 0, width, height); // remove what is painted so far
ctx.lineWidth = lineWidth
ctx.strokeStyle = strokeColor
ctx.fillStyle = fillColor
ctx.globalAlpha = alpha

ctx.save();
ctx.beginPath();
ctx.translate(parentWidth / 2, parentHeight / 2);
ctx.rotate((Math.PI / 180) * rotAngle);
ctx.moveTo(0, 0);

// drawing part, first calculate height using Pythagoras equation
var trheight = Math.sqrt(Math.pow(trbase, 2) - Math.pow(trbase / 2, 2));
trheight = trheight * hFactor;
var hfBase = trbase * hFactor;
ctx.lineTo(hfBase / -2, trheight); // left arm
ctx.lineTo(hfBase / 2, trheight); // right arm

ctx.closePath(); // base drawn automatically
ctx.fill();
ctx.stroke();
ctx.restore();
}
}

DropShadow
{
anchors.fill: canvas
horizontalOffset: 0
verticalOffset: 3
radius: 3
samples: 7
color: "#80000000"
source: canvas
}
}
}



About the warning:



I believe that should not consider as a BUG. DropShadow is an Item, so if you nest with its parent, it will do like render a shadow on the shadow.


DropShadow


Item



Why didn't the shadow rotated?



Because you are rotating the contents of Canvas.
Even rotate the polygon, these properties won't change. Always drop the shadow vertically.


Canvas


horizontalOffset: 0
verticalOffset: 3



Rotate both:



enter image description here


Item {
anchors.fill: parent
rotation: 30
Canvas
{
id: canvas
anchors.fill: parent

// set properties with default values
property real hFactor: 1 // height factor
property real trbase: 200
property color strokeColor: "black"
property color fillColor: "yellow"
property int lineWidth: 1
property real alpha: 1
property real parentWidth: parent.width; // try
property real parentHeight: parent.height;

onStrokeColorChanged: requestPaint();
onFillColorChanged: requestPaint();
onLineWidthChanged: requestPaint();

onPaint:
{
hFactor = Math.abs(hFactor)

var ctx = getContext("2d") // get context to draw with
ctx.clearRect(0, 0, width, height); // remove what is painted so far
ctx.lineWidth = lineWidth
ctx.strokeStyle = strokeColor
ctx.fillStyle = fillColor
ctx.globalAlpha = alpha

ctx.save();
ctx.beginPath();
ctx.translate(parentWidth / 2, parentHeight / 2);
ctx.moveTo(0, 0);

// drawing part, first calculate height using Pythagoras equation
var trheight = Math.sqrt(Math.pow(trbase, 2) - Math.pow(trbase / 2, 2));
trheight = trheight * hFactor;
var hfBase = trbase * hFactor;
ctx.lineTo(hfBase / -2, trheight); // left arm
ctx.lineTo(hfBase / 2, trheight); // right arm

ctx.closePath(); // base drawn automatically
ctx.fill();
ctx.stroke();
ctx.restore();
}
}

DropShadow
{
anchors.fill: canvas
horizontalOffset: 0
verticalOffset: 3
radius: 3
samples: 7
color: "#80000000"
source: canvas
}
}





Perfect answer, thank you. Only 1 note: Since the parent item has the property rotation: 30 set, the line ctx.rotate((Math.PI / 180) * rotAngle); inside Canvas has to be removed, as this creates double rotation.
– Bremen
Jul 3 at 5:57


rotation: 30


ctx.rotate((Math.PI / 180) * rotAngle);


Canvas





@Bremen Thanks for helping improve the answer, I removed the unused rotate part.
– Jiu
Jul 3 at 6:05






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

V3YqcpjP8F,Gh 9iRixODm3
kQuNNUvxBMIYFY789hqdDNYih4giFmOV 6JSp,hgqJ 9dTI6dko7rTWU15oEpTKS2

Popular posts from this blog

PHP contact form sending but not receiving emails

Do graphics cards have individual ID by which single devices can be distinguished?

Create weekly swift ios local notifications