这里实现一个之前很火的白天黑夜切换的开关,使用动画和基本元素实现,无图片等外部资源,纯QML实现;
-
之前在网上看到很有意思的一个图:
-
想着自己刚好看了QML动画相关的,于是也动手纯手搓一个:
-
最后效果如下:
-
动图是这样的:
-
其中动画源码如下: -
源码:
-
使用:
-
//网红的白天黑夜切换开关 Rectangle { color: "#abcce1" anchors.fill: parent Column { anchors.centerIn: parent SwitchDayAndNight { switchWidth_i: 200 //根据宽度自动设定开关样式 animationDuration_i: 500 } SwitchDayAndNight { switchWidth_i: 600 //根据宽度自动设定开关样式 animationDuration_i: 1000 } } }
-
具体动画:
-
//切换动画 ParallelAnimation { id: cloudsAndSunMove_ID alwaysRunToEnd: true loops: 1 running: false NumberAnimation { target: lightRect_ID //太阳和光晕移动 property: "x" to: switchWidth_i - lightRect_ID.x - lightRect_ID.width duration: animationDuration_i easing.type: Easing.InOutCubic } NumberAnimation { target: moonRect_ID //月亮移动 property: "x" to: lightRect_ID.width + dropShadow_light_ID.radius * 2 - moonRect_ID.x duration: animationDuration_i easing.type: Easing.InOutCubic } NumberAnimation { target: distantCloudsItem_ID //远处云层下移 property: "y" to: rootItem_ID.height - distantCloudsItem_ID.y duration: animationDuration_i easing.type: Easing.InOutCubic } NumberAnimation { target: cloudsItem_ID //云层下移 property: "y" to: rootItem_ID.height - cloudsItem_ID.y duration: animationDuration_i easing.type: Easing.InOutCubic } NumberAnimation { target: starsItem_ID //星星下移 property: "y" to: -starsItem_ID.y - rootItem_ID.height duration: animationDuration_i easing.type: Easing.InOutCubic } } //星星动画 SequentialAnimation { id: starsShiningAnimation_ID loops: Animation.Infinite running: (0 === switchState_i) PropertyAnimation { target: star9_ID property: "scale" from: 0.1 to: 1 duration: 400 } PropertyAnimation { target: star6_ID property: "scale" from: 0.1 to: 1 duration: 400 } PropertyAnimation { target: star5_ID property: "scale" from: 0.1 to: 1 duration: 400 } PropertyAnimation { target: star2_ID property: "scale" from: 0.1 to: 1 duration: 400 } PauseAnimation { duration: 4000 } } //宇航员动画 SequentialAnimation { id: astronautAnimation_ID loops: Animation.Infinite running: (0 === switchState_i) PauseAnimation { duration: 2000 } ParallelAnimation { NumberAnimation { target: astronaut_ID property: "x" duration: animationDuration_i * 8 from: -astronaut_ID.width to: switchWidth_i / 5 * 3 easing.type: Easing.OutInBack } NumberAnimation { target: astronaut_ID property: "y" duration: animationDuration_i * 16 from: rootItem_ID.height + astronaut_ID.height to: -astronaut_ID.height easing.type: Easing.OutInBack } RotationAnimation { target: astronaut_ID from: 0 to: 360 duration: animationDuration_i * 16 } } PauseAnimation { duration: 4000 } } //飞机动画 SequentialAnimation { id: planeAnimation_ID loops: Animation.Infinite running: (1 === switchState_i) PauseAnimation { duration: 2000 } ParallelAnimation { //注意如果使用Animator,改变动画状态running为false后再调用complete()不生效 NumberAnimation { target: plane_ID property: "x" duration: animationDuration_i * 8 from: switchWidth_i to: -plane_ID.width easing.type: Easing.InOutCubic } NumberAnimation { target: plane_ID property: "y" duration: animationDuration_i * 8 from: rootItem_ID.height / 3 * 2 to: 0 easing.type: Easing.InOutCubic } } PauseAnimation { duration: 3000 } }
-
-
总结:
- 如果把矩形设置半径,然后需要设置
clip
属性,在这种情况下会出现内部组件超出范围的情况,需要设置遮盖或着色器; - 设置遮盖后内外阴影会有一些问题,可以自己写;
- 因为
Animator
是独立用GPU渲染,阻塞也不会影响运行,但是在需要自定义动画启停且频率较高时还是不要用了,容易有问题;
- 如果把矩形设置半径,然后需要设置