QML 中类似于 MacOS 停靠站的组件

问题描述 投票:0回答:3

使用 QtQuick,我在中继器中有一行 5 个图像。我想实现一个类似于 MacOS 停靠动画的悬停动画。这是一张图片供参考:

为了进一步分解它,这就是我想要完成的任务。这些图像在悬停时应如下所示:

  • 悬停图像展开
  • 相邻图像扩大,但稍小
  • 图像在展开时不会重叠

这是我到目前为止的代码

  Row {
    spacing: 2
    anchors.bottom: parent.bottom
    anchors.bottomMargin: 30
    anchors.horizontalCenter: parent.horizontalCenter

    Repeater {
      id: iconRepeater
      model: iconColors()
      Image {
        source: "icons/" + modelData + ".png"
        scale: mouseArea.containsMouse ? 1.5 : 1.0
        MouseArea {
          id: mouseArea
          anchors.fill: parent
          hoverEnabled: true
          onClicked: endTimer()
        }
        Behavior on scale {
          PropertyAnimation {
            duration: 75
          }
        }
      }
    }
  }

这会扩展您悬停在其上的图像,但我似乎无法影响邻居。任何建议表示赞赏!

macos qt qml qt-quick dock
3个回答
7
投票

我建议一个更强大的解决方案,您可以控制缩放系数以及影响的传播和衰减:

  Column {
    Slider {
      id: foff
      from: 1
      to: 5
      stepSize: 1
      value: 2
      snapMode: Slider.SnapAlways
    }
    Slider {
      id: sf
      from: 0.5
      to: 2.5
      stepSize: 0.5
      value: 0.5
      snapMode: Slider.SnapAlways
    }
    Slider {
      id: dmp
      from: 1
      to: 5
      stepSize: 1
      value: 1
      snapMode: Slider.SnapAlways
    }
  }

  Row {
    id: row
    anchors.bottom: parent.bottom
    anchors.bottomMargin: 30
    anchors.horizontalCenter: parent.horizontalCenter

    property int falloff: foff.value // how many adjacent elements are affected
    property int current: -1
    property real scaleFactor: sf.value // that's how much extra it scales
    property real damp: dmp.value // decay of influence 

    Repeater {
      id: iconRepeater
      model: 10
      Rectangle {
        width: 50 * pseudoScale
        height: width
        anchors.bottom: parent.bottom
        color: "red"
        border.color: "black"
        property real pseudoScale: {
          if (row.current == -1) return 1
          else {
            var diff = Math.abs(index - row.current)
            diff = Math.max(0, row.falloff - diff)
            var damp = row.falloff - Math.max(1, diff)
            var sc = row.scaleFactor
            if (damp) sc /= damp * row.damp
            diff = diff / row.falloff * sc + 1
            return diff
          }
        }
        MouseArea {
          id: mouseArea
          anchors.fill: parent
          hoverEnabled: true
          onContainsMouseChanged: row.current = containsMouse ? index : -1
        }
        Behavior on pseudoScale {
          PropertyAnimation {
            duration: 150
          }
        }
      }
    }
  }

1
投票

可能是这样的:

Row {
    anchors {
        bottom: parent.bottom
        left: parent.left
        right: parent.right
    }

    Repeater {
        id: rep
        model: ['red', 'yellow', 'pink', 'green', 'teal', 'orchid', 'blue', 'orange']
        property int currentIndex: -10

        delegate: Rectangle {
            anchors.bottom: parent.bottom
            // Calculate the width depending on the currently hovered element
            width: (rep.currentIndex === index ? 100 : ((rep.currentIndex - index) === 1 || (rep.currentIndex - index) === -1 ? 80 : 50))
            height: width
            radius: width / 2
            color: modelData
            MouseArea {
                anchors.fill: parent
                hoverEnabled: true
                // onEntered/Exited did not react. This will work.
                onContainsMouseChanged: {
                    if (containsMouse) rep.currentIndex = index
                    else rep.currentIndex = -10 // -10 is safe
                }
            }
            // Makes the movement smooth
            Behavior on width {
                NumberAnimation {}
            }
        }
    }
}

我尝试在代码中添加必要的解释作为注释。 唯一需要调整的是,当第一次调整大小时,点将首先移动。将其放在可轻柔的位置并进行一些体力劳动以进行正确的位置处理可以解决这个问题。基本上,当鼠标进入时,您需要将可轻拂的宽度变化的一半(在我的情况下约为 55 左右)向左移动,当鼠标再次离开时向右移动。

您也可以使用 ListView 来实现这一点,很可能,但由于背景的估计大小不断变化,获得正确的定位可能更具挑战性。


0
投票

我尝试了上面的两个代码并遇到了同样的问题。当我从右向左滑动项目而不是从左向右滑动时,它们会起作用。这是一个可能的错误吗? Problem swiping left to right

© www.soinside.com 2019 - 2024. All rights reserved.