查看完整版本: [-- 养生编程之眼见不为实(3) --]

QTCN开发网 -> Qt 作品展 -> 养生编程之眼见不为实(3) [打印本页] 登录 -> 注册 -> 回复主题 -> 发表主题

yanhubin 2019-09-03 17:00

养生编程之眼见不为实(3)

因为工作的关系这篇帖子拖了好久,废话不多说,此篇主要讲动画及粒子效果。
首先,我们看到,当用户列表这个代理Item被往左边拽的时候,右侧的按钮是有一个过冲弹簧动画的,为了实现这个动画,我们在右侧的删除按钮的Item中x属性是被这样绑定的   x: contactDelegate_item.x + parent.width     而不是通过anchors锚定在contactDelegate_item的右边线。这样,我们就可以通过设置一个目标为contactDelegateDel_item NumberAnimation 动画,这个动画曲线设置为我们想要的过冲弹簧效果 easing.type:Easing.OutElastic 并通过一些时间等参数设定,达到我们想要的效果。代码如下:
  1. NumberAnimation {
                    id: contactDelegateDelBg_rect_inAnimation
                    target: contactDelegateDel_item
                    properties: "x"
                    to: parent.width - contactDelegateDel_item.width
                    duration: 1000; easing.type:Easing.OutElastic; easing.period: 0.5; onStarted: delImg_animation.start()
                }
其实除了这个过冲弹簧效果,我们会看到上面现实的垃圾箱也会通过摇摆,来证明它的存在。
因此,我们在过冲动画开始的同时给这个垃圾箱嗑个药,让它摇摆起来。RotationAnimation就是这药丸的罪魁祸首,同样通过一下属性设置实现我们想要的效果。
  1. RotationAnimation { id: delImg_animation; target: del_img; properties: "rotation"; from: -50; to: 0; duration: 2000 ; easing.type:Easing.OutElastic; easing.period: 0.1}
有出现自然有退场, 退场动画我们也加上,兄弟情还是有的,也有回心转意不想让它灰飞烟灭的时候
  1. NumberAnimation {
                    id: contactDelegateDelBg_rect_outAnimation
                    target: contactDelegateDel_item
                    properties: "x"
                    to: parent.width
                    duration: 200
                }
到这里,基本的动画效果都实现了,接下来是本系列篇的重点灰飞烟面。
而这里才是本篇主题眼见不为实想要表达的。
第一篇里我介绍过老版本微信眼睛渐开的效果,很多人如果需要实现它,可能想到的是找UI要一个动画效果,但是我们发现,这个眼睛的展开程度是与拖动距离有关,如果使用动画我们就得将距离与动画帧绑定,这个很费力不讨好。
带过很多人,新手往往不太喜欢善用z轴,可能跟大家学习qt都是通过widget入门,在学习widget的时候又是通过.ui去实现自己人生的第一个界面效果,而通过这样的方式是不会去考虑z轴的,今天我要说的就是把界面提升到3维空间,用z轴去解决一些我们平时觉得很难实现的东西,这就是本篇的主题,眼见不为实。
首先,我们来分析下微信这个眼睛,我的实现方法是在listview的header中添加一个item,并且把我们看到的眼睛锚定到item的中心,之后我们在这个item的上面覆盖一层遮罩,遮罩是一个中心透明的圆,边上同背景色一样的颜色,实现方法可以是用图片,也可以用canvas ,通过拖拽距离与透明圆大小绑定,实现透明视窗变大,眼睛渐露,画张图给大家看下

[attachment=20799]
那么现在,各位在看到飞灰烟面效果,想要去实现的时候是否想到了什么。我们观察到实现效果中,所有粒子颜色是不一样的,看上去就像是从背景中各个位置取了颜色,给我们的粒子系统中的粒子上色,且从不同的位置发射,页面还要从右边逐渐消失,这太南南南南南南了,跟本没有实现的思路。
简直跟昨天看男篮世界杯周琦进攻犯规,两个发球失误还想赢球一样难。

但如果我们换个思路,所谓的消失如果是我们通过z轴覆盖一层跟背景色一样的遮罩,是不是看上去就跟消失一样了,看上去是减,其实是加,我们这样做试试。我们加一个遮罩,躲在最右侧,等待指令大杀四方。
  1. Item {
                    id: mask_item
                    x: parent.width
                    width: parent.width
                    height: parent.height
                    Behavior on x { NumberAnimation {duration: 1000} }
                    Rectangle{
                        id: maskgradient_rect
                        height: parent.height
                        width: height
                        rotation: -90
                        gradient: Gradient {
                            GradientStop { position: 0.0; color: "#00F7F9FE" }
                            GradientStop { position: 0.7; color: "#00F7F9FE" }
                            GradientStop { position: 1.0; color: "#FFFFFFFF" }
                        }
                    }
                    Rectangle{
                        anchors{
                            left: maskgradient_rect.right
                            top: maskgradient_rect.top
                            bottom: maskgradient_rect.bottom
                        }
                        width: contactDelegateBg_rect.width + 100
                        color: "white"
                    }
                }
