使用vue3.0实现一些动画效果

一,

动画效果:

1,横屏滚动

2,根据横屏滚动的距离,左侧文本缩小放大

3,鼠标悬浮单张图片时根据悬浮位置发生倾斜效果

横屏滚动函数:

 function handlerMouserScroll(event) { //鼠标滑动list横屏滑动效果
        //获取滚轮跨距,兼容获取方式
        let detail = event.wheelDelta || -event.detail || event.wheelDeltaY
        // console.log('detail:'+detail)
        /*反向*/
        let moveForwardStep = -1
        /*正向*/
        let moveBackStep = 1
        let step = 0
        //如果跨步大于0,表明正向跨步,将跨步放大100倍,改变滑动速度,如果跨步小于0,表明反向跨步,将跨步放大500倍,改变滑动速度
        step = detail > 0 ? moveForwardStep * 30 : moveBackStep * 30
        // console.log('step:'+step)
        /*覆盖当前滚动条的位置,单位是像素,叠增或剃减*/
        roadMap.value.scrollLeft = roadMap.value.scrollLeft + step
        // console.log('roadMap.value.scrollLeft:'+roadMap.value.scrollLeft)
 
        //平滑值(越小越慢,不能小于等于0)
        let slipNum = 0.8
        //末尾值(越小,则越平稳,越大越仓促)
        let endNum = 1
        /*递减步伐值*/
        let decreasingPaceNum = step
        /*速度*/
        let paceNum=20;
 
        /*效果一*/
        let t1 = setInterval(() => {
          if (Math.abs(decreasingPaceNum) < endNum) {
            clearInterval(t1)
            console.log(roadMap.value.scrollLeft);
            // if(roadMap.value.scrollLeft>350){
            //   goHideTrue.value = true;
            // }else{
            //   goHideTrue.value = false;
            // }
            return
          }
          decreasingPaceNum = decreasingPaceNum * slipNum
          roadMap.value.scrollLeft = roadMap.value.scrollLeft + decreasingPaceNum
          textOpacity.value =1- roadMap.value.scrollLeft/500*0.7;
          textScale.value = 1 - roadMap.value.scrollLeft/500*0.25;
          
        }, paceNum)
      }

其中在这个函数中下面两句代码实现左侧文本的透明度及大小的变化

 textOpacity.value =1- roadMap.value.scrollLeft/500*0.7;

 textScale.value = 1 - roadMap.value.scrollLeft/500*0.25;

抖动效果函数:

 function shake(event) {  //鼠标悬浮抖动效果
        event.stopPropagation();
        let x=0;
        let y=0;
        let width = event.currentTarget.offsetWidth;
        let height =event.currentTarget.offsetHeight;
        if (event.offsetX || event.offsetY) {  //适用非Mozilla浏览器
          x = event.offsetX;
          y = event.offsetY;
        } else if (event.layerX || event.layerY) {  //兼容Mozilla浏览器
          x = event.layerX;
          y = event.layerY;
        }
        if(x height/2){
          //左下
          event.currentTarget.animate({
            transform: "perspective(1000px) rotateX(5deg) rotateY(5deg) scale3d(1, 1, 1)"
          },800)
        }else if(x  width/2 && ywidth/2 && y==height/2){
          //右中
          event.currentTarget.animate({
            transform: "perspective(1000px) rotateX(0deg) rotateY(-5deg) scale3d(1, 1, 1)"
          },800)
        }else if(x>width/2 && y>height/2){
          // 右下
          event.currentTarget.animate({
            transform: "perspective(1000px) rotateX(5deg) rotateY(-5deg) scale3d(1, 1, 1)"
          },800)
        }else if(x==width/2 && y>height/2){
          //下中
          event.currentTarget.animate({
            transform: "perspective(1000px) rotateX(5deg) rotateY(0deg) scale3d(1, 1, 1)"
          },800)
        }
        // console.log('width:'+width+'height:'+height+'X:'+x+'Y:'+y);
      }

组件完整代码:



  

二,

动画效果:两边图像根据中间元素的拖拽位置展示

首先左右两张图片元素的定位,

右边图片采用img标签,平铺整个盒子‘mbp4img’,左侧图片以背景图的形式放入div盒子,方便改变左侧盒子的宽度以此实现左侧图片展示部分图像

 
.mbp4img{
    display: inline-block;
    margin-top: 2rem;
    position: relative;
    overflow: hidden;
    border-radius: 38px;
  }
  .mbp4img .imgLeft{
    width: 50%;
    height: 100%;
    background: url('../../assets/MB/p42.png') no-repeat top left;
    position: absolute;
    top:0;
    left: 0;
  }
  .line{
    width: 4px;
    height:100%;
    background-color: #ff8a00;
    border: 1px solid #a96a1e;
    position: absolute;
    top:0;
    left: 50%;
  }
  .line .round{
    width: 48px;
    height: 48px;
    border-radius: 30px;
    background-color: #0e0d0d;
    border: 6px solid #ff8a00;
    position: absolute;
    top:50%;
    left:50%;
    transform: translate(-50%,-50%);
  }
  .line .round img{
    position: absolute;
    top:50%;
    transform: translate(0,-50%);
  }
  .line .round .goleft{
    left:4px;
  }
  .line .round .goright{
    right:4px;
  }

