浙江铃声推荐联盟

也许vue+css3做交互特效更简单

前端简单说2019-03-26 08:44:42

点击上方 蓝字,即可关注我们哦!


作者:守候

https://segmentfault.com/a/1190000012073091


1.前言

做项目就难免会开发交互效果或者特效,而我最近开发的项目一直在使用 vue,开发技术栈方面,理所当然就使用了 vue+ css3开发,过程中发现使用 vue+ css3开发特效,和 javascript/ jquery+ css3的思维方式不一样,但是比 javascript/ jquery+ css3简单一点点。今天就分享三个简单的小实例,希望能起到拓展思维的作用,让大家明白vue+css3应该怎样开发交互效果!如果大家有什么好的建议,或者觉得我哪里写错了,欢迎指出!

  1. 文章上面的代码,虽然代码很简单,不难理解,但是也是建议大家边写边看,这样不会混乱。

  2. 文章所提及的小实例,都是很基础的,大家可以参照自己的想法进行扩展,或者修改,可能会有意想不到的效果。我写这类型的文章也是想授人以渔,不是授人以鱼!

  3. 这几个实例,摘自我自己的平常练习的项目,代码已经提到github上面了(vue-demos)。欢迎大家star。

2.开场小动画

运行效果

gif图模糊效果看着跟实际效果不太一样!大家注意!

原理分析

说到原理分析,其实也没什么可以分析的,就是在页面是下面这个状态的时候,把文字替换掉。至于看到字体缩成一团,就是 letter-spacing这个 css属性的控制效果。字体模糊就是 filter:blur()这个 css属性的控制效果!看到有逐渐的变化,就是css3动画( animation)的效果

下面简单分析下,这个动画的几个步骤,从下面看到,这个动画一共8个步骤。

这下就清晰明了了,我们要在下图这个瞬间开始改变文字,也就是页面加载了两秒后,动画执行了两次后就开始改变文字。然后每隔两秒改变一次文字,直到最后!

下面给出 vuejavascript两种方式的代码,看下哪种方式更加的简单!

vue方式
  1.    <!DOCTYPE html>

  2.    <html lang="en">

  3.    <head>

  4.        <meta charset="UTF-8">

  5.        <title>Title</title>

  6.    </head>

  7.    <style>

  8.        body{

  9.            background: #ccc;

  10.        }

  11.        h1 {

  12.            color: white;

  13.            text-transform: uppercase;

  14.            margin-top: 100px;

  15.            text-align: center;

  16.            font-size: 6rem;

  17.            line-height: 1;

  18.            animation: letterspacing 1s 7 alternate ease-in-out;

  19.            display: block;

  20.            letter-spacing: .5rem;

  21.        }

  22.        @keyframes letterspacing {

  23.            0% {

  24.                letter-spacing: -72px;

  25.                filter: blur(20px);

  26.            }

  27.            40% {

  28.                filter: blur(6px);

  29.            }

  30.            80% {

  31.                letter-spacing: 8px;

  32.                filter: blur(0);

  33.            }

  34.        }

  35.    </style>

  36.    <body>

  37.    <div id="text">

  38.        <h1>{{testText}}</h1>

  39.    </div>

  40.    </body>

  41.    <script src="vue.min.js"></script>

  42.    <script type="text/javascript">

  43.        new Vue({

  44.            el:'#text',

  45.            data:{

  46.                nowIndex:0,

  47.                testText:'欢迎浏览'

  48.            },

  49.            mounted(){

  50.                let _this=this;

  51.                let timer = setInterval(function(){

  52.                    _this.nowIndex++;

  53.                    switch (_this.nowIndex) {

  54.                        case 1:

  55.                            _this.testText = '守候的文章';

  56.                            break;

  57.                        case 2:

  58.                            _this.testText = '愿您浏览愉快';

  59.                            break;

  60.                        case 3:

  61.                            _this.testText = '学到知识';

  62.                            break;

  63.                    }

  64.                    if (_this.nowIndex > 3) {

  65.                        setTimeout(() => {

  66.                            clearInterval(timer);

  67.                        }, 2000)

  68.                    }

  69.                }, 2000)

  70.            }

  71.        })

  72.    </script>

  73.    </html>

