美文网首页
vue 小球粒子动画

vue 小球粒子动画

作者: 大梦无痕 | 来源:发表于2021-04-19 16:34 被阅读0次

效果图

image.png

插件three.js,自行下载导入

//canvas.js
import THREE from "@/libs/three.js";
export function particle(el){
    var SEPARATION = 200, AMOUNTX = 200, AMOUNTY = 50;
    var container;
    var camera, scene, renderer;
    var particles, particle, count = 0;
    var mouseX = 0, mouseY = -500;
    var windowHalfX = window.innerWidth / 2;
    var windowHalfY = window.innerHeight / 2;
    init();
    animate();
    function init() {
        container = document.createElement( 'div' );
        container.className = "canvas";
        (el?el:document.body).appendChild( container );
        console.log( window.innerWidth / window.innerHeight);
        camera = new THREE.PerspectiveCamera( 100, window.innerWidth / window.innerHeight, 1, 10000 );
        camera.position.z = 3000;
        scene = new THREE.Scene();
        particles = new Array();
        var PI2 = Math.PI * 2;
        console.log(THREE);
        var material = new THREE.ParticleCanvasMaterial( {
            color: "#64CAE5",
            program: function ( context ) {
                context.beginPath();
                context.arc( 0, 0, 1, 0, PI2, true );
                context.fill();
            }
        } );
        var i = 0;
        for ( var ix = 0; ix < AMOUNTX; ix ++ ) {
            for ( var iy = 0; iy < AMOUNTY; iy ++ ) {
                particle = particles[ i ++ ] = new THREE.Particle( material );
                particle.position.x = ix * SEPARATION - ( ( AMOUNTX * SEPARATION ) / 2 );
                particle.position.z = iy * SEPARATION - ( ( AMOUNTY * SEPARATION ) / 2 );
                scene.add( particle );
            }
        }
        renderer = new THREE.CanvasRenderer();
        console.log(renderer);
        renderer.setSize( window.innerWidth, window.innerHeight );
        container.appendChild( renderer.domElement );
        //是否开启事件
        //document.addEventListener( 'mousemove', onDocumentMouseMove, false );
        //document.addEventListener( 'touchstart', onDocumentTouchStart, false );
        //document.addEventListener( 'touchmove', onDocumentTouchMove, false );
        window.addEventListener( 'resize', onWindowResize, false );
    }
    function onWindowResize() {
        windowHalfX = window.innerWidth / 2;
        windowHalfY = window.innerHeight / 2;
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize( window.innerWidth, window.innerHeight );
    }
    //
    function onDocumentMouseMove( event ) {
        mouseX = event.clientX - windowHalfX;
        mouseY = event.clientY - windowHalfY;
    }
    function onDocumentTouchStart( event ) {
        if ( event.touches.length === 1 ) {
            event.preventDefault();
            mouseX = event.touches[ 0 ].pageX - windowHalfX;
            mouseY = event.touches[ 0 ].pageY - windowHalfY;
        }
    }
    function onDocumentTouchMove( event ) {
        if ( event.touches.length === 1 ) {
            event.preventDefault();
            mouseX = event.touches[ 0 ].pageX - windowHalfX;
            mouseY = event.touches[ 0 ].pageY - windowHalfY;
        }
    }
    //
    function animate() {
        requestAnimationFrame( animate );
        render();
    }
    function render() {
        camera.position.x += ( mouseX - camera.position.x ) * .05;
        camera.position.y += ( - mouseY - camera.position.y ) * .05;
        camera.lookAt( scene.position );
        var i = 0;
        for ( var ix = 0; ix < AMOUNTX; ix ++ ) {
            for ( var iy = 0; iy < AMOUNTY; iy ++ ) {
                particle = particles[ i++ ];
                particle.position.y = ( Math.sin( ( ix + count ) * 0.3 ) * 50 ) + ( Math.sin( ( iy + count ) * 0.5 ) * 50 );
                particle.scale.x = particle.scale.y = ( Math.sin( ( ix + count ) * 0.3 ) + 1 ) * 2 + ( Math.sin( ( iy + count ) * 0.5 ) + 1 ) * 2;
            }
        }
        renderer.render( scene, camera );
        count += 0.1;
    }
}
export default particle;

炫彩丝带动画ribbon.js,需要代码的私信我

