How to Blend overlapping SVG in QML - qt

I have two SVG files that I am animating, one is a fixed figure that is centered in the screen, while the other is a second shape coming from the bottom of the screen and ending up overlapping a bit on the first shape:
Image {
id: progressIconFix
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
source: "../../images/Progress2-01.svg"
}
Image {
id: progressIcon
y: screenHeight
anchors.horizontalCenter: parent.horizontalCenter
source: "../../images/Progress1-01.svg"
states: State {
name: "visible";
when: progressIcon.visible;
PropertyChanges {
target: progressIcon;
y: progressIconFix.height + 180;
}
}
transitions: Transition {
from: "";
to: "visible";
reversible: true;
ParallelAnimation {
NumberAnimation {
properties: "y";
duration: 1050;
easing.type: Easing.InOutQuad;
}
}
}
}
I would like to make it so that when the second shape overlaps with the fixed one, the overlapped area (and only the overlap) between the two gets blended with a "multiply" effect. However, if I use:
Blend {
anchors.fill: progressIconFix
source: progressIconFix
foregroundSource: progressIcon
mode: "multiply"
}
The moving shape gets blended since the beginning in its entirety, but I would really like this effect to happen only when it overlaps the fixed shapes and only on the intersection area of the two.
Something like this should be happening:

Related

Why my animations works in a strange way?