javascript方式
  1.    <!DOCTYPE html>

  2.    <html lang="en">

  3.    <head>

  4.        <meta charset="UTF-8">

  5.        <title>Title</title>

  6.    </head>

  7.    <style>

  8.        body{

  9.            background: #ccc;

  10.        }

  11.        h1 {

  12.            color: white;

  13.            text-transform: uppercase;

  14.            margin-top: 100px;

  15.            text-align: center;

  16.            font-size: 6rem;

  17.            line-height: 1;

  18.            animation: letterspacing 1s 7 alternate ease-in-out;

  19.            display: block;

  20.            letter-spacing: .5rem;

  21.        }

  22.        @keyframes letterspacing {

  23.            0% {

  24.                letter-spacing: -6rem;

  25.                filter: blur(1rem);

  26.            }

  27.            40% {

  28.                filter: blur(.3rem);

  29.            }

  30.            80% {

  31.                letter-spacing: .5rem;

  32.                filter: blur(0rem);

  33.            }

  34.        }

  35.    </style>

  36.    <body>

  37.    <div id="text">

  38.        <h1>欢迎浏览</h1>

  39.    </div>

  40.    </body>

  41.    <script>

  42.        var oH1=document.querySelector('h1'),nowIndex=0;

  43.        console.log(oH1)

  44.        var timer = setInterval(function () {

  45.            nowIndex++;

  46.            switch (nowIndex) {

  47.                case 1:

  48.                    oH1.innerHTML = '守候的文章';

  49.                    break;

  50.                case 2:

  51.                    oH1.innerHTML = '愿您浏览愉快';

  52.                    break;

  53.                case 3:

  54.                    oH1.innerHTML = '学到知识';

  55.                    break;

  56.            }

  57.            if (nowIndex > 3) {

  58.                setTimeout(() => {

  59.                    clearInterval(timer);

  60.                }, 2000)

  61.            }

  62.        }, 2000)

  63.    </script>

  64.    </html>

3.导航滑块

运行效果

原理分析

首先,下面是页面初始化的时候,橙色滑块的位置


鼠标放到第二个tab上面,大家可以看到,橙色滑块就是向右偏移了一个tab的距离

鼠标放到第三个tab上面,大家可以看到,橙色滑块就是向右偏移了两个tab的距离

如果从第一个tab到第六个tab的索引是0,1,2,3,4,5。

那么滑块的公式就是(索引*tab的宽度)。大家看到有逐渐过去的效果,其实是css3过渡( transition)的效果。大家看下面的代码就行了,一看就懂!代码如下:

vue方式
  1.    <!DOCTYPE html>

  2.    <html lang="en">

  3.    <head>

  4.        <meta charset="UTF-8">

  5.        <title>Title</title>

  6.    </head>

  7.    <link rel="stylesheet" href="reset.css">

  8.    <style>

  9.        .nav{

  10.            margin: 40px;

  11.            position: relative;

  12.        }

  13.    .nav li{

  14.        float: left;

  15.        width: 100px;

  16.        height: 40px;

  17.        line-height: 40px;

  18.        color: #fff;

  19.        text-align: center;

  20.        background: #09f;

  21.        cursor: pointer;

  22.    }

  23.        .nav span{

  24.            position: relative;

  25.            z-index: 2;

  26.        }

  27.        .nav .slider{

  28.            position: absolute;

  29.            transition: all .5s cubic-bezier(0.4, -0.3, 0.57, 1.38);

  30.            width: 100px;

  31.            height: 40px;

  32.            background: #f90;

  33.            top: 0;

  34.            left: 0;

  35.            z-index: 1;

  36.        }

  37.    </style>

  38.    <body>

  39.    <div class="nav clear" id="nav" @mouseleave="nowIndex=0">

  40.        <ul>

  41.            <li @mouseenter.stop="nowIndex=0"><span>Tab One</span></li>

  42.            <li @mouseenter.stop="nowIndex=1"><span>Tab Two</span></li>

  43.            <li @mouseenter.stop="nowIndex=2"><span>Tab Three</span></li>

  44.            <li @mouseenter.stop="nowIndex=3"><span>Tab four</span></li>

  45.            <li @mouseenter.stop="nowIndex=4"><span>Tab five</span></li>

  46.            <li @mouseenter.stop="nowIndex=5"><span>Tab six</span></li>

  47.        </ul>

  48.        <div class="slider" :style="{'transform':'translate3d('+nowIndex*100+'px,0,0)'}"></div>

  49.    </div>

  50.    </body>

  51.    <script src="vue.min.js"></script>

  52.    <script type="text/javascript">

  53.       new Vue({

  54.           el:'#nav',

  55.           data:{

  56.               nowIndex:0

  57.           }

  58.       })

  59.    </script>

  60.    </html>

