QML

时间:2017-09-26 20:42:00

标签: macos qt qml qt-quick dock

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

MacOS Dock

为了进一步分解,这就是我想要实现的目标。这些图像在悬停时应如下:

  • 悬停的图片展开
  • 相邻图片展开,但略少
  • 图片在扩展时不重叠

这是我到目前为止的代码

  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
          }
        }
      }
    }
  }

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

2 个答案:

答案 0 :(得分:6)

我建议使用更强大的解决方案,您可以控制缩放因子以及影响的传播和衰减:

enter image description here

  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 :(得分: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 {}
            }
        }
    }
}

我试图在代码中作为评论进行必要的解释。 唯一需要一些tweeking的是,当第一次调整大小时,这些点最初会被移动。把它放在一个可以轻松和一些体力劳动的正确位置handeling可以解决这个问题。基本上你需要将鼠标进入时左侧宽度变化的一半(在我的情况下为~55左右)向左移动,当它再次离开时向右移动。

您最有可能使用ListView,但由于背景的估计大小不断变化,可能更适合定位正确。