首页前端开发其他前端知识使用单个dom元素添加动画的方法教程

使用单个dom元素添加动画的方法教程

时间2024-03-26 11:08:03发布访客分类其他前端知识浏览331
导读:这篇文章给大家分享的是“使用单个dom元素添加动画的方法教程”,文中的讲解内容简单清晰,对大家学习和理解有一定的参考价值和帮助,有这方面学习需要的朋友,接下来就跟随小编一起学习一下“使用单个dom元素添加动画的方法教程”吧。...
这篇文章给大家分享的是“使用单个dom元素添加动画的方法教程”,文中的讲解内容简单清晰,对大家学习和理解有一定的参考价值和帮助,有这方面学习需要的朋友,接下来就跟随小编一起学习一下“使用单个dom元素添加动画的方法教程”吧。


DOM动画效果

  1. 让一个元素从左至右进行运动
    div id="box">
    /div>
    
    var box = document.getElementById("box");
    
    var t = null;

    t = setInterval(function(){

        
    }
)

运动的终止条件

t = setInterval(function(){ 终止条件} )

    // 元素的属性值 === 目标点
    if(dom.attr === target){
    
        clearInterval(t);

    }
    

运动的三要素

  • 起始点

一个运动的起始点其实就是当前元素的位置,我们通过API获取当前元素的位置,让这个位置作为运动的起始。

  • 目标

  • 速度

运动的底层原理

  • 让元素通过定时器在很短的间隔内进行CSS属性值的改变
  • 这样连续的运动在用户看来就是动画效果

DOM动画效果封装

封装的主要作用就是让元素可以在短时间间隔内不断改变属性实现动画效果

单属性运动框架:

button id="btn">
    开始运动/button>
    
div id="box">
    /div>
    
div id="line">
    /div>
    
script>
    
    var  box = document.getElementById("box");
    
    var  btn = document.getElementById("btn");
    
    var  target = 500;
    
    // 速度可以根据 起始点和目标点进行判断,从而决定正负;
     
    var speed  = 17;
    
    // - 方向;
 
    btn.onclick = function(){
    
        // 1. 获取元素初始位置;
    
        var _left = box.offsetLeft;
    
        speed  = target - _left >
    = 0 ? speed : -speed ;

        var interval = setInterval( function(){
    
            // 4. 判定运动的终止条件;
 
            if(Math.abs(target - _left) = Math.abs(speed) ){
    
                // 因为终止时有可能没有到达目标点,因此我们把元素赋值到目标点位置;
     
                box.style.left = target + "px";
    
                clearInterval( interval );

            }
else{
    
                // 2. 元素根据初始位置进行改变;
     
                _left += speed;
    
                // 3. DOM操作,根据已有数据让元素属性发生改变;
     
                box.style.left = _left + "px";

            }

        }
 , 30)
    }
    
    /script>
    
  • 匀速运动封装
script>
    // - 提取属性名作为参数;
 btn.onclick = function(){

    animate( "left", 500 )}
function animate( attr , target , speed = 10 ){
    
    // 1. 获取元素初始样式
    var _style = getComputedStyle( box );
    
    // 2. 根据属性要求取出当前的属性的属性值;
     
    var _css_style = parseInt(_style[attr]);
    
    speed  = target - _css_style >
    = 0 ? speed : -speed ;

    var interval = setInterval( function(){
    
        // 4. 判定运动的终止条件;
 
        if(Math.abs(target - _css_style) = Math.abs(speed) ){
    
            // 因为终止时有可能没有到达目标点,因此我们把元素赋值到目标点位置;
     
            box.style[attr] = target + "px";
    
            clearInterval( interval );

        }
else{
    
            // 2. 元素根据初始位置进行改变;
     
            _css_style += speed;
    
            // 3. DOM操作,根据已有数据让元素属性发生改变;
     
            box.style[attr] = _css_style + "px";

        }

    }
 , 30)}
    /script>
    
  • 兼容透明度
