移动端: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>
<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>