//vsx: window.atob("MjAyMS0wOC0wMQ==");
//login.vue
<template>
    <div id="login" v-loading="loading">
        <!-- 粒子动画 -->
        <div class="lz" id="lz" :style="'background:url('+back+');background-size: 100% 100%;'">
            <!-- 炫彩丝带动画 -->
            <div class="particle" id="particle"></div>
        </div>
        <div class="warapp">
            <div class="form">
                <div class="tabs">
                   <h2 class="subhead">用户登录/User login</h2>
                </div>
                <div class="body">
                    <el-form :model="form" ref="from1" class="from">
                        <el-form-item prop="username" class="formItem" :rules="[{required:true,trigger:'blur',message:'请输入用户名'}]">
                            <!-- <el-input type="text" maxlength="11" v-model="form.phone" autocomplete="off" placeholder="请输入手机号"></el-input> -->
                            <input class="input" type="text" maxlength="11" @focus="focus3=true" @blur="focus3=false" v-model="form.username" autocomplete="off" />   
                            <div :class="focus3||form.username?'poslabel acv':'poslabel'">请输入用户名</div>
                        </el-form-item>
                        <el-form-item prop="password" class="formItem" :rules="[{required:true,trigger:'blur',message:'请输入密码'}]">
                            <!-- <el-input type="password" v-model="form.password" placeholder="请输入密码"></el-input> -->
                            <input class="input" type="password"  @focus="focus4=true" @blur="focus4=false" v-model="form.password" /> 
                            <div :class="focus4||form.password?'poslabel acv':'poslabel'">请输入密码</div>  
                        </el-form-item>
                        <!-- <div class="msg">
                            <router-link class="href" to="/password">忘记密码</router-link>
                        </div> -->
                        <el-form-item>
                            <el-button round style="display: block;width: 100%;" type="primary" :loading="loading" @click="submitPass">登录</el-button>
                            <!-- <p class="versions"><span class="cer">还没账户?</span><router-link :to="{path:'/register'}" class="cor">马上注册</router-link></p> -->
                        </el-form-item>
                    </el-form>
                </div>
            </div>
        </div>
        <div class="footer">
            <div class="text">折百惠</div>
            <div class="text">copyright@2015-2020 武汉折百惠科技有限公司 All Rights Reserved. 沪ICP备15020529号</div>
        </div>
    </div>
</template>
<script>
    import {validateTel} from "@/libs/reg.js";
    import {mapActions,mapState} from "vuex";
    import back1 from "@/assets/back1.png";
    import {factory} from "@/libs/ribbon.js";
    import {particle} from "@/libs/canvas.js";
    export default{
        data(){
            return {
                back:back1,
                focus1:false,
                focus2:false,
                focus3:false,
                focus4:false,
                form:{
                    username:"",
                    //verify:"",
                    password:"",
                    //type:2,////1.验证码登录 2.手机号密码登录
                },
                time:180,//验证码失效时间
                loading:false,
                isCode:false,//验证码是否已经发送
                rules:{
                    validateTel:validateTel
                }
            }
        },
        computed:{
            ...mapState({
                token:state=>state.token
            }),
        },
        methods:{
            ...mapActions(["getLogin","getToken"]),
            //密码登录
            submitPass(){
                this.loading = true;
                this.$refs.from1.validate((some)=>{
                    if(some){
                        this.getLogin(this.form).then((res)=>{
                            if(res.code==0){
                                this.$store.commit("SET_USERINFO",res.data);
                                this.$router.push("/Layout/home");
                            }
                            this.loading = false;
                            this.$message({
                                type:res.code==0?'success':'error',
                                message:res.msg
                            })
                        }).catch(()=>{
                            this.loading = false;
                        })
                    }else{
                        this.loading = false;
                        this.$message.error("请填写完成表单");
                        return false;
                    }
                })
            },
            getExp(){
                this.getToken().then((res)=>{
                    if(res.code==0){
                        res.data.exp = new Date().getTime()+res.data.exp*1000;
                        this.$store.commit("SET_TOKEN",res.data);
                    }
                })
            }
        },
        mounted(){
            if(!this.token.exp||!this.token||this.token.exp<new Date().getTime()){
                this.getExp();
            }
            if(typeof window === "object"){
                setTimeout(()=>{
                    window.Ribbons = factory(document.getElementById("lz"));
                    new Ribbons("Ribbons",factory());
                    particle(document.getElementById("particle"));
                },100)
            }
        }
    }
