[GET]ThreeJS + TweenJS模拟微信跳一跳粒子效果

上接翻转移动动画文章。

在下在实现移动动画的基础上,又去尝试了一下使用ThreeJS实现粒子效果,其过程异常头大。

这个是微信里的特效
这里写图片描述

设计思路

  • 生成粒子
  • 设置位置
  • 控制粒子移动

错误示范
这里写图片描述

通过错误示范,可以看到所生成的红色粒子,没有按照预想的状态去移动,而是产生了自己的移动方式。

之所以会出现这种情况,是因为在此之前在下没有考虑坐标系的缘故,将场景中所有方块的坐标系统一认定为世界坐标(粒子绑定在Player身上)。

之后在下在了解了以下坐标系以后,对整个代码进行了修整。

正确示范

首先是创建粒子,创建8个粒子,并且给定初始位置

这里的位置并没有选择用随机,因为考虑最后的实现效果
在下在类外面定义了一个常量数组,用来存储固定的粒子位置

  • this.geometry.vertices 用于存储粒子的位置
  • this.particles 粒子的节点
// 创建粒子
    CreatorParticles() {
        this.geometry = new THREE.Geometry();
        let vertext = null;
        for (let i = 0; i < 8; i++) {
            vertext = new THREE.Vector3(pos[i][0],pos[i][1],pos[i][2]);
            this.geometry.vertices.push(vertext);
        }
        let loader = new THREE.TextureLoader();
        let sprite = loader.load('./img/brick1.jpg');
        let color = [1, 0, 0];
        let size = 1;
        let pointsMaterial = new THREE.PointsMaterial({
            size: size,
            map: sprite,
            depthTest: false,
            transparent: true,
            opacity: 1.0,
            blending: THREE.AdditiveBlending
        });
        pointsMaterial.color.setRGB(color[0], color[1], color[2]);
        this.particles = new THREE.Points(this.geometry, pointsMaterial);
        this.particles.verticesNeedUpdate = true;
        this.play.add(this.particles);
        this.particles.position.set(0, 0, 0)
        this.particles.visible = false;
    }

这里是粒子的固定位置,0~7,最后一位是粒子向上的固定位置

// 粒子固定位置
const pos = [
    [-1,3,0],
    [0,2,0],
    [0,3,0],
    [0,3,-1],
    [1,3,-1],
    [2,2,0],
    [1,2,-2],
    [-1,1,0],
    [0, 0, -1]
]

做好了生成,边去考虑如何移动。
这里我是使用TweenJS去实现所有个粒子的移动

首先是向下的持续粒子效果

  • _obj是接收粒子当前位置
  • _int是指当前粒子在this.geometry.vertices中的下标
// 粒子移动
    ParticlesMove(_obj, _int) {
        let self = this;
        let endP = {
            x: _obj.x,
            y: _obj.y,
            z: _obj.z,
        }
        this.ParticlesTween = new TWEEN.Tween(endP);
        this.ParticlesTween.to({
            x: 0,
            y: 0,
            z: -1,
        },200);

        this.ParticlesTween.start();
        function onUpdate() {
            if(!self.switchTween) {
                self.ParticlesTween.stop();
            } else {
                self.geometry.verticesNeedUpdate = true;
                self.geometry.vertices[_int].x = this.x;
                self.geometry.vertices[_int].y = this.y;
                self.geometry.vertices[_int].z = this.z;
            }
        }
        function onComplete() {
            // self.particles.visible = true;
            if(self.switchTween) {
                self.geometry.verticesNeedUpdate = true;
                self.geometry.vertices[_int].x = pos[_int][0];
                self.geometry.vertices[_int].y = pos[_int][1];
                self.geometry.vertices[_int].z = pos[_int][2];
                self.ParticlesMove(self.geometry.vertices[_int], _int);
            } else {

            }
        }

        this.ParticlesTween.onUpdate(onUpdate);
        this.ParticlesTween.onComplete(onComplete);
    }

