您当前的位置:首页 > 计算机 > 编程开发 > Html+Div+Css(前端)

给回到顶部滚动加动画

时间:12-14来源:作者:点击数:
城东书院 www.cdsy.xyz

移动端:document.body.scrollTop

PC 端:document.documentElement.scrollTop

var GAP = 0;  //距离文档顶部距离预设,默认为0
var scrollToTop = function(scrollDuration) {
  var scrollHeight = window.pageYOffset;
  var scrollStep = Math.PI / (scrollDuration / 15);
  var cosParameter = scrollHeight / 2;
  var scrollCount = 0;
  var scrollMargin;
  var scrollPosition;

  var scrollInterval = setInterval(function() {
    if(window.pageYOffset != 0) {
      scrollCount = scrollCount + 1;
      scrollMargin = cosParameter - cosParameter * Math.cos(scrollCount * scrollStep);

      if(scrollHeight - scrollMargin > scrollPosition) {
        clearInterval(scrollInterval);
        scrollToTop(scrollDuration / scrollCount);
      }

      scrollPosition = scrollHeight - scrollMargin;

      window.scrollTo(0, (scrollPosition));
    } else {
      clearInterval(scrollInterval);
    }
  }, 15);
};

var scrollToElement = function(element, interval) {
  var offset = getElementOffset(element);   //获取到文档顶部距离
  var initialOffset = window.pageYOffset;

  var scrollHeight = offset - initialOffset;

  var scrollStep = Math.PI / (interval / 15);
  var cosParameter = scrollHeight / 2;
  var scrollCount = 0;
  var scrollMargin;
  var previousScrollMargin;
  var signChanged = false;

  var scrollInterval = setInterval(function() {
    if((window.pageYOffset < offset - GAP || window.pageYOffset > offset) && !signChanged) {
      scrollCount = scrollCount + 1;
      scrollMargin = cosParameter - cosParameter * Math.cos(scrollCount * scrollStep);

      if(previousScrollMargin) {
        signChanged = Math.abs(scrollMargin) < Math.abs(previousScrollMargin);
      }

      window.scrollTo(0, initialOffset + scrollMargin);
      previousScrollMargin = scrollMargin;
    } else {
      clearInterval(scrollInterval);
    }
  }, 15);
};

var getElementOffset = function(element) {
  return window.pageYOffset + element.getBoundingClientRect().top;
}

升级版

var GAP = 0; //距离文档顶部距离预设,默认为0
export var scrollToTop = function(scrollDuration) {
  /*
  移动端需要设置滚动条请使用
         document.body.scrollTop,
     PC上使用
         document.documentElement.scrollTop
    */
  var scrollHeight = document.body.scrollTop || document.documentElement.scrollTop;
  var scrollStep = Math.PI / (scrollDuration / 15);
  var cosParameter = scrollHeight / 2;
  var scrollCount = 0;
  var scrollMargin;
  var scrollPosition;

  var scrollInterval = setInterval(function() {
    let pageYOffset = document.body.scrollTop || document.documentElement.scrollTop;
    if(pageYOffset != 0) {
      scrollCount = scrollCount + 1;
      scrollMargin = cosParameter - cosParameter * Math.cos(scrollCount * scrollStep);

      if(scrollHeight - scrollMargin > scrollPosition) {
        clearInterval(scrollInterval);
        scrollToTop(scrollDuration / scrollCount);
      }

      scrollPosition = scrollHeight - scrollMargin;

      document.body.scrollTop = scrollPosition
      document.documentElement.scrollTop = scrollPosition;
    } else {
      clearInterval(scrollInterval);
    }
  }, 15);
};

export var scrollToElement = function(element, interval) {
  var offset = getElementOffset(element); //获取到文档顶部距离
  var initialOffset = document.body.scrollTop || document.documentElement.scrollTop;

  var scrollHeight = offset - initialOffset;

  var scrollStep = Math.PI / (interval / 15);
  var cosParameter = scrollHeight / 2;
  var scrollCount = 0;
  var scrollMargin;
  var previousScrollMargin;
  var signChanged = false;

  var scrollInterval = setInterval(function() {
    if((document.documentElement.scrollTop < offset - GAP || document.documentElement.scrollTop > offset) && !signChanged) {
      scrollCount = scrollCount + 1;
      scrollMargin = cosParameter - cosParameter * Math.cos(scrollCount * scrollStep);

      if(previousScrollMargin) {
        signChanged = Math.abs(scrollMargin) < Math.abs(previousScrollMargin);
      }

      document.body.scrollTop = initialOffset + scrollMargin;
      document.documentElement.scrollTop = initialOffset + scrollMargin;
      previousScrollMargin = scrollMargin;
    } else {
      clearInterval(scrollInterval);
    }
  }, 15);
};