I have write a simple animation demo,but the animation work in a strange way.
The Code
import QtQuick 2.5
import QtQuick.Controls 2.12
ApplicationWindow {
visible: true
width: 480
height: 680
id: root
Rectangle {
id: rect
width: 200
height: 200
color: "blue"
anchors.centerIn: parent
states: State {
name: "A"
when: mouseArea.pressed
PropertyChanges {target: rect; color:"red"; }
PropertyChanges {target: rect; width: rect.width + 100}
PropertyChanges {target: rect; rotation: 720}
}
transitions: Transition {
ColorAnimation {duration: 1000}
NumberAnimation {duration: 1000}
RotationAnimation {duration: 1000}
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
}
}
Q1: When mouse press and hold, I want the rectange width increase 100 every time,but my code seems not work?
Q2: If the width assign a const value(eg 100), the NumberAnimation seems not work, the width change immediately?
Q3:The RotationAnimation not rotate 720, it rotate exceed 720?
Currently, I am not familiar with js&qml, Hope Good Man(Woman) can help me.
Q1: You shouldn't bind rect.width to itself. That causes a binding loop. Either use a constant value or come up with some way outside of rect to keep track of what size you want the rect to be.
Q2: You need to tell the NumberAnimation which property to animate on. In this case it's "width".
Q3: 720 degrees means twice all the way around. That's exactly what I'm seeing when I test it, so I think it's working correctly.
The code below works for me.
Rectangle {
id: rect
width: 200
height: 200
color: "blue"
anchors.centerIn: parent
states: State {
name: "A"
when: mouseArea.pressed
PropertyChanges {target: rect; color:"red"; }
PropertyChanges {target: rect; width: 300} // Fixed value
PropertyChanges {target: rect; rotation: 720}
}
transitions: Transition {
ColorAnimation {duration: 1000}
NumberAnimation {property: "width"; duration: 1000} // Specify property
RotationAnimation {duration: 1000}
}
}
In addition to the answer from JarMan, I think you want to define a onPressed handler in the MouseArea, where you assign a new value to the width of the rect (note the difference between "binding" and "assigning"):
MouseArea {
id: mouseArea
anchors.fill: parent
onPressed: rect.width += 100
}
To clarify why that PropertyChange on width didn't work: as long as State "A" is active (thus during the mouse press), the PropertyChange overwrites the binding in the original Rectangle code, and you are defining it as a binding, meaning during the "A" state, the width is bound to itself (the binding loop that JarMan writes about). When state "A" is not active anymore, it will return to width: 300 (which is basically also a binding, albeit being constant).
When you use the above onPressed handler, the width property will loose it's binding and become fixed to the value assigned to it. Note: you can make it bound again by using Qt.binding or temporarily by using another PropertyChanges from a State

PropertyAnimation vs. NumberAnimation

The QML code below animates two rectangles. One uses PropertyAnimation, while the other uses NumberAnimation. Both rectangles move similarly. I don't see anything different between the two animation types.
import QtQuick 2.0
import QtQuick.Window 2.0
Window {
visible: true
width: 640
height: 480
Rectangle {
id: r1
width: 100; height: 100
color: "red"
Behavior on x { PropertyAnimation {} }
}
Rectangle {
id: r2
y: 150
width: 100; height: 100
color: "blue"
Behavior on x { NumberAnimation {} }
}
// click anywhere to start animation
MouseArea { anchors.fill: parent; onClicked: r1.x = r2.x = 200 }
}
What is the difference between PropertyAnimation and NumberAnimation; and when should I use one over the other?
tl;dr.
NumberAnimation is derived from PropertyAnimation, and thus, it makes logical sense for them to exhibit similar behaviour.
NumberAnimation is a specialized PropertyAnimation that defines an animation to be applied when a numerical value changes.
(Source)
While NumberAnimation specifically animates numeric values (e.g. x, y, width, opacity), PropertyAnimation is generic and can animate non-numeric ones (e.g. color, size).
Lé longer answer:
1. PropertyAnimation can animate non-numeric types. NumberAnimation only animates numbers.
NumericAnimation can animate numeric properties such as x, y, width, height, opacity. But it can't animate color, size, or points.
Here's an example where the animation types differ in animating the color property. The first rectangle transitions from red to green while the second rectangle stays blue. In this case, PropertyAnimation should be used over NumberAnimation.
Rectangle {
id: r1
width: 100; height: 100
color: "red"
Behavior on color { PropertyAnimation {} } // works
}
Rectangle {
id: r2
y: 150
width: 100; height: 100
color: "blue"
Behavior on color { NumberAnimation {} } // fails
}
MouseArea { anchors.fill: parent; onClicked: r1.color = r2.color = "green" }
But then again, you can ColorAnimation instead...
2. PropertyAnimation is generic.
This is a build-off from #1. But this is another advantage on its own.
Since PropertyAnimation is more generic, it can be used if you decide to have a dynamic PropertyAnimation::property.
Here's an example where the animation property is user-provided:
Rectangle {
id: rect
width: 100; height: 100
color: "red"
PropertyAnimation { id: animation; target: rect }
}
MouseArea {
anchors.fill: parent
onClicked: {
animation.property = t1.text;
animation.to = t2.text;
animation.start();
}
}
Row {
width: parent.width; height: 50
anchors.bottom: parent.bottom
TextField { id: t1; width: parent.width/2; height: 50; placeholderText: "property" }
TextField { id: t2; width: parent.width/2; height: 50; placeholderText: "to" }
}
Using NumberAnimation also works, but restricts the viable properties to only numeric ones... users can't simulate supernovas or rainbows. :(
3. NumberAnimation is strict.
Let's compare the from and to properties.
NumberAnimation
from: real
to: real
PropertyAnimation
from: variant
to: variant
This makes NumberAnimation stricter. QML will prevent you from making silly mistakes:
NumberAnimation {
id: animation
to: "green" // Invalid property assignment: number expected
}
Use it when you're strictly limited animating numbers.
This also means that using NumberAnimation can improve readability and communication. It tells the people reading your code that you're only intending to animate numbers — not anchors, colours, unicorns or whatever.
4. NumberAnimation is more efficient at animating numbers.
– says Qt:
Specialized property animation types have more efficient implementations than the PropertyAnimation type.
(Source)
Here, the "specialized types" refers to NumberAnimation, along with other types such as AnchorAnimation and ColorAnimation.
I haven't tried profiling QML to benchmark the differences, but it seems like the rule of thumb for choosing animation types is:
If you're animating numbers, you should default to NumberAnimation.
PropertyAnimation should be a last resort (prefer the other types).

Turning Card with Text change -> Looking for QML Logic for Sequential Actions/Animations

I want to create some sort of Vocabulary Trainer.
I have a Card QML File what shoud represent some kind of a record card where you can see the Vocabulary. When you've answered, the card should turn around 180° and a new Word/Text should be visible on it.
So far I've created a Rectangle for the Card and a Transformation for the Rotation split up in two PropertyAnimations.
For the sake of simplicity I just want the animation to happen when I'm clicking on the Card. Then the Card turns from 0 to 90 degrees. Afterwards the text should be changed. And at last the Card should turn from -90 to 0 degrees. So I'm looking for a logic that allows me to execute an animation, changes a property (text) instantly and executing another animation as a sequence.
Here is my Code so far:
import QtQuick 2.2
import QtGraphicalEffects 1.0
Item {
Rectangle {
id: card
anchors.fill: parent
border.width: 1
border.color: "grey"
antialiasing: true
Text {
id: question
text: "test test test"
anchors.centerIn: card
}
transform: Rotation {
id: rotation
origin.x: (card.width / 2)
origin.y: (card.height / 2)
axis {
x: 0
y: 1
z: 0
}
angle: 0
}
MouseArea {
anchors.fill: card
onClicked: {
// Code for Turning Card arround
rotate_away.start()
question.text = "abcabcabc"
rotate_new.start()
}
}
PropertyAnimation {
id: rotate_away
target: rotation
properties: "angle"
from: 0
to: 90
duration: 1000
}
PropertyAnimation {
id: rotate_new
target: rotation
properties: "angle"
from: -90
to: 0
duration: 1000
}
}
}
So the problem is this part:
rotate_away.start()
question.text = "abcabcabc"
rotate_new.start()
The text changes but only the 2'nd animation will be executed.
I tried
while (rotate_away.running) {}
to wait for the 1st animation but then the application gets stuck.
I think the animations should be played sequently by using SequentialAnimation. Please revisit your code as follows:
MouseArea {
anchors.fill: card
onClicked: {
// Code for Turning Card around
// rotate_away.start()
// question.text = "abcabcabc"
// rotate_new.start()
fullRotate.start();
}
}
SequentialAnimation {
id: fullRotate
PropertyAnimation {
id: rotate_away
target: rotation
properties: "angle"
from: 0
to: 90
duration: 1000
}
PropertyAction {
target: question
property: "text"
value: "abcabcabc"
}
PropertyAnimation {
id: rotate_new
target: rotation
properties: "angle"
from: -90
to: 0
duration: 1000
}
}
Also, I recommend Flipable which is meant for flipping effects.

QT QML ListView - centralised highlight bar with enlarged text

I'm attempting to implement a 5 line centralised menu using ListView. The text in the highlighted position needs to be larger than the other menu items and should transition smoothly as the menu is scrolled. Ideally there should be 3 different text sizes - central biggest, items next to central slightly smaller and items on the outside even smaller, but just bigger text for the central item is ok.
When menu stops scrolling the centralised item needs to scroll horizontally if bigger than the screen width.
This is for an embedded device that has a rotary encoder for menu navigation. setIndex() is used to set the menu position.
The following code works ok when scrolling slowly but gets a bit confused when scrolling faster. Items outwith the central bar sometimes go big etc.
Seems like a problem that should have already been solved but I can't find an example anywhere.
Here is the code -
import QtQuick 1.1
// Menu
// 5 line menu, highlight bar centralised
Rectangle {
id: window
color: "#00000000"
property int numLines: 5
property alias menuIndex: listView.currentIndex
property int lineHeight: window.height/window.numLines
property alias model: listView.model
clip: true
function setIndex(iIndex) {
var displayedIndex = Math.round((listView.contentY/window.lineHeight + Math.floor(numLines/2)));
//console.log("MENU2: " + displayedIndex + " " + iIndex + " " + Math.abs(displayedIndex - iIndex));
// If we're too far behind current index jump straight to it rather than leaving it to smooth scroll
if (Math.abs(displayedIndex - iIndex) > 15)
listView.positionViewAtIndex(iIndex, ListView.Center);
listView.currentIndex = iIndex
}
function setItemSelected(bSelected) {
scrollingText.setItemSelected(bSelected);
}
// Define a delegate component. A component will be
// instantiated for each visible item in the list.
Component {
id: menuItemDelegate
Item {
id:wrapper
height: window.height/window.numLines
width: window.width
Text {id: wrapperText; text: menuText; width: window.width; height: window.height/window.numLines; font.pixelSize: (wrapper.height * 3)/4; color: "white"; horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignVCenter}
states: [
State {
name: "Current"
when: wrapper.ListView.isCurrentItem
PropertyChanges { target: wrapper; scale: 1.0 }
PropertyChanges { target: scrollingText; currentText: menuText }
PropertyChanges { target: scrollingText; scrollStart: true }
},
State {
name: "NotCurrent"
when: wrapper.ListView.isCurrentItem == 0
PropertyChanges { target: wrapper; scale: 0.7 }
}
]
transitions: Transition {
ParallelAnimation
{
NumberAnimation { properties: "scale"; duration: 100 }
}
}
}
}
// Highlight bar
Image {id: highlightBar; y: 2 * window.lineHeight; height: lineHeight; width:window.width; source: "Menu_HighlightBar.png"; scale: 1; opacity:1}
// Scrolling text that pops up on top of highlight bar area
Menu2ScrollingText {id: scrollingText; x:0; z:1; y: 2 * window.lineHeight; height: lineHeight; width: window.width}
ListView {
id: listView
anchors.fill: window
//model: cppMenuModel
delegate: menuItemDelegate
highlight: Rectangle { color: "lightsteelblue"; opacity: 0 } // not visible
highlightFollowsCurrentItem: true
preferredHighlightBegin: highlightBar.y
preferredHighlightEnd: preferredHighlightBegin + window.lineHeight
highlightRangeMode: ListView.StrictlyEnforceRange
currentIndex: 0
}
}

QML zoom from a clicked rectangle to another UI element

I have 9:9 matrix of Rectangle elements on the main QML form with Repeater. What I want to implement is if user clicks on one of rectangles, it zooms to TextEdit widget which on Esc press zooms back.
Is it possible with QML?
If yes, how am I supposed to turn Rectangle to TextEdit and zoom this TextEdit to fill the parent?
Just starting to work with QML and can't quite get an answer from http://doc.qt.nokia.com/4.7-snapshot/qdeclarativeanimation.html yet.
Thank you.
1) Sure thing! This is more or less what QML is made for.
2) This is an example of how you can do what you want (not the only way to do it):
Rectangle {
id: parentRect
width: 500; height: 500
// Every item in the grid should look like this
Rectangle {
id: singleItem
color: "red"
state: "closed"
// Hidden text input, shown when user clicks
TextInput {
id: textInput
anchors.fill: parent
text: "Input here"
cursorVisible: true
}
// MouseArea that will catch the user click
MouseArea {
anchors.fill: parent
onClicked: singleItem.state = "open"
}
// Item states
states: [
State {
name: "closed"
PropertyChanges {target: singleItem; width: 25; height: 25}
PropertyChanges {target: textInput; opacity: 0}
},
State {
name: "open"
PropertyChanges {target: singleItem; width: parentRect.width; height: parentRect.height}
PropertyChanges {target: textInput; opacity: 1; focus: true}
}
]
// Transitions between states
transitions: Transition {
ParallelAnimation {
NumberAnimation {
target: singleItem
properties: "width,height"
duration: 1000
}
NumberAnimation {
target: textInput
property: "opacity"
duration: 1000
}
}
}
}
}
Even I'm new to qt-quick. I don't think it is possible to zoom unless we write our code to do such. I'm not sure though. :-)
This effect is good and it will b nice to see in coming versions. Try to give a feature request to the community <3

Resources