Qt Quick - Как лучше всего анимировать переход изображения при изменении состояния компонента? - PullRequest
2 голосов
/ 09 января 2020

С помощью Qt Quick я создал пользовательскую кнопку, которая выглядит следующим образом:

enter image description here

Эта кнопка также содержит несколько состояний (по умолчанию, зависание, нажатие ), а переход между состояниями анимирован. Я нашел способ легко анимировать каждое свойство с помощью движка Qt Quick, за исключением изображения. Действительно, я хочу анимировать переход изображения, выполняя перекрестное затухание между состояниями.

Однако я не смог найти такой аниматор для изображений. Единственный способ, который я нашел, - это добавить к моей кнопке 3 изображения, по одному для каждого состояния, и анимировать их соответствующую непрозрачность.

Ниже приведен код для моих кнопок:

Button
{
    property bool hoveredBtn: false
    property bool pressedBtn: false

    id: btAnimStateDemo
    height: 40
    anchors.right: parent.right
    anchors.rightMargin: 5
    anchors.left: parent.left
    anchors.leftMargin: 5
    anchors.top: parent.top
    anchors.topMargin: 290
    state: "DEFAULT"

    // the button background
    background: Rectangle
    {
        id: btAnimStateDemoBg
        anchors.fill: parent
    }

    // the button text
    Text
    {
        id: btAnimStateDemoText
        text: qsTr("A button showing animated states (default, hovered, pressed)")
        renderType: Text.NativeRendering
        font.bold: true
        horizontalAlignment: Text.AlignHCenter
        verticalAlignment: Text.AlignVCenter
        anchors.fill: parent
    }

    Image
    {
        id: btAnimStateDemoDefaultImage
        width: 30
        height: 30
        anchors.left: parent.left
        anchors.leftMargin: 5
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 5
        anchors.top: parent.top
        anchors.topMargin: 5
        opacity: 1.0
        source: "Resources/Palette.svg"
    }

    Image
    {
        id: btAnimStateDemoHoverImage
        width: 30
        height: 30
        anchors.left: parent.left
        anchors.leftMargin: 5
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 5
        anchors.top: parent.top
        anchors.topMargin: 5
        opacity: 0.0
        source: "Resources/Smile.svg"
    }

    Image
    {
        id: btAnimStateDemoPressedImage
        width: 30
        height: 30
        anchors.left: parent.left
        anchors.leftMargin: 5
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 5
        anchors.top: parent.top
        anchors.topMargin: 5
        opacity: 0.0
        source: "Resources/Woman.svg"
    }

    // the component state array
    states:
    [
        State
        {
            name: "DEFAULT"
            PropertyChanges { target: btAnimStateDemoBg; color: "green"}
            PropertyChanges { target: btAnimStateDemoBg; radius: 4}
            PropertyChanges { target: btAnimStateDemoDefaultImage; opacity: 1.0}
            PropertyChanges { target: btAnimStateDemoHoverImage; opacity: 0.0}
            PropertyChanges { target: btAnimStateDemoPressedImage; opacity: 0.0}
        },
        State
        {
            name: "HOVERED"
            PropertyChanges { target: btAnimStateDemoBg; color: "red"}
            PropertyChanges { target: btAnimStateDemoBg; radius: 10}
            PropertyChanges { target: btAnimStateDemoDefaultImage; opacity: 0.0}
            PropertyChanges { target: btAnimStateDemoHoverImage; opacity: 1.0}
            PropertyChanges { target: btAnimStateDemoPressedImage; opacity: 0.0}
        },
        State
        {
            name: "PRESSED"
            PropertyChanges { target: btAnimStateDemoBg; color: "blue"}
            PropertyChanges { target: btAnimStateDemoBg; radius: 15}
            PropertyChanges { target: btAnimStateDemoDefaultImage; opacity: 0.0}
            PropertyChanges { target: btAnimStateDemoHoverImage; opacity: 0.0}
            PropertyChanges { target: btAnimStateDemoPressedImage; opacity: 1.0}
        }
    ]

    // the matching transitions between states
    transitions:
    [
        Transition
        {
            from: "*"; to: "DEFAULT"
            ColorAnimation { property: "color"; easing.type: Easing.Linear; duration: 1000 }
            NumberAnimation { properties: "radius, opacity"; easing.type: Easing.Linear; duration: 1000 }
        },
        Transition
        {
            from: "*"; to: "HOVERED"
            ColorAnimation { property: "color"; easing.type: Easing.Linear; duration: 1000 }
            NumberAnimation { properties: "radius, opacity"; easing.type: Easing.Linear; duration: 1000 }
        },
        Transition
        {
            from: "*"; to: "PRESSED"
            ColorAnimation { property: "color"; easing.type: Easing.Linear; duration: 1000 }
            NumberAnimation { properties: "radius, opacity"; easing.type: Easing.Linear; duration: 1000 }
        }
    ]

    // the mouse area which will apply the correct state in relation to the current mouse status
    MouseArea
    {
        anchors.fill: parent
        hoverEnabled: true

        onEntered: {btAnimStateDemo.state = "HOVERED"; btAnimStateDemo.hoveredBtn = true;}
        onExited: {btAnimStateDemo.state = btAnimStateDemo.pressedBtn ? "PRESSED" : "DEFAULT"; btAnimStateDemo.hoveredBtn = false;}
        onPressed: {btAnimStateDemo.state = "PRESSED"; btAnimStateDemo.pressedBtn = true;}
        onReleased: {btAnimStateDemo.state = btAnimStateDemo.hoveredBtn ? "HOVERED" : "DEFAULT"; btAnimStateDemo.pressedBtn = false;}
    }
}

приведенный выше код работает хорошо и достигает цели, которую я планировал, но немного сложен с моей точки зрения. Было бы замечательно, если бы для изображений существовал аниматор, такой как NumberAnimation или ColorAnimation, но я не нашел ни одного.

Поэтому мой вопрос: существует ли более простой способ анимировать переход изображения между состояниями компонентов чем мое предложенное выше решение? Предлагает ли Qt Quick аниматор для достижения этой цели?

1 Ответ

0 голосов
/ 12 января 2020

Создайте таблицу SpriteSheet, которая присваивает состояния каждому из трех кадров, затем установите для свойства интерполяции значение true, чтобы оно переходило между изображениями.

Анимация спрайтов с помощью SpriteSequence SpriteSequence демонстрирует использование последовательности спрайтов для рисования анимированного и интерактивного медведя. Объект SpriteSequence определяет пять различных спрайтов. Медведь изначально находится в неподвижном состоянии:

      Sprite{
          name: "still"
          source: "content/BearSheet.png"
          frameCount: 1
          frameWidth: 256
          frameHeight: 256
          frameDuration: 100
          to: {"still":1, "blink":0.1, "floating":0}
      }

При щелчке по сцене анимация устанавливает последовательность спрайтов в падающие состояния и анимирует свойство y медведя.

  SequentialAnimation {
      id: anim
      ScriptAction { script: image.goalSprite = "falling"; }
      NumberAnimation { target: image; property: "y"; to: 480; duration: 12000; }
      ScriptAction { script: {image.goalSprite = ""; image.jumpTo("still");} }
      PropertyAction { target: image; property: "y"; value: 0 }
  }

В конце анимации медведь возвращается в исходное состояние.

...