不可能
pathview弄出来就这效果是不能接受的,所以继续往下,基本流程清楚后开始花里胡哨起来!
先理解
还是先理解做法的理念,这次找到这位大佬的demo QML实现酷炫的 Cover Flow 效果(PathView) ,概括起来为pathview添加部分效果,目的是为了好看:
- 展示分了层次,有一种前面和后面的层次,这就是z轴。
- 大小也有层次,最前面展示的最大,形成动态感。
- 各个目标有一定程度的翻转,看起来更立体。
- 出现倒影效果
PathAttribute
在Path的每个点后,可以自定义一些数据,这些数据可以应用于当前点的delegate。ok那每个点后添加三个属性,分别应用于后续使用的z轴,旋转角度和缩放大小:
Path{
id:pathview_path
startX: root.width*2/7
startY: root.height/3
PathAttribute{name:"picZ";value: 0}
PathAttribute{name:"picAngle";value: 50}
PathAttribute{name:"picScale";value: 0.6}
PathLine{x:root.width/2;y:root.height/3}
PathAttribute{name:"picZ";value: 100}
PathAttribute{name:"picAngle";value: 0}
PathAttribute{name:"picScale";value: 1.0}
PathLine{x:root.width*5/7;y:root.height/3}
PathAttribute{name:"picZ";value: 0}
PathAttribute{name:"picAngle";value: -50}
PathAttribute{name:"picScale";value: 0.6}
}
设置后,delegate中可通过PathView.picZ等来访问当前点的这个数据。而点与点之间的点的数据底层会自动计算逐步的递增或递减,就不用自己再定义了。
Z轴
z轴大概就是垂直于电脑屏幕的轴线,z轴值越大,就等于离看这电脑屏幕的你越近。
在delegate的Item里添加z:PathView.picZ属性和数据即可。
可以看到,中间的点的z轴数据是100,两边的是0。
大小和翻转
大小简单,用scale属性可以控制大小:scale:PathView.picScale。
而翻转就复杂很多,先设置变量接住设置的翻转角度属性:property int angle1: PathView.picAngle
为delegate添加翻转效果,使用transform: Rotation组件,通过设置原点的旋转轴和角度,就形成了旋转的效果。
transform: Rotation{
origin.x:image.width/2.0
origin.y:image.height/2.0
axis{x:0;y:1;z:0}
angle: angle1
}
这个通过官网文档可以理解一点 Rotation QML Type
而这个图和解释,就挺一目了然的:
倒影效果
先设好图片,右键资源文件目录qml.qrc有一个Open in Editor选项,里面选择Add添加图片进资源文件备用。
加载图片需要路径,这次的listmode的数据为图片的路径:
ListModel {
id:datamodel;
ListElement {url:"qrc:/1.jpg";}
ListElement {url:"qrc:/2.jpg";}
ListElement {url:"qrc:/3.jpg";}
ListElement {url:"qrc:/4.jpg";}
ListElement {url:"qrc:/5.jpg";}
}
后面在delegate里添加图片,由于有图片翻转了会出现一定的锯齿,添加抗锯齿属性antialiasing:
Image{
id:image
antialiasing: true
source: url
width: mydelegate.width
height: mydelegate.height
}
添加倒影是在图片的正下方再画一个倒立的图片即可,这边怎么实现的就不去追究了,直接拿大佬的:
ShaderEffect {
id: effectImage
anchors.top: image.bottom
width: image.width
height: image.height;
anchors.left: image.left
property variant source: image;
property size sourceSize: Qt.size(0.5 / image.width, 0.5 / image.height);
fragmentShader:
"varying highp vec2 qt_TexCoord0;
uniform lowp sampler2D source;
uniform lowp vec2 sourceSize;
uniform lowp float qt_Opacity;
void main() {
lowp vec2 tc = qt_TexCoord0 * vec2(1, -1) + vec2(0, 1);
lowp vec4 col = 0.25 * (texture2D(source, tc + sourceSize) + texture2D(source, tc- sourceSize)
+ texture2D(source, tc + sourceSize * vec2(1, -1))
+ texture2D(source, tc + sourceSize * vec2(-1, 1)));
gl_FragColor = col * qt_Opacity * (1.0 - qt_TexCoord0.y) * 0.2;
}"
}
鼠标键盘
pathview是没有集成鼠标点击事件的,就是点击项目是不会切换到那个项目,只能鼠标拖动。
所以在delegate中添加鼠标点击,集成这个效果吧:
MouseArea{
anchors.fill: parent
onClicked: {
pathView.currentIndex = index;
}
}
同理添加一下键盘控制,一开始发现怎么都不生效,后来发现是得先让pathview聚焦才行:
focus: true;
Keys.onLeftPressed: decrementCurrentIndex();
Keys.onRightPressed: incrementCurrentIndex();
Keys.onTabPressed: incrementCurrentIndex();
中间突出
最后把设置一下无论鼠标怎么拖动,突出的只有一个项目,术语叫期待选定项位位置,让当前选定的项位在路径的中间,这样无论怎么拖动都有一个固定在中间了:
preferredHighlightBegin: 0.5
preferredHighlightEnd: 0.5
我们不一样!
曾经的我很丑,但也只是曾经。