javascript方式
  1.    <!DOCTYPE html>

  2.    <html lang="en">

  3.    <head>

  4.        <meta charset="UTF-8">

  5.        <title>Title</title>

  6.    </head>

  7.    <link rel="stylesheet" href="reset.css">

  8.    <style>

  9.        .nav{

  10.            position: relative;

  11.        }

  12.    .nav li{

  13.        float: left;

  14.        width: 100px;

  15.        height: 40px;

  16.        line-height: 40px;

  17.        color: #fff;

  18.        text-align: center;

  19.        background: #09f;

  20.        cursor: pointer;

  21.    }

  22.        .nav span{

  23.            position: relative;

  24.            z-index: 2;

  25.        }

  26.        .nav .slider{

  27.            position: absolute;

  28.            transition: all .5s cubic-bezier(0.4, -0.3, 0.57, 1.38);

  29.            width: 100px;

  30.            height: 40px;

  31.            background: #f90;

  32.            top: 0;

  33.            left: 0;

  34.            z-index: 1;

  35.        }

  36.    </style>

  37.    <body>

  38.    <div class="nav clear" id="nav">

  39.        <ul>

  40.            <li><span>Tab One</span></li>

  41.            <li><span>Tab Two</span></li>

  42.            <li><span>Tab Three</span></li>

  43.            <li><span>Tab four</span></li>

  44.            <li><span>Tab five</span></li>

  45.            <li><span>Tab six</span></li>

  46.        </ul>

  47.        <div class="slider"></div>

  48.    </div>

  49.    </body>

  50.    <script type="text/javascript">

  51.        var oDiv=document.querySelector("#nav"),oLi=oDiv.querySelectorAll("li"),oSlider=document.querySelector(".slider");

  52.        oDiv.addEventListener("mouseleave",function () {

  53.            oSlider.style.transform='translate3d(0,0,0)';

  54.        })

  55.        for(var i=0;i<oLi.length;i++){

  56.            oLi[i].index=i;

  57.            oLi[i].addEventListener("mouseenter",function (e) {

  58.                oSlider.style.transform='translate3d('+this.index*100+'px,0,0)';

  59.            })

  60.        }

  61.    </script>

  62.    </html>

4.轮播图

运行效果


原理分析

蓝框的是li,黑框的是div

初始化状态

处于显示第二张图片的时候


看到上面,其实也就是控制ul的偏移量( transform:translate3d)。计算公式和上面的滑块相似,索引( 0|1|2|3)* li的宽度。不同的就是,ul的偏移量是取负数,因为ul是想左偏,上面的滑块是向右偏!

当第一张图片的时候,ul偏移量设置( transform:translate3d(0px,0px,0px))。

当第二张图片的时候,ul偏移量设置( transform:translate3d(-1000px,0px,0px))。

当第二张图片的时候,ul偏移量设置( transform:translate3d(-2000px,0px,0px))。以此类推,偏移量很简单的就能计算出来!

可能我说的大家有点懵,但是,看下面的代码,就不会懵了,因为代码也很简单!