</script>
<style lang="scss" scoped>
        .canvas{
            position: absolute;
            left: 0;
            top: 180px;
            right: 0;
            bottom: 0;
            overflow: hidden;
        }
        #login{
        height: 100%;
        width: 100%;
        position: relative;
        background: #F7F7F7;
        padding-bottom: 80px;
        box-sizing: border-box;
        overflow: auto;
        >>> .el-button{
            height: auto;
        }
        .warapp{
            height: 370px;
            width: 350px;
            position: relative;
            z-index: 100;
            overflow: hidden;
            left: 50%;
            top: 50%;
            transform: translate(-50%,-50%);
            .form{
                position: absolute;
                right: 0;
                top: 0;
                height: 100%;
                width: 100%;
                background:rgba(255,255,255,0.8);
                padding: 20px 40px;
                box-sizing: border-box;
                -webkit-box-sizing: border-box;
                -moz-box-sizing: border-box;
                >>> .el-button--primary{
                    background: #3068F0;
                }
                .formItem{
                    border-bottom: 1.5px solid #979797;
                    position: relative;
                    .poslabel{
                        position:absolute;
                        left: 8px;
                        top: 0;
                        font-size: 16px;
                        color: #909090;
                        line-height: 40px;
                        width: 100%;
                        height: 100%;
                        z-index: 1;
                        transition: all 0.5s;
                    }
                    .poslabel.acv{
                        top: -28px;
                        height: 28px;
                        line-height: 28px;
                        font-size: 12px;
                    }
                }
                .input{
                    color: #909090;
                    width: 100%;
                    border: none;
                    outline: none;
                    height: 40px;
                    line-height: 40px;
                    font-size: 16px;
                    background: none;
                    position: relative;
                    z-index: 2;
                    padding-left: 8px;
                    box-sizing: border-box;
                }
                .tabs{
                    height: 48px;
                    line-height: 48px;
                    display: flex;
                    width: 100%;
                    margin: 0 auto;
                    justify-content: center;
                    .subhead{
                        font-size: 20px;
                        line-height: 20px;
                        margin-top: 35px;
                        margin-bottom: 52px;
                        color: #368ae3;
                        letter-spacing: 2px;
                        text-shadow: 0 0 3px #368ae3;
                        text-align: center;
                        font-weight: 100;
                    }
                }
                .body{
                    width: 100%;
                    margin: 40px auto 20px auto;
                    >>> .el-form-item{
                        margin-bottom: 40px;
                    }
                }
                .msg{
                    margin-bottom: 40px;
                    line-height: 20px;
                    text-align: right;
                    .href{
                        color: #909090;
                        text-decoration: none;
                        font-size: 14px;
                    }
                }
                .versions{
                    text-align: center;
                    line-height: 60px;
                    font-size: 14px;
                    color: #909090;
                    .cor{
                        color: #3068F0;
                        text-decoration: none;
                    }
                }
            }
        }
        .footer{
            text-align: center;
            font-size: 14px;
            color:#fff;
            line-height: 30px;
            width: 100%;
            position: absolute;
            bottom: 100px;
            z-index: 101;
        }
    }
    .lz{
        position: fixed;
        left: 0;
        top: 0;
        bottom: 0;
        right: 0;
        z-index: 1;
        background: #3068F0;
        .particle{
            position: absolute;
            top: 180px;
            width: 100%;
            bottom: 0;
        }
    }
</style>

相关文章

  • vue 小球粒子动画

    效果图 插件three.js,自行下载导入 炫彩丝带动画ribbon.js,需要代码的私信我

  • 粒子动画效果实现和Swift面向协议开发

    粒子动画效果实现是通过CALayer的子类,CAEmitterLayer实现。 实现粒子动画效果分以下几个步骤: ...

  • 粒子动画

  • 粒子动画

    占位符

  • 粒子动画

    一、在 UIKit 中,粒子系统由两部分组成: 1: 一个或多个 CAEmitterCells :发射器电...

  • 粒子动画

    一个或多个CAEmitterCells:发射器电池可以看作是单个粒子的原型(例如,一个单一的粉扑在一团烟雾)。当散...

  • 粒子动画

    @property(nonatomic, strong) CAEmitterLayer *emitterLayer...

  • 粒子动画

    公司做了一个类似小游戏的项目,背景需要放个流星雨效果粒子动画,详细的不多说,主要自己纪录学习,上代码。 -(voi...

  • 粒子动画

    粒子系统 直播中常用的粒子是怎么搞出来的呢,下面来进行一下探究 CAEmitterLayer 是一个高性能的粒子引...

  • 粒子动画

    什么是粒子系统? 粒子系统是由总体具有相同的表现规律,个体却随机表现出不同的特征的大量显示元素构成的集合 粒子定义...

网友评论

      本文标题:vue 小球粒子动画

      本文链接:https://www.haomeiwen.com/subject/udoilltx.html