实现拖拽中间元素改变左边图片展示大小函数:

function goLeft(e) {
      console.log(111111)
      let disX = e.clientX - line.value.offsetLeft;
      document.onmousemove = e => {
        //用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
        let left = e.clientX - disX;
        if(left >=0 && left <=999){
          //移动当前元素
          line.value.style.left = left + "px";
          imgLeft.value.style.width = left + "px";
          if(left <=20){
            line.value.style.left = 0 + "px";
            imgLeft.value.style.width = 0 + "px";
          }
          if(left >=980){
            line.value.style.left = 998 + "px";
            imgLeft.value.style.width = 998 + "px";
          }
         
        }
        
      };
      document.onmouseup = e => {
        //鼠标弹起来的时候不再移动
        document.onmousemove = null;
        //预防鼠标弹起来后还会循环(即预防鼠标放上去的时候还会移动)  
        document.onmouseup = null;
      };
    }

组件完整代码:





三,

动画效果:

1,鼠标在两侧元素区域滑动,两侧元素滑动到中心位置,同时中心位置文案缩小隐藏

2,元素到达中心位置后形成前后关系的图片列表,并且向下滑动鼠标,图片逐渐向下隐藏,后一张图片向前来到第一张的位置,隐藏图片添加到列表最后

3,向上滑动鼠标,列表变成两张图片向两侧分开,并逐渐放大显示中间文案

文档结构:默认隐藏中间的图片列表,显示中间文案及左右图片

NEWS

MetaOil is an innovative platform that provides Web3 business
solutions for the oil and gas industry on the one hand, and an
immersive experience for users on the other, building a new
world where the energy industry meets the digital economy

{{item.title}}

{{leftObj.obj.title}}

{{rightObj.obj.title}}

实现:首先使用css3动画写出中间文字缩小隐藏,左右图片向中间滑动重叠的效果

.Map7Zoom1 { 
  animation: Map7Zoom1 2s linear 1 forwards;
  }
  @keyframes Map7Zoom1 {
    from {
      transform: scale(1);
    }
    to {
      transform: scale(0);
    }
  }
  .Map7Zoom2 {
  animation: Map7Zoom2 2s linear 1 forwards;
  }
  @keyframes Map7Zoom2 {
    from {
      left:-643px;
      opacity: 1;
      transform: scale(1) translate(0,-50%);
    }
    to {
      left: 237px;
      opacity: 0.9;
      transform: scale(0.95) translate(0,-59%);
    }
  }
  .Map7Zoom3 {
  animation: Map7Zoom3 2s linear 1 forwards;
  }

使用js函数控制动画执行时间,p7AniGo为true时动画执行,左右及中间动画执行结束隐藏之前的左右两端图片显示我们之前隐藏的图片列表

 function RLscroll(event){
          event.stopPropagation();
          let detail = event.wheelDelta || -event.detail || event.wheelDeltaY
          if(detail<0 ){
            p7AniGo.value = true;  
            setTimeout(function(){
              imgsListShow.value =true;

            },2000)
          }
        }

中间图片列表实现鼠标下滑,第一张图片下滑并更新列表的操作

第一张图片下滑之后从图片列表数组中删除(因为dom的渲染机制,数组的最后一个元素在页面最前面所以用pop(),我们获取到图片数组的时候需要先对数组进行翻转,这样数组的最后一位就是原数据的第一位了),删除之后使用unshift将删除的数据放在数组的第一位,这样是实现了数组的更新

然后更新页面列表元素的key值,实现页面的重新渲染

 Map7list.arr.pop();
 Map7list.arr.unshift(lastItem);
 key.value = key.value + 1;

 function scrollBottom(event){
        //获取滚轮跨距,兼容获取方式
        event.stopPropagation();
        emit('bottomIsShow', { data: false })
          let detail = event.wheelDelta || -event.detail || event.wheelDeltaY
          if(detail>0){
            p7AniGo.value =false;
            imgsListShow.value =false;
          }else if(flag){
            flag = false;
            map7Item.value[Map7list.arr.length-1].animate({
              top: 750 +'px'
            },1000)
            var timer1 = setTimeout(() => {
              clearTimeout(timer1);
              var lastItem =Map7list.arr[Map7list.arr.length-1];
              Map7list.arr.pop();
              Map7list.arr.unshift(lastItem);
              key.value = key.value + 1;
              flag = true
            }, 1000);
          }
        
        }

上完整组件代码:


    
    
      

4,

动画效果:向下滑动鼠标,外圈正向旋转,内里图标反向旋转,向上滑动鼠标,大圈反向旋转,内里小图标正向旋转

先上文档结构:

 css样式,/*no*/不会默认吧px单位改为rem,因为rem计算后的定位在不同分辨率的屏幕下无法做到准确定位,(因为宽高比的不同,rem针对宽做计算)

