代码之家  ›  专栏  ›  技术社区  ›  Kieran E

QML中的MacOS dock-like组件

  •  1
  • Kieran E  · 技术社区  · 7 年前

    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 回复  |  直到 7 年前
        1
  •  7
  •   dtech    7 年前

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

    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
              }
            }
          }
        }
      }
    
        2
  •  1
  •   derM - not here for BOT dreams    7 年前

    可能是这样的:

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

    我试图在代码中加入必要的解释作为注释。 唯一需要做一些调整的是,当第一次调整大小时,这些点最初会移动。把它放在一个可翻转的位置上,并在右利手位置进行一些体力劳动,可以解决这个问题。基本上,当鼠标进入时,你需要将flickable移动一半的宽度变化(在我的例子中大约55个左右)到左边,当它再次离开时,移动到右边。

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

    推荐文章