var getElementOffset = function(element) {
  var initialOffset = document.body.scrollTop || document.documentElement.scrollTop;
  return initialOffset + element.getBoundingClientRect().top;
}


<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
      *{
        padding: 0px;
        margin: 0px;
        
      }
      body,html{
        height: 10000px;
      }
      #main{
        width: 100px;
        height: 100px;
        background: red;
      }
      #text{
        margin-top: 1000px;
        width: 100px;
        height: 100px;
        background: red;
      }
    </style>
    <script src="./index.js"></script>
    <script type="text/javascript">
      window.onload=function(){
        setTimeout(()=>{
                                        scrollToTop(1000);   //回到顶部
          scrollToElement(document.querySelector("#text"),5500);
        },2000)
        
      }
    </script>
  </head>
  <body>
    
    <div>
      
    </div>
    
    
    <div>
      
    </div>
  </body>
</html>

推荐用以下这个

(function(window) {
  var requestAnimFrame = (function() {
    return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) {
      window.setTimeout(callback, 1000 / 60);
    };
  })();

  var easeInOutQuad = function(t, b, c, d) {
    t /= d / 2;
    if(t < 1) return c / 2 * t * t + b;
    t--;
    return -c / 2 * (t * (t - 2) - 1) + b;
  };

  var animatedScrollTo = function(element, to, duration, callback) {
    var start = element.scrollTop,
      change = to - start,
      animationStart = +new Date();
    var animating = true;
    var lastpos = null;

    var animateScroll = function() {
      if(!animating) {
        return;
      }
      requestAnimFrame(animateScroll);
      var now = +new Date();
      var val = Math.floor(easeInOutQuad(now - animationStart, start, change, duration));
      console.log(val)
      if(lastpos) {
        if(lastpos === element.scrollTop) {
          lastpos = val;
          element.scrollTop = val;
        } else {
          animating = false;
        }
      } else {
        lastpos = val;
        element.scrollTop = val;
      }
      if(now > animationStart + duration) {
        element.scrollTop = to;
        animating = false;
        if(callback) {
          callback();
        }
      }
    };
    requestAnimFrame(animateScroll);
  };

  if(typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
    module.exports = animatedScrollTo;
  } else {
    window.animatedScrollTo = animatedScrollTo;
  }
})(window);

增加几种动画效果

var requestAnimFrame = (function() {
  return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) {
    window.setTimeout(callback, 1000 / 60);
  };
})();

var tween = {
  linear: function(t, b, c, d) {
    return c * t / d + b;
  },
  easeIn: function(t, b, c, d) {
    return c * (t /= d) * t + b;
  },
  strongEaseIn: function(t, b, c, d) {
    return c * (t /= d) * t * t * t * t + b;
  },
  strongEaseOut: function(t, b, c, d) {
    return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
  },
  sineaseIn: function(t, b, c, d) {
    return c * (t /= d) * t * t + b;
  },
  sineaseOut: function(t, b, c, d) {
    return c * ((t = t / d - 1) * t * t + 1) + b;
  },
  easeInOutQuad: function(t, b, c, d) {
    t /= d / 2;
    if(t < 1) return c / 2 * t * t + b;
    t--;
    return -c / 2 * (t * (t - 2) - 1) + b;
  }
};

export var animatedScrollTo = function(element, to, duration,callback, Bzr='linear') {
  var start = element.scrollTop,
    change = to - start,
    animationStart = +new Date();
  var animating = true;
  var lastpos = null;

  var animateScroll = function() {
    if(!animating) {
      return;
    }
    requestAnimFrame(animateScroll);
    var now = +new Date();
    var val = Math.floor(tween[Bzr](now - animationStart, start, change, duration));

    if(lastpos) {
      if(lastpos === element.scrollTop) {
        lastpos = val;
        element.scrollTop = val;
      } else {
        animating = false;
      }
    } else {
      lastpos = val;
      element.scrollTop = val;
    }
    if(now > animationStart + duration) {
      element.scrollTop = to;
      animating = false;
      if(callback) {
        callback();
      }
    }
  };
  requestAnimFrame(animateScroll);
};

增加清除定时器

var requestAnimFrame = (function() {
  return window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    function(callback) {
      window.setTimeout(callback, 1000 / 60);
    };
})();
var cancelAnimationFrame = (function() {
  return window.cancelAnimationFrame ||
    window.webkitCancelAnimationFrame ||
    window.mozCancelAnimationFrame ||
    window.oCancelAnimationFrame ||
    function(id) {
      window.clearTimeout(id)
    }
})()