script>
function animate( dom , attr , target , speed = 10 ){
    
    // 1. 获取元素初始样式
    var _style = getComputedStyle( dom );
    
    // 2. 根据属性要求取出当前的属性的属性值;
 
    if( attr === "opacity"){
    
        var _css_style = parseInt(_style[attr] * 100 );
    
        target *= 100;

    }
else{
    
        var _css_style = parseInt(_style[attr]);

    }
    
    speed  = target - _css_style >
    = 0 ? speed : -speed ;

    var interval = setInterval( function(){
    
        // 4. 判定运动的终止条件;
 
        if(Math.abs(target - _css_style) = Math.abs(speed) ){
    
            // 因为终止时有可能没有到达目标点,因此我们把元素赋值到目标点位置;
 
            if( attr === "opacity"){
    
                dom.style[attr] = target / 100;

            }
else{
    
                dom.style[attr] = target + "px";

            }
    
            clearInterval( interval );

        }
else{
    
            // 2. 元素根据初始位置进行改变;
     
            _css_style += speed;
    
            // 3. DOM操作,根据已有数据让元素属性发生改变;
 
            if( attr === "opacity"){
    
                dom.style[attr] = _css_style / 100 ;

            }
else{
    
                dom.style[attr] = _css_style + "px";

            }

        }

    }
 , 30)}
    /script>
    
  • 缓冲运动
    • 缓冲运动是一种运动方式
    • 这种运动方式是速度在运动过程中会有改变的运动
    • 距离越小 速度越小
button id="btn">
    开始运动/button>
    
div id="box">
    /div>
    
script>
    
var  box = document.getElementById("box");
    
var  btn = document.getElementById("btn");

btn.onclick = function(){

    animate( box , "left" , 500 )
}

function animate( dom , attr , target , transition = "buffer", speed = 10 ){
    
    var _style = getComputedStyle( dom );

    if( attr === "opacity"){
    
        var _css_style = parseInt(_style[attr] * 100 );
    
        target *= 100;

    }
else{
    
        var _css_style = parseInt(_style[attr]);

    }
     
      
    if( transition === "liner"){
    
        speed  = target - _css_style >
    = 0 ? speed : -speed ;

    }

      
    var interval = setInterval( function(){

        if( transition === "buffer"){
    
            // 计算速度;
     
            speed = (target - _css_style) / 10;
    
            //速度不取整在小数部分会做很多无意义的计算;
     
            speed = speed >
 0 ? Math.ceil(speed) :Math.floor( speed )
        }


        if(Math.abs(target - _css_style) = Math.abs(speed) ){
    
            // 因为终止时有可能没有到达目标点,因此我们把元素赋值到目标点位置;
 
            if( attr === "opacity"){
    
                dom.style[attr] = target / 100;

            }
else{
    
                dom.style[attr] = target + "px";

            }
    
                clearInterval( interval );

        }
else{
    
            // 2. 元素根据初始位置进行改变;
     
            _css_style += speed;
    
            // 3. DOM操作,根据已有数据让元素属性发生改变;
 
            if( attr === "opacity"){
    
                dom.style[attr] = _css_style / 100 ;

            }
else{
    
                dom.style[attr] = _css_style + "px";

            }

        }

    }
 , 30)
}
         
/script>
    
//只需要改变里面transition的值就可以调整运动模式
//buffer为缓冲运动
//liner为匀速运动

多属性运动框架 (拓展)

  • 多属性运动框架
  • 我们在多次调用animate的时候会开启多个定时器
  • 因为定时器之中的数据都一样,我们看不出在效果上的差异
  • 但是多次开启定时器会极其严重的消耗计算机性能
  • 开启当前定时器之前关闭上一个定时器