.MAP4 .p4Con .leftImg{
    width: 49.72%;
    height: 100%;
    display: flex;
    align-items: center;
  }
  .MAP4 .p4Con .leftImg .imgbox{
    width: 467px;/*no*/
    height: 467px;/*no*/
    position: relative;
    margin-left: 12.15%;
    margin-top: 80px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .MAP4 .p4Con .leftImg .imgbox .imgborder{
    width: 467px;/*no*/
    height: 467px;/*no*/
    position: relative;
    transform:rotate(0deg);
  }
  .MAP4 .p4Con .leftImg .imgbox .p4icon{
    position: absolute;
    /* top:50%;
    left: 50%;
    transform: translate(-52%,-51%); */
  }
  .MAP4 .p4Con .leftImg .imgbox .imgborder img{
    position: absolute;
  }
  .MAP4 .p4Con .leftImg .imgbox .imgborder img:first-child{
    width: 467px; /*no*/
    height: 467px; /*no*/
    top:0;
    left: 0;
  }
  .MAP4 .p4Con .leftImg .imgbox .imgborder img:nth-child(2){
    top: 16px; /*no*/
    left: 203px; /*no*/
    transform:rotate(0deg);
    /* transform: translate(-50%,0); */
  }
  .MAP4 .p4Con .leftImg .imgbox .imgborder img:nth-child(3){
    top: 312px; /*no*/
    right: 48px; /*no*/
    transform:rotate(0deg);
  }
  .MAP4 .p4Con .leftImg .imgbox .imgborder img:nth-child(4){
    top:315px; /*no*/
    left:51px; /*no*/
    transform:rotate(0deg);
    /* transform: translate(0,-40%); */
  }

js部分

 getDeg计算当前元素以旋转的度数,detail判断鼠标滑动的方向,大于0向上滑动,小于0向下滑动

 let flag = true;
      function wheelScrollRotate(){
        event.stopPropagation();
        let detail = event.wheelDelta || -event.detail || event.wheelDeltaY 
        if(!flag){
          return
        }
        let angle = getDeg();
        // console.log(angle);
        flag = false
        if(detail<0){  //大于0向上,小于0向下
          let degree = 0;
          var timer1 = setInterval(() =>{
            if(degree>=119){
              flag = true
              clearInterval(timer1);
            }
            degree += 1;
            rotateStyle1.obj.transform = `rotate(${angle+degree}deg)`;
            rotateStyle2.obj.transform = `rotate(${-angle-degree}deg)`;
          }, 2);
        }else{
          let degree = 0;
          var timer1 = setInterval(() =>{
            if(degree>=119){
              flag = true
              clearInterval(timer1);
            }
            degree += 1;
            rotateStyle1.obj.transform = `rotate(${angle-degree}deg)`;
            rotateStyle2.obj.transform = `rotate(${-angle+degree}deg)`;
          }, 2);
        }
       
      }
      function getDeg(){
        var el = document.getElementById("rotateBox");
        var st = window.getComputedStyle(el, null);
        var tr = st.getPropertyValue("-webkit-transform") ||
          st.getPropertyValue("-moz-transform") ||
          st.getPropertyValue("-ms-transform") ||
          st.getPropertyValue("-o-transform") ||
          st.getPropertyValue("transform") ||
           "FAIL";
      var values = tr.split('(')[1].split(')')[0].split(',');
      var a = values[0];
      var b = values[1];
      var c = values[2];
      var d = values[3];
      var scale = Math.sqrt(a * a + b * b);
      var sin = b / scale;
      var angle = Math.round(Math.atan2(b, a) * (180 / Math.PI));
      return angle
      }

完整的组件代码:



  

5,

纯纯的css3动画,元素的浮动,背景图和眼睛图的放大效果

眼镜图的放大效果,之所以用背景图,因为发现img标签在vue3.0的项目下无法放大到超出屏幕宽高

.MB1ani {
  animation: MB1ani 1.5s linear 1 forwards;
  }
  @keyframes MB1ani {
    0% {
      background-size: 1440px 900px;
      background-position:50% 30%;
    }
    100% {
      background-size: 4320px 5400px;
      background-position:50% 28%;
      display: none;
    }
  }

蓝色背景图的放大

.MB1Animation2 {
  animation: MB1Animation2 0.3s linear 1 forwards;
  }
  @keyframes MB1Animation2 {
    0% {
      width: 1008px;
      height: 441px;
      top:135px;
      left:216px;
    }
    100% {
      width: 100%;
      height: 100%;
      left:0px;
      top:55px;
    }
  }

文字的向上效果

.MB1Animation4 {
  animation: MB1Animation4 1s linear 1 forwards;
  }
  @keyframes MB1Animation4 {
    0% {
      top: 464px;
    }
    100% {
      top: -200px;
    }
  }

元素的悬浮效果

.MB1Animation5 {
  animation: MB1Animation5 2.5s linear infinite;
  }
  @keyframes MB1Animation5 {
    0% {
      top: 155px;
      left: 140px;
    }
    50% {
      top: 163px;
      left: 155px;
    }
    100% {
      top: 155px;
      left: 140px;
    }
  }

完整组件代码:





你可能感兴趣的:(自定义效果插件,前端,vue.js)