var tween = {
  linear: function(t, b, c, d) {
    return c * t / d + b;
  },
  easeIn: function(t, b, c, d) {
    return c * (t /= d) * t + b;
  },
  strongEaseIn: function(t, b, c, d) {
    return c * (t /= d) * t * t * t * t + b;
  },
  strongEaseOut: function(t, b, c, d) {
    return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
  },
  sineaseIn: function(t, b, c, d) {
    return c * (t /= d) * t * t + b;
  },
  sineaseOut: function(t, b, c, d) {
    return c * ((t = t / d - 1) * t * t + 1) + b;
  },
  easeInOutQuad: function(t, b, c, d) {
    t /= d / 2;
    if(t < 1) return c / 2 * t * t + b;
    t--;
    return -c / 2 * (t * (t - 2) - 1) + b;
  }
};
var myReq; 
export var animatedScrollTo = function(element, to, duration, callback, Bzr = 'linear') {
  var start = element.scrollTop,
    change = to - start,
    animationStart = +new Date();
  var animating = true;
  var lastpos = null;

  var animateScroll = function() {
    console.log('-------------')
    if(!animating) {
      return;
    }
    myReq=requestAnimFrame(animateScroll);
    var now = +new Date();
    var val = Math.floor(tween[Bzr](now - animationStart, start, change, duration));

    if(lastpos) {
      if(lastpos === element.scrollTop) {
        lastpos = val;
        element.scrollTop = val;
      } else {
        animating = false;
      }
    } else {
      lastpos = val;
      element.scrollTop = val;
    }
    if(now > animationStart + duration) {
      element.scrollTop = to;
      animating = false;
      cancelAnimationFrame(myReq);   //清除定时器动画
      callback&&callback();
    }
  };
  myReq=requestAnimFrame(animateScroll);
};


<!DOCTYPE html>
<html>

  <head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
      * {
        padding: 0px;
        margin: 0px;
      }
      
      body,
      html {
        height: 10000px;
      }
      
      #main {
        width: 100px;
        height: 100px;
        background: red;
      }
      
      #text {
        margin-top: 1000px;
        width: 100px;
        height: 100px;
        background: red;
      }
    </style>
    <script src="animatedScrollTo.js"></script>
    <script type="text/javascript">
      window.onload = function() {

        setTimeout(() => {
          animatedScrollTo(
            document.documentElement, // element to scroll with (most of times you want to scroll with whole <body>)
            2000, // target scrollY (0 means top of the page)
            700, // duration in ms
            function() { // callback function that runs after the animation (optional)
              console.log('done!')
            }
          );
        }, 2000)

      }
    </script>
  </head>

  <body>

    <div>

    </div>

    <div>

    </div>
  </body>

</html>

Vue DEMO