script>
    // 在一个定时器之中,用for循环同时执行多次dom样式操作;
     // 1. 需要优化的部分:参数,要把样式部分的参数优化成一个对象;
 function animate( dom , attrs , transition = "buffer", speed = 10 ){
    
    var _style = getComputedStyle( dom );

    // 获取元素当前的属性 : 
    for(var attr in attrs ){
    
        // attr ? 要过渡的css属性名;
    
        // attrs[attr] ? 要过渡的当前属性;
 
        attrs[attr] = {
    
            target : attrs[attr],
            // 元素当前的属性放入到这个对象之中;
 
            now  : parseInt(_style[attr])
        }

    }
    
    // 因为直接关闭interval是没有作用的,此时的inteval是一个局部变量,每次animate被调用的时候都会直接重置;
     
    // 我们应该吧定时器的id放在当前正在执行过渡效果的dom对象上;
     
    clearInterval(dom.interval);

    dom.interval = setInterval( function(){

        for(var attr in attrs){
    
        // 取出 attrs 之中的目标点和当前值;
     
            speed = (attrs[attr].target -  attrs[attr].now) / 10 ;
                        
            // 根据速度正负,进行速度取整;
     
            speed = speed >
     0 ? Math.ceil( speed ) : Math.floor( speed );
    
            // 判定终止条件;
 
            if( attrs[attr].target ===  attrs[attr].now){
    
                // 删除已经到达目标点的属性;
     
                delete attrs[attr]
                // 判定attrs里面已经没有属性了;
 
                for(var a in attrs){
    
                    return false;

                }
    
                clearInterval(dom.interval);

            }
else{
    
                attrs[attr].now += speed;
    
                dom.style[ attr ] = attrs[attr].now + "px";

            }

        }

    }
 , 30)}
    // 优化参数之后,key值是等待运动的css属性,value值是元素的目标;
 btn.onclick = function(){

    animate( box , {
 width : 500 , height : 400 }
 )}
    /script>
    