vue方
  1.    <!DOCTYPE html>

  2.    <html lang="en">

  3.    <head>

  4.        <meta charset="UTF-8">

  5.        <title>Title</title>

  6.        <link rel="stylesheet" href="reset.css">

  7.        <style>

  8.            .slide-img {

  9.                width: 1000px;

  10.                height: 500px;

  11.                overflow: hidden;

  12.                position: relative;

  13.                margin: 20px auto;

  14.            }

  15.            ul {

  16.                transition: all .5s ease;

  17.            }

  18.            li {

  19.                float: left;

  20.            }

  21.            .slide-arrow div {

  22.                width: 50px;

  23.                height: 100px;

  24.                position: absolute;

  25.                margin: auto;

  26.                top: 0;

  27.                bottom: 0;

  28.                background: url("http://i1.bvimg.com/1949/4d860a3067fab23b.jpg") no-repeat;

  29.            }

  30.            .arrow-right {

  31.                transform: rotate(180deg);

  32.                right: 0;

  33.            }

  34.            .arrow-left {

  35.                left: 0;

  36.            }

  37.            .slide-option{

  38.                position: absolute;

  39.                bottom: 10px;

  40.                width: 100%;

  41.                left: 0;

  42.                text-align: center;

  43.            }

  44.            .slide-option span{

  45.                display: inline-block;

  46.                width: 14px;

  47.                height: 14px;

  48.                border-radius: 100%;

  49.                background: #ccc;

  50.                margin: 0 10px;

  51.            }

  52.            .slide-option .active{

  53.                background: #09f;

  54.            }

  55.        </style>

  56.    </head>

  57.    <body>

  58.    <div class="slide-img clear" id="slide-img">

  59.        <!--用tran这个class控制ul是否含有过渡效果,样式已经写好-->

  60.        <ul :style="{'width':(listWidth*list.length)+'px','transform':'translate3d(-'+(listWidth*nowIndex)+'px,0,0)'}">

  61.            <!--遍历出来的图片-->

  62.            <li v-for="(li,index) in list" :style="{'width':listWidth+'px'}">

  63.                <a href="javascript:;">

  64.                    <img :src="li" class="slider-img"/>

  65.                </a>

  66.            </li>

  67.        </ul>

  68.        <div class="slide-option">

  69.            <span v-for="(li,index) in list" :class="{'active':index===nowIndex}"></span>

  70.        </div>

  71.        <div class="slide-arrow">

  72.            <div class="arrow-left" @click.stop="switchDo('reduce')"></div>

  73.            <div class="arrow-right" @click.stop="switchDo"></div>

  74.        </div>

  75.    </div>

  76.    </body>

  77.    <script src="vue.min.js"></script>

  78.    <script type="text/javascript">

  79.        new Vue({

  80.            el: '#slide-img',

  81.            data: {

  82.                nowIndex: 0,

  83.                listWidth: '1000',

  84.                list: ['./images/timg1.jpg', './images/timg2.jpg', './images/timg3.jpg', './images/timg4.jpg'],

  85.                timer:null

  86.            },

  87.            methods: {

  88.                //滑动操作

  89.                switchDo(reduce){

  90.                    clearInterval(this.timer);

  91.                    //根据reduce判断this.nowIndex的增加或者减少!

  92.                    if(reduce==='reduce'){

  93.                        //如果是第一张,就返回最后一张

  94.                        if(this.nowIndex===0){

  95.                            this.nowIndex=this.list.length-1;

  96.                        }

  97.                        else{

  98.                            this.nowIndex--;

  99.                        }

  100.                    }

  101.                    else{

  102.                        //如果是最后一张,就返回第一张

  103.                        if(this.nowIndex===this.list.length-1){

  104.                            this.nowIndex=0;

  105.                        }

  106.                        else{

  107.                            this.nowIndex++;

  108.                        }

  109.                    }

  110.                    var _this=this;

  111.                    this.timer=setInterval(function () {

  112.                        _this.switchDo();

  113.                    },4000)

  114.                },

  115.            },

  116.            mounted(){

  117.                var _this=this;

  118.                this.timer=setInterval(function () {

  119.                    _this.switchDo();

  120.                },4000)

  121.            }

  122.        })

  123.    </script>

  124.    </html>