<template>
  <div>
    <div class="cardList" v-for="(item,index) in lists">
      <div class="list onepx-top-border">
        <div @click="jump(item.link)" class="lg">
          <img v-if="item.poster_image" class="banner" :src="item.poster_image" />
          <img v-else class="banner" :src="bgimg" />
          <div class="min"></div>
          <div class="nu">{{index+1}}</div>
        </div>
        <div class="mvcont flex" @click.stop="jump(item.link)">
          <p class="mvnema">{{item.name}}</p>
          <p class="performer" v-if="item.actor">演员:{{item.actor}}</p>
          <p class="performer" v-else> </p>
          <div class="details">
            <img class="fire" src="../../assets/img/fire@3x.png" />
            <span class="hot">热度 {{item.hot_score}}</span>
            <span class="data" @click.stop="toggleChars(index)">数据详情</span>
            <span class="arrow" :class="{ active: showIndex==index}"></span>
          </div>
        </div>
        <div class="hband" @click="jump(item.button_info.url)">
          <div class="hit">{{item.button_info.text}}</div>
        </div>
      </div>
      <div class="datadetails" v-if="showIndex==index">
        <div class="con onepx-top-border">
          <div class="left">
            <div class="num color-636363">视频播放 排名<span class="yll">{{item.video_play.play_rank}}</span>/<span>{{item.video_play.play_total}}</span></div>
            <div class="palys flex">
              <div class="playnum">
                <div class="num" :style="{width: item.video_play.play_score+'%'}"></div>
              </div>
              <span class="color-636363">{{item.video_play.play_count}}</span>
            </div>
            <div class="num color-636363 maginTop">视频发布 排名<span class="yll">{{item.video_publish.publish_rank}}</span>/<span>{{item.video_publish.publish_total}}</span></div>
            <div class="palys flex">
              <div class="playnum">
                <div class="num" :style="{width: item.video_publish.publish_score+'%'}"></div>
              </div>
              <span class="color-636363">{{item.video_publish.publish_count}}</span>
            </div>
          </div>
          <div v-if="item.video_image" class="right" :style="{backgroundImage: 'url('+item.video_image+')'}" @click="jump(item.video_link)">
            <div class="palyicon"></div>
          </div>
          <div v-else class="right" :style="{backgroundImage: 'url('+bgimg+')'}" @click="jump(item.video_link)">
          </div>
        </div>
        <div>
          <chart :day='day(item.rank_data_day)' :week='week(item.rank_data_week)'></chart>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
  import Toast from 'mint-ui/lib/toast';
  import 'mint-ui/lib/toast/style.css';

  import Bus from "@/common/openScheme.js"
  import chart from "@/components/pm/chart.vue"
  import bgimg from "@/assets/img/none.png"
  import {animatedScrollTo} from "@/utils/scrollTo"

  export default {
    props: ['lists'],
    data() {
      return {
        bgimg: bgimg,
        showIndex: -1 //当前显示chart的card
      }
    },
    components: {
      chart
    },
    computed: {

    },
    mounted: function() {
      this.toggleChars(0);
    },
    methods: {
      getPosition(node) {
        var width = node.offsetWidth; //元素宽度
        var height = node.offsetHeight; //元素高度
        var left = node.offsetLeft; //获取元素相对于其根元素的left值var left
        var top = node.offsetTop; //获取元素相对于其根元素的top值var top
        var current = node.offsetParent; // 取得元素的offsetParent

        // 一直循环直到根元素  
        while(current != null) {  
          left += current.offsetLeft;  
          top += current.offsetTop;  
          current = current.offsetParent;  
        }
        return {
          "width": width,
          "height": height,
          "left": left,
          "top": top
        };
      },
      toggleChars(index) {
        if(this.showIndex == index) {
          this.showIndex = -1;
        } else {
          this.showIndex = -1;
          this.$nextTick(() => {
            var H=0;
            if(document.getElementsByClassName("cardList").length){
               H =this.getPosition(document.getElementsByClassName("cardList")[index]).top;
            }
            setTimeout(()=>{
              if(index==0){    //如果点击的是第一个,直接回到顶部
                H=0;
              }
              animatedScrollTo(  //移动端:document.body.scrollTop     PC端:document.documentElement.scrollTop
                document.body,H,500,function(){
                  console.log('done!');
                }
              )
              //document.body.scrollTop = H;
                    //document.documentElement.scrollTop = H;
            },0)
            
                this.showIndex = index;
          })
        }
      },
      day(data) {
        if(data) {
          let Y = data.map((item) => {
            return +item.rank_score
          });
          let X = data.map((item) => {
            let time = item.rank_time.split(" ")[1].split(":");
            return time[0] + ':' + time[1]
          });
          let Z = data.map((item) => {
            return +item.rank_rank
          });
          return {
            X,
            Y,
            Z
          }
        }
      },
      week(data) {
        if(data) {
          let Y = data.map((item) => {
            return +item.rank_score
          });
          let X = data.map((item) => {
            let time = item.rank_time.split(" ")[0].split("-");
            return time[1] + '/' + time[2]
          });
          let Z = data.map((item) => {
            return +item.rank_rank
          });
          return {
            X,
            Y,
            Z
          }
        }
      },
      jump(url) {
        Bus.$emit("openScheme", url);
        return false;
      }
    }
  }
</script>