在动画播放结束方法onComplete()中,在不满足条件的的前提下持续回粒子移动方法ParticlesMove()

重点注意
这里我在做移动的时候吃了极大的亏
self.geometry.verticesNeedUpdate = true;
请注意这一段,在控制移动时,一定要告诉渲染器,我粒子需要移动,否则,粒子更改了位置信息,但是显示不会发生变化

经过这段移动代码,便实现了这样的效果:
这里写图片描述

GIF可能看不出效果
他是一个持续向下一个点的粒子效果

最后要做的就是实现向上的粒子特效

同样使用TweenJS去做

传入的参数同上

ParticlesMove2(_obj, _int) {
        let self = this;
        let endP = {
            x: _obj.x,
            y: _obj.y,
            z: _obj.z,
        }
        this.ParticlesTween2 = new TWEEN.Tween(endP);

        this.ParticlesTween2.to({
            x: pos[_int][0],
            y: pos[_int][1],
            z: pos[_int][2],
        }, 500);

        this.ParticlesTween2.start();
        function onUpdate() {
            self.geometry.vertices[_int].x = this.x;
            self.geometry.vertices[_int].y = this.y;
            self.geometry.vertices[_int].z = this.z;
            self.geometry.verticesNeedUpdate = true;
        }
        function onComplete() {
            self.particles.visible = false;
        }

        this.ParticlesTween2.onUpdate(onUpdate);
        this.ParticlesTween2.onComplete(onComplete);
    }

向上的效果:
这里写图片描述

只有一瞬间的效果,因此不再需要持续调用

总结
虽然最后实现了这样一个效果,但是与微信的相比还是差距很大(看到的大厂的实力)

对于小游戏或者技术实现玩一玩这个东西还是不错的
= =、

若有错误,欢迎指出。

开源万岁
Mr.YingS

aji@fristd.com

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
对于Vue3和Vite结合使用的项目,如果想要实现微信扫码登录功能,你可以按照以下步骤进行操作: 1. 在项目中安装 `@types/weixin-js-sdk`,这是微信JS-SDK的类型声明文件。 ```bash npm install @types/weixin-js-sdk --save-dev ``` 2. 在需要实现扫码登录的页面中引入微信JS-SDK。 ```html <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script> ``` 3. 创建一个辅助方法用于获取微信扫码登录所需的参数。 ```typescript import axios from 'axios'; async function getWeChatLoginParams(): Promise<any> { // 发起请求获取微信扫码登录所需的参数 const response = await axios.get('/your_api_endpoint'); // 返回获取到的参数 return response.data; } ``` 4. 在组件中使用上述辅助方法获取微信扫码登录参数,并初始化微信JS-SDK。 ```typescript import { ref, onMounted } from 'vue'; export default { setup() { const loginUrl = ref(''); onMounted(async () => { // 获取微信扫码登录参数 const params = await getWeChatLoginParams(); // 初始化微信JS-SDK wx.config({ appId: params.appId, timestamp: params.timestamp, nonceStr: params.nonceStr, signature: params.signature, jsApiList: ['scanQRCode'] // 需要使用的微信JS-SDK接口 }); // 获取扫码登录的url wx.ready(() => { wx.scanQRCode({ needResult: 1, scanType: ['qrCode'], success: (res: any) => { loginUrl.value = res.resultStr; } }); }); }); return { loginUrl }; } }; ``` 5. 在模板中使用获取到的登录url生成二维码展示给用户,并在用户扫码成功后进行相关的处理。 ```html <template> <div> <qrcode :value="loginUrl" size="200"></qrcode> <!-- 在这里添加处理扫码成功后的逻辑 --> </div> </template> ``` 请将上述代码根据自己的项目需求进行相应调整。 注意:以上代码仅为示例,具体的接口调用和业务逻辑可能需要你根据实际情况进行进一步开发和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值