在点击删除后开始从右到左的动画,看上去就像页面从右到左消失一样。
好了,只剩下粒子效果了,那么我们又如何实现那个复杂粒子生成算法。
同样换条路走,我们给界面截个图,将图片粒子化,是不是就很简单了,看看是否可行。

组装加农炮
  1. ParticleSystem {
                    id: particleSystem
                    anchors.left: mask_item.left
                    height: parent.height

                    Emitter {
                        id: emitter;
                        anchors.verticalCenter: parent.verticalCenter;
                        emitRate: 2000;
                        lifeSpan: 1000;
                        size: 3;     //粒子大小
                        sizeVariation: 5;  //    粒子大小变化
                        velocity: PointDirection{ x: -100; xVariation: 150; yVariation: 50}
                        width: 100;
                        height: mask_item.height
                    }

                }
                CustomParticle {
                    system: particleSystem
                    property real maxWidth: parent.width
                    property real maxHeight: parent.height
                    ShaderEffectSource {
                        id: pictureSource
                        sourceItem: picture
                        hideSource: true
                    }
                    Image {
                        id: picture
                    }

                    ShaderEffectSource {
                        id: particleSource
                        sourceItem: particle
                        hideSource: true
                    }

                    Rectangle{
                        id: particle
                        width: 5
                        height: width
                        color: "#ec534e"
                        radius: width/2
                    }

                    vertexShader:"
                        uniform highp float maxWidth;
                        uniform highp float maxHeight;
                        varying highp vec2 fTex2;
                        varying lowp float fFade;
                        uniform lowp float qt_Opacity;

                        void main() {

                            fTex2 = vec2(qt_ParticlePos.x, qt_ParticlePos.y);
                            //Uncomment this next line for each particle to use full texture, instead of the solid color at the center of the particle.
                            //fTex2 = fTex2 + ((- qt_ParticleData.z / 2. + qt_ParticleData.z) * qt_ParticleTex); //Adjusts size so it's like a chunk of image.
                            fTex2 = fTex2 / vec2(maxWidth, maxHeight);
                            highp float t = (qt_Timestamp - qt_ParticleData.x) / qt_ParticleData.y;
                            fFade = min(t*4., (1.-t*t)*.75) * qt_Opacity;
                            defaultMain();
                        }
                    "
                    property variant particleTexture: particleSource
                    property variant pictureTexture: pictureSource
                    fragmentShader: "
                        uniform sampler2D particleTexture;
                        uniform sampler2D pictureTexture;
                        varying highp vec2 qt_TexCoord0;
                        varying highp vec2 fTex2;
                        varying lowp float fFade;
                        void main() {
                            gl_FragColor = texture2D(pictureTexture, fTex2) * texture2D(particleTexture, qt_TexCoord0).w * fFade;
                    }"
                }
装上子弹,并发射
  1. MouseArea {
                        anchors.fill: parent
                        onClicked: {
                            contactDelegateBg_rect.grabToImage(function(grabResult) {
                                picture.source = grabResult.url;})

                            emitter.enabled = true
                            contactDelegateDelMask_item_inAnimation.start()

                        }
                    }

完美!!!
最后,当页面都被遮住,加农炮子弹射完后,我们把整个Item的身高压缩到0,最后真正的消灭它。
至此本篇核心内容到此为止,对于新手,很多效果的实现不要去看表面,我们可以把他们分解,并抽象到三维空间,无中生有,虚实结合!
最后把完整的Demo代码附上!代码使用5.13,可能大家没那么新,把import改一下即可。此Demo纯属养生代码,用于消遣,没有任何注释!
完整效果




[attachment=20800]


305750665 2019-09-04 09:10
老哥牛逼

liudianwu 2019-09-04 10:12
拖得不算久,还可以!

suzhuorui 2019-09-05 10:23
老哥,这个zip格式损坏了

suzhuorui 2019-09-05 11:49
为啥,用迅雷下载的就不可用,用浏览器下载的就可以

modongzhen 2019-10-09 15:44
大佬你好,我想问一下为什么我编译运行之后,没有显示用户头像的呢

有这个提示。QNetworkReplyHttpImplPrivate::_q_startOperation was called more than once QUrl("http://img5.duitang.com/uploads/item/201411/29/20141129010249_dh32E.thumb.700_0.jpeg")

xdh873939316 2019-10-10 08:32
  

coolee 2019-11-06 19:19
感谢分享,向楼主学习,编程也是一种态度!


查看完整版本: [-- 养生编程之眼见不为实(3) --] [-- top --]



Powered by phpwind v8.7 Code ©2003-2011 phpwind
Gzip disabled