<style lang="scss" scoped="scoped">
  .cardList {
    background: white;
    position: relative;
    .list {
      box-sizing: border-box;
      padding: .24rem .24rem;
      overflow: hidden;
      display: flex;
      justify-content: flex-start;
      align-items: center;
      .lg {
        position: relative;
        width: 1.18rem;
        height: 1.60rem;
        .banner {
          width: 1.18rem;
          height: 1.60rem;
        }
        .min {
          position: absolute;
          top: 0px;
          left: 0px;
          width: 0;
          height: 0;
          border-top: 0.5rem solid #FFD644;
          border-right: 0.5rem solid transparent;
        }
        .nu {
          position: absolute;
          font-size: 0.24rem;
          line-height: 0.28rem;
          text-align: center;
          top: 0.05rem;
          left: 0.01rem;
          width: 0.25rem;
          height: 0.25rem;
          color: black;
          transform: scale(0.9);
        }
      }
      .mvcont {
        position: relative;
        box-sizing: border-box;
        padding: 0.12rem .12rem 0rem;
        flex: 1;
        width: 100%;
        height: 1.60rem;
        margin: 0 0.05rem;
            flex-direction: column;
            flex-wrap: wrap;
        .mvnema {
          font-size: 0.32rem;
          color: #333333;
          padding-bottom: 0.05rem;
        }
        .performer {
          line-height: normal;
          font-size: 0.24rem;
          color: #636363;
          display: -webkit-box !important;
          overflow: hidden;
          text-overflow: ellipsis;
          word-break: break-all;
          -webkit-box-orient: vertical;
          -webkit-line-clamp: 1;
        }
        .details {
          font-size: 0.24rem;
          line-height: .27rem;
          color: #939393;
          align-self:flex-start;
          position: absolute;
          left: 0.12rem;
          bottom: 0.12rem;
          .fire {
            width: 0.2rem;
            margin-top: -0.05rem;
            vertical-align: middle;
          }
          .hot {
            display: inline-block;
            line-height: 1;
            line-height: normal;
          }
          .data {
            line-height: 1;
            display: inline-block;
            margin-left: 0.3rem;
            color: #FF8200;
            line-height: normal;
          }
          .arrow {
            display: inline-block;
            width: 0.2rem;
            height: 0.2rem;
            background-image: url("../../assets/img/jiantou.svg");
            background-repeat: no-repeat;
            background-size: 0.2rem 0.2rem;
            transition: -webkit-transform .2s ease-in-out;
            &.active {
              transform: rotate(180deg);
            }
          }
        }
      }
      .hband {
        background: #FF8200;
        border-radius: 0.04rem;
        width: 1.28rem;
        height: .58rem;
        line-height: .68rem;
        text-align: center;
        .hit {
          font-size: 0.28rem;
          color: #FFFFFF;
          letter-spacing: 0;
        }
      }
    }
    .datadetails {
      width: 100%;
      .con {
        position: relative;
        margin: 0rem .24rem;
        padding-top: 0.24rem;
        padding-bottom: 0.24rem;
        display: flex;
        justify-content: flex-start;
        align-items: center;
        .left {
          height: 1.46rem;
          flex: 1;
          font-size: 0.24rem;
          color: #636363;
          line-height: 0.24rem;
          .color-636363 {
            color: #636363;
            .yll {
              color: #ffa74b;
            }
            &.maginTop {
              margin-top: 0.3rem;
            }
          }
          .palys {
            margin: 0.1rem 0rem 0.1rem 0rem;
            vertical-align: middle;
            align-items: center;
            .playnum {
              width: 3rem;
              height: .24rem;
              background: #E4E4E4;
              display: inline-block;
              position: relative;
              .num {
                position: absolute;
                top: 0rem;
                left: 0rem;
                width: 0%;
                height: 100%;
                background: #FF8200;
              }
            }
            span {
              display: inline-block;
              margin-left: 0.1rem;
              height: .24rem;
              line-height: .24rem;
            }
          }
        }
        .right {
          display: block;
          width: 2.6rem;
          height: 1.46rem;
          background-image: url('https://wx1.sinaimg.cn/large/60ca8a58ly1fkrxoeljr3j21hc0m6go8.jpg');
          background-size: 100% 100%;
          position: relative;
          .palyicon {
            width: .64rem;
            height: .64rem;
            border: 1px solid white;
            border-radius: 50%;
            position: absolute;
            top: 50%;
            left: 50%;
            margin-left: -.32rem;
            margin-top: -.32rem;
            &::after {
              content: "";
              position: absolute;
              top: 50%;
              left: 50%;
              margin-left: -0.10rem;
              margin-top: -0.18rem;
              width: 0px;
              height: 0px;
              border-top: 0.18rem solid transparent;
              border-left: 0.24rem solid white;
              border-bottom: 0.18rem solid transparent;
            }
          }
        }
        .chars {
          width: 100%;
          .tit {
            height: 0.34rem;
            width: 100%;
            font-size: 0.24rem;
            .trend {
              float: left;
              color: #636363;
            }
            .time1,
            .time2 {
              color: white;
              width: 1.07rem;
              height: .33rem;
              line-height: .33rem;
              text-align: center;
              background: #bdbdbd;
              border-radius: 0.34rem;
              float: right;
              div {
                font-size: 0.24rem;
                width: 100%;
                height: 100%;
                transform: scale(0.7);
              }
              &.magr {
                margin-left: 0.15rem;
              }
              &.active {
                background: #FF8200;
              }
            }
          }
        }
        .charscon {
          width: 100%;
          height: 2rem;
          margin-top: 0.2rem;
          background: pink;
        }
      }
    }
  }
</style>
城东书院 www.cdsy.xyz
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