javascript方式
  1.    <!DOCTYPE html>

  2.    <html lang="en">

  3.    <head>

  4.        <meta charset="UTF-8">

  5.        <title>Title</title>

  6.        <link rel="stylesheet" href="reset.css">

  7.        <style>

  8.            .slide-img {

  9.                width: 1000px;

  10.                height: 500px;

  11.                overflow: hidden;

  12.                position: relative;

  13.                margin: 20px auto;

  14.            }

  15.            ul {

  16.                transition: all .5s ease;

  17.            }

  18.            li {

  19.                float: left;

  20.            }

  21.            .slide-arrow div {

  22.                width: 50px;

  23.                height: 100px;

  24.                position: absolute;

  25.                margin: auto;

  26.                top: 0;

  27.                bottom: 0;

  28.                background: url("http://i1.bvimg.com/1949/4d860a3067fab23b.jpg") no-repeat;

  29.            }

  30.            .arrow-right {

  31.                transform: rotate(180deg);

  32.                right: 0;

  33.            }

  34.            .arrow-left {

  35.                left: 0;

  36.            }

  37.            .slide-option{

  38.                position: absolute;

  39.                bottom: 10px;

  40.                width: 100%;

  41.                left: 0;

  42.                text-align: center;

  43.            }

  44.            .slide-option span{

  45.                display: inline-block;

  46.                width: 14px;

  47.                height: 14px;

  48.                border-radius: 100%;

  49.                background: #ccc;

  50.                margin: 0 10px;

  51.            }

  52.            .slide-option .active{

  53.                background: #09f;

  54.            }

  55.        </style>

  56.    </head>

  57.    <body>

  58.    <div class="slide-img clear" id="slide-img">

  59.        <!--用tran这个class控制ul是否含有过渡效果,样式已经写好-->

  60.        <ul id="slide-img-ul">

  61.            <!--遍历出来的图片-->

  62.            <li style="width: 1000px;"><a href="javascript:;"><img src="images/timg1.jpg" class="slider-img"/></a></li>

  63.            <li style="width: 1000px;"><a href="javascript:;"><img src="images/timg2.jpg" class="slider-img"/></a></li>

  64.            <li style="width: 1000px;"><a href="javascript:;"><img src="images/timg3.jpg" class="slider-img"/></a></li>

  65.            <li style="width: 1000px;"><a href="javascript:;"><img src="images/timg4.jpg" class="slider-img"/></a></li>

  66.        </ul>

  67.        <div class="slide-option">

  68.            <span></span>

  69.            <span></span>

  70.            <span></span>

  71.            <span></span>

  72.        </div>

  73.        <div class="slide-arrow">

  74.            <div class="arrow-left"></div>

  75.            <div class="arrow-right"></div>

  76.        </div>

  77.    </div>

  78.    </body>

  79.    <script type="text/javascript">

  80.        window.onload=function () {

  81.            var oUl=document.querySelector('#slide-img-ul');

  82.            var oLi=oUl.querySelectorAll('li');

  83.            var oSpan=document.querySelector('.slide-option').querySelectorAll('span');

  84.            var oArrowLeft=document.querySelector('.arrow-left');

  85.            var oArrowRight=document.querySelector('.arrow-right');

  86.            oUl.style.width='4000px';

  87.            oArrowLeft.addEventListener('click',function () {

  88.                switchDo('reduce');

  89.            })

  90.            oArrowRight.addEventListener('click',function () {

  91.                switchDo();

  92.            })

  93.            var timer=null,nowIndex=0;

  94.            function switchDo(reduce){

  95.                clearInterval(timer);

  96.                //设置样式

  97.                oUl.style.transform='translate3d(-'+(1000*nowIndex)+'px,0,0)';

  98.                for (var i=0;i<oSpan.length;i++){

  99.                    if(i===nowIndex){

  100.                        oSpan[i].className='active';

  101.                    }

  102.                    else{

  103.                        oSpan[i].className='';

  104.                    }

  105.                }

  106.                //根据reduce判断this.nowIndex的增加或者减少!

  107.                if(reduce==='reduce'){

  108.                    //如果是第一张,就返回最后一张

  109.                    if(nowIndex===0){

  110.                        nowIndex=oLi.length-1;

  111.                    }

  112.                    else{

  113.                        nowIndex--;

  114.                    }

  115.                }

  116.                else{

  117.                    //如果是最后一张,就返回第一张

  118.                    if(nowIndex===oLi.length-1){

  119.                        nowIndex=0;

  120.                    }

  121.                    else{

  122.                        nowIndex++;

  123.                    }

  124.                }

  125.                timer=setInterval(function () {

  126.                    switchDo();

  127.                },4000)

  128.            }

  129.            switchDo();

  130.        }

  131.    </script>

  132.    </html>

5.小结

好了,关于 vue+ css3开发的特效,以及和 javascript+ css3的对比,就说到这里了,希望这三个小实例,能帮到大家了解下应该怎么使用 vue+ css3开发特效的。今天讲这三个小实例不是说给大家代码,让大家复制粘贴使用,而是希望能起到一个抛砖引玉的作用,拓展思维的作用!就像我之前写文章说得那样,我写文章是希望能起到一个授人以渔的作用,而不是授人以鱼!最后,如果大家觉得有什么地方我写错了,写错不好,或者有其它什么建议,欢迎指出!让大家相互学习,共同进步!


觉得本文对你有帮助?请分享给更多人