轮播图功能实现

 style>

            *{
    
                  margin: 0;
    
                  padding: 0;

            }

            .container{
    
                  width: 1130px;
    
                  height: 286px;
    
                  margin: 0 auto;
    
                  position: relative;
    
                  overflow: hidden;

            }

            .wrapper{
    
                  width: 6780px;
    
                  position: absolute;
    
                  left: 0;

            }

            .slide{
    
                  float: left;

            }


            .slide , .slide img{
    
                  width: 1130px;
    
                  height: 286px;

            }

            .button-prev{
    
                  left: 0;
    
                  background-position: 30px center;
    
                  background-image: url(https://static.zcool.cn/git_z/z/widget/slider/images/svg/left_arrow.svg?v=2);
    
                  top: 0;
    
                  width: 13px;
    
                  height: 100%;
    
                  padding: 0 80px;
    
                  border-radius: 2px;
    
                  position: absolute;
    
                  background-repeat: no-repeat;

            }

            .button-prev:hover{
    
                  background-image: url(https://static.zcool.cn/git_z/z/widget/slider/images/svg/left_arrowhover.svg?v=2);

            }

            .button-next{
    
                  right: 0;
    
                  background-position: 91px center;
    
                  background-image: url(https://static.zcool.cn/git_z/z/widget/slider/images/svg/right_arrow.svg?v=2);
    
                  top: 0;
    
                  width: 13px;
    
                  height: 100%;
    
                  padding: 0 80px;
    
                  border-radius: 2px;
    
                  position: absolute;
    
                  background-repeat: no-repeat;

            }

            .button-next:hover{
    
                  background-image: url(https://static.zcool.cn/git_z/z/widget/slider/images/svg/right_arrowhover.svg?v=2);

            }

            .pagination{
    
                  position: absolute;
    
                  bottom: 10%;
    
                  width: 100%;
    
                  height: 10px;
    
                  left: 30px;

            }

            .pagination span{
    
                  display: inline-block;
    
                  width: 10px;
    
                  height: 10px;
    
                  margin-left: 10px;
    
                  border-radius: 50%;
                      
                  background-color: cornflowerblue;
    
                  border: 2px solid transparent;
    
                  background-clip: content-box;

            }

            .pagination span.active{
    
                  border: 2px solid skyblue;
    
                  box-shadow: 0 0 5px skyblue;
    
                  background-color: #fff;

            }
    
      /style>
    
!-- 类名请使用和我一样的类名 -->
    
div class="container">
    
    div class="wrapper">
    
          !-- 第0张图片 -->
    
          div class="slide">
    
                img src="https://img.zcool.cn/ad_manager/location/f35d611484931101c43350bbdbd5.jpg" alt="">
    
          /div>
    
          div class="slide">
    
                img src="https://img.zcool.cn/ad_manager/location/3dcb6113a3471101c433505bbd72.jpg" alt="">
    
          /div>
    
          div class="slide">
    
                img src="https://img.zcool.cn/ad_manager/location/65f36113a3341101c4335014b174.jpg" alt="">
    
          /div>
    
          div class="slide">
    
                img src="https://img.zcool.cn/ad_manager/location/7f97611481181101c43350225b33.jpg" alt="">
    
          /div>
    
          div class="slide">
    
                img src="https://img.zcool.cn/ad_manager/location/afcf6114801e1101c433507f9e28.jpg" alt="">
    
          /div>
    
          !-- 最后一张图片 -->
    
          !-- 把第0张图片放在整个图片结构的最后 -->
    
          div class="slide">
    
                img src="https://img.zcool.cn/ad_manager/location/f35d611484931101c43350bbdbd5.jpg" alt="">
    
          /div>
    
    /div>
    
    div class="button-next">
    /div>
    
    div class="button-prev">
    /div>
    
    div class="pagination">
    
          span class="active">
    /span>
    
          span>
    /span>
    
          span>
    /span>
    
          span>
    /span>
    
          span>
    /span>
    
    /div>
    
/div>
    

script src="./utils.js">
    /script>
    
script>
    
    // 轮播图的核心就是左右切换按钮,实现显示元素下标的改变;
     
    var index = 0 ;
     
    var prev = 0;
    

    var next_btn = document.querySelector(".button-next");
    
    var prev_btn = document.querySelector(".button-prev");
    
    var slides   = document.querySelectorAll(".slide");
    
    var wrapper  = document.querySelector(".wrapper");
    
    // 自动播放的阻止功能是在鼠标移入container容器之中就触发的;
     
    var container   = document.querySelector(".container");
    

    var bullets = document.querySelectorAll(".pagination span");
    

    // 绑定事件 
    // - 轮播图改变下标功能必须设置边界;
 
    function bindEvent(){

          next_btn.onclick = function(){
    
                add();
    
                bannerAnimate();

          }

          prev_btn.onclick = function(){
    
                reduce()
                bannerAnimate();

          }

          container.onmouseover = function(){
    
                stop();

          }

          container.onmouseout = function(){
    
                autoPlay();

          }


          bullets.forEach( function( ele , i ){


                ele.onmouseover = function(){
    
                      prev = index;
    
                      // 防止穿帮逻辑;
     
                      // - 如果在假的第0张图片上(在最后一张图片上)
                      // - 我们先让真假图片呼喊然后在进行元素的动画效果;
 
                      if( index === 5 ){
    
                            wrapper.style.left = 0;

                      }
    
                      index = i;
    
                      bannerAnimate();

                }

          }
)
    }
    
    // 下标增加;

    function add(){
    
          
          prev = index;


          if( index === slides.length - 1 ){
    
                // 这个逻辑会在最后一张图片进行切换时进入;
     
                // 我们让wrapper直接位移到开头,改变元素位置的同时让用户无法感知;
     
                wrapper.style.left = 0;
    
                // 我们需要从第0个图片切换到第一个图片;
    
                // -因为我们最后一张图片的显示和开头图片的显示是一样的
                index = 1;

          }
else{
    
                index ++;

          }

    }
    
    // 下标减少;
 
    function reduce(){
    
          prev = index;


          if( index === 0 ){
    
                wrapper.style.left = -(slides.length - 1) * 1130 + "px";
    
                index = slides.length - 2;

          }
else{
    
                index --;

          }

    }
    
    // 根据我们的算法去实现动画效果;

    function bannerAnimate(){

          animate( wrapper , {
 left : - index * 1130 }
    );
    

          // 给对应的分页器按钮添加active;
     

          // 先去清空所有的类名;
 

          bullets.forEach( function( ele ){

                ele.classList.remove("active")
          }
    )

          // 下标需要进行特殊处理,在显示最后一张图片的时候,给第0个按钮添加active;
     

          bullets[ index === 5 ? 0 : index ].classList.add("active");

    }
    
    bindEvent();
    

    var interval = null;

    function autoPlay(){
    
          // 间隔3s,让js点击一下下一页按钮;
 
          interval = setInterval( function(){
    
                // 虚拟点击 : 
                next_btn.dispatchEvent( new Event("click"));

          }
 , 3000 )
    }


    function stop(){

          clearInterval( interval )
    }
    

    autoPlay();
    

/script>

示例如下

项目背景:uniapp h5应用,为了提示用户下载,这里有个 提示下载的dom, 本想来想在 每个 tabbar 中添加(一共添加四个);但是想 尝试换种玩法 如下: 效果如下

直接上代码:

function showDownloadTisp() {
    
  console.log('--------------------------->
    showDownloadTisp')
  // #ifdef H5
  const parent = document.querySelector('.uni-tabbar')
  console.log('parent:', parent)
  const tips = document.createElement('p')
  tips.id = 'downloadTisp'


  tips.setAttribute('style',
    'background: rgba(51,51,51,0.75);
    '
  )

  tips.setAttribute('style',
    `background: rgba(51,51,51,0.75);
     position: fixed;
    width: 100%;
height: ${
uni.upx2px(120)}
    px;
 bottom:${
uni.upx2px(-140)}
    px;
      display: flex;
    flex-direction: row;
    justify-content: space-between;
    align-items:center;
    transition:0.5s;
    `
  )

  const desParent = document.createElement('p')
  const des = document.createTextNode('Download our App, you will get a better experience.')
  desParent.appendChild(des)
  desParent.setAttribute('style',
    `padding: 0;
    color: #FFFFFF;
font-size:${
uni.upx2px(24)}
    px;
margin-left: ${
uni.upx2px(27)}
    px;
padding-right: ${
uni.upx2px(25)}
    px;
`
  )

  const iosImage = document.createElement('img')
  iosImage.src = '../static/guide/download ios.png'
  iosImage.setAttribute('style',
    `width: ${
uni.upx2px(154)}
    px;
height: ${
uni.upx2px(54)}
    px;
margin-right: ${
uni.upx2px(25)}
    px;
`)

  const anroidImage = document.createElement('img')
  anroidImage.src = '../static/guide/download android.png'
  anroidImage.setAttribute('style',
    `width: ${
uni.upx2px(154)}
    px;
height: ${
uni.upx2px(54)}
    px;
margin-right: ${
uni.upx2px(50)}
    px;
`)

  const closedImage = document.createElement('img')
  closedImage.src = '../static/guide/download closd.png'
  closedImage.setAttribute('style',
    `width: ${
uni.upx2px(30)}
    px;
height: ${
uni.upx2px(30)}
    px;
    position: absolute;
right:${
uni.upx2px(15)}
    px;
top: ${
uni.upx2px(15)}
    px;
padding: ${
uni.upx2px(5)}
    ;
    `
  )

  tips.appendChild(desParent)
  tips.appendChild(iosImage)
  tips.appendChild(anroidImage)
  tips.appendChild(closedImage)


  iosImage.onclick = () =>
 {

    //console.log("iosImage.onclick")
    window.location.href = 'https://apps.apple.com/cn/app/gbm001/id1574324240'
    // window.open('https://www.baidu.com/')
  }
    

  anroidImage.onclick = () =>
 {

    //console.log("anroidImage.onclick")
    window.location.href = 'https://play.google.com/store/apps/details?id=com.vandream.gbmpro'
    // window.open('https://www.sina.com.cn/')
  }
    

  closedImage.onclick = () =>
 {

    console.log("closedImage.onclick")
    tips.remove()
  }
    


  parent.parentNode.appendChild(tips)
  //parent.appendChild(tips)


  setTimeout(() =>
 {

    tips.style.transform = `translateY(${
uni.upx2px(-140) - 50}
    px);
`
    //console.log(" tips.style.transform done")
  }
, 2500)

  // #endif
}
    

通过代码创建节点 并且代码这是 style; 以及动画;在应用启动的时候 调用就可以了;

关于 js 设置变换动画;这边改成了 3D 的形式

function showDownloadTisp() {
    
  // #ifdef H5
  const parent = document.querySelector('.uni-tabbar')
  // console.log('parent:', parent)
  const tips = document.createElement('p')
  tips.id = 'downloadTisp'

  // tips.setAttribute('style',
  //   'background: rgba(51,51,51,0.75);
    '
  // )

  // tips.setAttribute('style',
  //   `background: rgba(51,51,51,0.75);
     position: fixed;
    width: 100%;
height: ${
uni.upx2px(120)}
    px;
 bottom:${
uni.upx2px(-140)}
    px;
      display: flex;
    flex-direction: row;
    justify-content: space-between;
    align-items:center;
    transition:0.5s;
    `
  // )
  tips.setAttribute('style',
    `background: rgba(51,51,51,0.75);
     position: fixed;
    width: 100%;
height: ${
uni.upx2px(120)}
    px;
     bottom:50px;
      display: flex;
    flex-direction: row;
    justify-content: space-between;
    align-items:center;
    transition:0.5s;
     transform-origin:center bottom;
     transform:perspective(900px) rotateX(90deg);
    `
  )

  const desParent = document.createElement('p')
  const des = document.createTextNode('Download our App, you will get a better experience.')
  desParent.appendChild(des)
  desParent.setAttribute('style',
    `padding: 0;
    color: #FFFFFF;
font-size:${
uni.upx2px(24)}
    px;
margin-left: ${
uni.upx2px(27)}
    px;
padding-right: ${
uni.upx2px(10)}
    px;
`
  )

  const iosImage = document.createElement('img')
  // iosImage.src = '../static/guide/download ios.png'
  iosImage.src = 'https://img.vandream.com/54/0330f6211506cc.png'
  iosImage.setAttribute('style',
    `width: ${
uni.upx2px(154)}
    px;
height: ${
uni.upx2px(54)}
    px;
margin-right: ${
uni.upx2px(25)}
    px;
`)

  const anroidImage = document.createElement('img')
  // anroidImage.src = '../static/guide/download android.png'
  anroidImage.src = 'https://img.vandream.com/53/0330f45097465d.png'
  anroidImage.setAttribute('style',
    `width: ${
uni.upx2px(154)}
    px;
height: ${
uni.upx2px(54)}
    px;
margin-right: ${
uni.upx2px(50)}
    px;
`)

  const closedImage = document.createElement('img')
  // closedImage.src = '../static/guide/download closd.png'
  closedImage.src = 'https://img.vandream.com/52/0330f523d7709d.png'
  closedImage.setAttribute('style',
    `width: ${
uni.upx2px(30)}
    px;
height: ${
uni.upx2px(30)}
    px;
    position: absolute;
right:${
uni.upx2px(15)}
    px;
top: ${
uni.upx2px(15)}
    px;
padding: ${
uni.upx2px(5)}
    ;
    `
  )

  tips.appendChild(desParent)
  tips.appendChild(iosImage)
  tips.appendChild(anroidImage)
  tips.appendChild(closedImage)

  iosImage.onclick = () =>
 {

    console.log('iosImage.onclick')
    window.location.href = 'https://apps.apple.com/cn/app/gbm001/id1574324240'
    // window.open('https://www.baidu.com/')
  }
    

  anroidImage.onclick = () =>
 {

    console.log('anroidImage.onclick')
    window.location.href = 'https://play.google.com/store/apps/details?id=com.vandream.gbmpro'
    // window.open('https://www.sina.com.cn/')
  }
    

  closedImage.onclick = () =>
 {

    console.log('closedImage.onclick')
    tips.remove()
  }
    

  parent.parentNode.appendChild(tips)
  // parent.appendChild(tips)

  setTimeout(() =>
 {

    // tips.style.transform = `translateY(${
uni.upx2px(-140) - 50}
    px);
    `
    tips.style.transform = 'rotateX(0deg)'
    // console.log(" tips.style.transform done"):rotateX(90deg);

  }
, 2500)

  // #endif
}
    



到此这篇关于“使用单个dom元素添加动画的方法教程”的文章就介绍到这了,感谢各位的阅读,更多相关使用单个dom元素添加动画的方法教程内容,欢迎关注网络资讯频道,小编将为大家输出更多高质量的实用文章!

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

javascript

若转载请注明出处: 使用单个dom元素添加动画的方法教程
本文地址: https://pptw.com/jishu/653459.html
PHP中函数漏洞你了解多少? JavaScript如何使用localStorage存储数据的呢?

游客 回复需填写必要信息