how to calculate the speed when the mobile phone is inertial scrolling, and how to decrease the speed after that
because I want to be a scrolling plug-in on the mobile phone, I want to simulate the original inertia scrolling of the phone, that is, after the fingers swipe, the mobile phone page will still scroll for some distance after the fingers are lifted.
now I have tried two methods
1. When the time between finger start and end is less than 300ms, the length that needs to continue scrolling is calculated according to the finger movement distance. After end, the animation effect is achieved through transition and top
2. After finger end, the draw speed is calculated by finger movement distance and usage time. If the use time is less than 300ms, a function that decreases speed each time is called through requestAnimationFrame loop. Jump out of the function loop when the speed is very small. Set the top value every time in the function, because the requestAnimationFrame interval is very short, about 16ms after that, to achieve the effect
the first method code
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalabel=no"/>
<meta charset="utf-8"/>
<title></title>
<style>
* {
margin: 0;
padding: 0;
}
.container {
position: relative;
margin: 50px;
width: calc(100% - 100px);
height: 400px;
border: 1px solid green;
box-sizing: border-box;
overflow: hidden;
}
.container .scroll {
position: absolute;
top: 0;
left: 0;
width: 100%;
transition: all 160ms ease-out;
}
.container p {
margin: 0 auto 10px;
width: 80%;
height: 80px;
border: 1px solid yellow;
}
.container .scroll:after {
content: "";
display: block;
clear: both;
}
.container .barBox {
position: absolute;
right: 2px;
top: 2px;
width: 3px;
height: calc(100% - 4px);
background: rgba(100, 200, 100, 0.3);
}
.container .barBox .bar {
position: absolute;
top: 0;
right: 0;
height: 0;
width: 100%;
background: -sharpccc;
transition: all 160ms ease-out;
}
</style>
</head>
<body>
<div class="container" id="container">
<div class="scroll">
<p style="border-color: green;"><p style="border-color: yellow;"><p style="border-color: -sharp932132;">
<p style="border-color: -sharp00007f;"><p style="border-color: red;"><p style="border-color: -sharp432892;">
<p style="border-color: -sharp007f00;"><p style="border-color: blue;"><p style="border-color: green;">
<p style="border-color: -sharp7f0000;"><p style="border-color: -sharp003947;"><p style="border-color: -sharpcccc33;">
<p style="border-color: green;"><p style="border-color: yellow;"><p style="border-color: -sharp932132;">
<p style="border-color: -sharp00007f;"><p style="border-color: red;"><p style="border-color: -sharp432892;">
<p style="border-color: -sharp007f00;"><p style="border-color: blue;"><p style="border-color: green;">
<p style="border-color: -sharp7f0000;"><p style="border-color: -sharp003947;"><p style="border-color: -sharpcccc33;">
<p style="border-color: green;"><p style="border-color: yellow;"><p style="border-color: -sharp932132;">
<p style="border-color: -sharp00007f;"><p style="border-color: red;"><p style="border-color: -sharp432892;">
<p style="border-color: -sharp007f00;"><p style="border-color: blue;"><p style="border-color: green;">
<p style="border-color: -sharp7f0000;"><p style="border-color: -sharp003947;"><p style="border-color: -sharpcccc33;">
</div>
<div class="barBox" id="barBox">
<div class="bar"></div>
</div>
</div>
<script>
var oContainer = document.getElementById("container");
var oScroll = oContainer.children[0];
var oBarBox = document.getElementById("barBox");
var oBar = oBarBox.children[0];
//
var iWrapperH = numberPx(getStyle(oContainer, "height"));
var iScrollH = numberPx(getStyle(oScroll, "height"));
var iBarBoxH = numberPx(getStyle(oBarBox, "height"));
var iBarH = iWrapperH / iScrollH * iBarBoxH;
//
setStyle(oBar, {
height: iBarH + "px"
})
//
var startTime = 0;
var endTime = 0;
var isMove = false;
var iScrollTop = 0;
var iBarTop = 0;
var endTimeout = null;
oContainer.addEventListener("touchstart", function (e) {
startTime = new Date().getTime();
var startY = e.targetTouches[0].clientY;
var startTop = numberPx(getStyle(oScroll, "top"));
var endY = startY;
var endTop = startTop;
setStyle(oScroll, {
top: startTop + "px"
})
setStyle(oBar, {
top: -startTop / iScrollH * iBarBoxH + "px"
})
var moveFn = function (e) {
isMove = true;
var nowY = e.targetTouches[0].clientY;
var nowTop = startTop;
endY = nowY;
var moveY = nowY - startY;
nowTop += moveY;
endTop = nowTop;
iScrollTop = nowTop > 0 ? 0 : (nowTop < iWrapperH - iScrollH ? iWrapperH - iScrollH : nowTop);
iBarTop = -iScrollTop / iScrollH * iBarBoxH;
setStyle(oScroll, {
top: iScrollTop + "px"
})
setStyle(oBar, {
top: iBarTop + "px"
})
}
var endFn = function (e) {
endTime = new Date().getTime();
if ( endTime - startTime <= 200 && isMove ) {
var moveY = endY - startY;
var iScale = 1;
var iTime = 300;
if ( Math.abs(moveY) <= 100 ) {
iScale = 1;
iTime = 300;
} else if ( Math.abs(moveY) <= 200 ) {
iScale = 2;
iTime = 500;
} else {
iScale = 3;
iTime = 700;
}
moveY = moveY * iScale;
endTop += moveY;
iScrollTop = endTop > 0 ? 0 : (endTop < iWrapperH - iScrollH ? iWrapperH - iScrollH : endTop);
iBarTop = -iScrollTop / iScrollH * iBarBoxH;
setStyle(oScroll, {
transition: "all " + iTime + "ms ease-out",
top: iScrollTop + "px"
})
setStyle(oBar, {
transition: "all " + iTime + "ms ease-out",
top: iBarTop + "px"
})
clearTimeout(endTimeout);
endTimeout = setTimeout(function () {
setStyle(oScroll, {
transition: "all 160ms ease-out"
})
setStyle(oBar, {
transition: "all 160ms ease-out",
})
}, 500);
}
isMove = false;
document.documentElement.removeEventListener("touchmove", moveFn);
oContainer.removeEventListener("touchend", endFn);
}
document.documentElement.addEventListener("touchmove", moveFn);
oContainer.addEventListener("touchend", endFn);
})
function getStyle (obj, name) {
if(window.getComputedStyle) {
return getComputedStyle(obj, null)[name];
} else {
return obj.currentStyle[name];
}
}
function setStyle (obj, oStyle) {
for(var i in oStyle) {
obj.style[i] = oStyle[i];
}
}
function numberPx (num) {
return Number(num.split("px")[0]);
}
</script>
</body>
</html>
the second code
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalabel=no"/>
<meta charset="utf-8"/>
<title></title>
<style>
* {
margin: 0;
padding: 0;
}
.container {
position: relative;
margin: 50px;
width: calc(100% - 100px);
height: 400px;
border: 1px solid green;
box-sizing: border-box;
overflow: hidden;
}
.container .scroll {
position: absolute;
top: 0;
left: 0;
width: 100%;
}
.container p {
margin: 0 auto 10px;
width: 80%;
height: 80px;
border: 1px solid yellow;
}
.container .scroll:after {
content: "";
display: block;
clear: both;
}
.container .barBox {
position: absolute;
right: 2px;
top: 2px;
width: 3px;
height: calc(100% - 4px);
background: rgba(100, 200, 100, 0.3);
}
.container .barBox .bar {
position: absolute;
top: 0;
right: 0;
height: 0;
width: 100%;
background: -sharpccc;
}
</style>
</head>
<body>
<div class="container" id="container">
<div class="scroll">
<p style="border-color: green;"><p style="border-color: yellow;"><p style="border-color: -sharp932132;">
<p style="border-color: -sharp00007f;"><p style="border-color: red;"><p style="border-color: -sharp432892;">
<p style="border-color: -sharp007f00;"><p style="border-color: blue;"><p style="border-color: green;">
<p style="border-color: -sharp7f0000;"><p style="border-color: -sharp003947;"><p style="border-color: -sharpcccc33;">
<p style="border-color: green;"><p style="border-color: yellow;"><p style="border-color: -sharp932132;">
<p style="border-color: -sharp00007f;"><p style="border-color: red;"><p style="border-color: -sharp432892;">
<p style="border-color: -sharp007f00;"><p style="border-color: blue;"><p style="border-color: green;">
<p style="border-color: -sharp7f0000;"><p style="border-color: -sharp003947;"><p style="border-color: -sharpcccc33;">
<p style="border-color: green;"><p style="border-color: yellow;"><p style="border-color: -sharp932132;">
<p style="border-color: -sharp00007f;"><p style="border-color: red;"><p style="border-color: -sharp432892;">
<p style="border-color: -sharp007f00;"><p style="border-color: blue;"><p style="border-color: green;">
<p style="border-color: -sharp7f0000;"><p style="border-color: -sharp003947;"><p style="border-color: -sharpcccc33;">
</div>
<div class="barBox" id="barBox">
<div class="bar"></div>
</div>
</div>
<script>
var oContainer = document.getElementById("container");
var oScroll = oContainer.children[0];
var oBarBox = document.getElementById("barBox");
var oBar = oBarBox.children[0];
//
var iWrapperH = numberPx(getStyle(oContainer, "height"));
var iScrollH = numberPx(getStyle(oScroll, "height"));
var iBarBoxH = numberPx(getStyle(oBarBox, "height"));
var iBarH = iWrapperH / iScrollH * iBarBoxH;
//
setStyle(oBar, {
height: iBarH + "px"
})
//
var startTime = 0;
var endTime = 0;
var pastTime = 0; //
var nowTime = 0; //
var isMove = false;
var iBarTop = 0;
var timer = true;
oContainer.addEventListener("touchstart", function (e) {
startTime = new Date().getTime();
pastTime = startTime;
var startY = e.targetTouches[0].clientY;
var startTop = numberPx(getStyle(oScroll, "top"));
var endY = startY;
var endTop = startTop;
timer = false;
var moveFn = function (e) {
isMove = true;
var nowY = e.targetTouches[0].clientY;
var nowTop = startTop;
endY = nowY;
var moveY = nowY - startY;
nowTop += moveY;
endTop = nowTop = getPos(nowTop);
setStyle(oScroll, {
top: nowTop + "px"
})
setStyle(oBar, {
top: getBarTop(nowTop) + "px"
})
}
var endFn = function (e) {
endTime = new Date().getTime();
var speed = (endY - startY) / (endTime - startTime);
if ( endTime - startTime <= 300 && isMove ) {
speed *= 16;
var f = 0,
top = endTop;
timer = true;
show();
function show () {
timer && requestAnimationFrame(show);
f = Math.min(Math.abs(speed) / 10, 0.5); //
if( speed > 0.2 ) {
speed -= f
} else if(speed < -0.2){
speed += f
} else {
timer = false
speed = 0
return
}
top += speed;
if ( top > 0 || top < iWrapperH -iScrollH ) {
timer = false
speed = 0
setStyle(oScroll, {
top: getPos(top) + "px"
})
setStyle(oBar, {
top: getBarTop(getPos(top)) + "px"
})
return
}
setStyle(oScroll, {
top: top + "px"
})
setStyle(oBar, {
top: getBarTop(top) + "px"
})
}
}
isMove = false;
document.documentElement.removeEventListener("touchmove", moveFn);
document.documentElement.removeEventListener("touchend", endFn);
}
document.documentElement.addEventListener("touchmove", moveFn);
document.documentElement.addEventListener("touchend", endFn);
})
function getPos (num) {
return num >= 0 ? 0 : (num <= iWrapperH - iScrollH ? iWrapperH - iScrollH : num);
}
function getBarTop (num) {
return -num / iScrollH * iBarBoxH;
}
function getStyle (obj, name) {
if(window.getComputedStyle) {
return getComputedStyle(obj, null)[name];
} else {
return obj.currentStyle[name];
}
}
function setStyle (obj, oStyle) {
for(var i in oStyle) {
obj.style[i] = oStyle[i];
}
}
function numberPx (num) {
return Number(num.split("px")[0]);
}
</script>
</body>
</html>
you can see the original effect
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalabel=no">
<title></title>
<style>
* {
margin: 0;
padding: 0;
}
.container {
position: relative;
margin: 50px;
width: calc(100% - 100px);
height: 400px;
border: 1px solid green;
box-sizing: border-box;
overflow: auto;
}
.container p {
margin: 0 auto 10px;
width: 80%;
height: 80px;
border: 1px solid yellow;
}
</style>
</head>
<body>
<div class="container" id="container">
<div class="scroll">
<p style="border-color: green;"><p style="border-color: yellow;"><p style="border-color: -sharp932132;">
<p style="border-color: -sharp00007f;"><p style="border-color: red;"><p style="border-color: -sharp432892;">
<p style="border-color: -sharp007f00;"><p style="border-color: blue;"><p style="border-color: green;">
<p style="border-color: -sharp7f0000;"><p style="border-color: -sharp003947;"><p style="border-color: -sharpcccc33;">
<p style="border-color: green;"><p style="border-color: yellow;"><p style="border-color: -sharp932132;">
<p style="border-color: -sharp00007f;"><p style="border-color: red;"><p style="border-color: -sharp432892;">
<p style="border-color: -sharp007f00;"><p style="border-color: blue;"><p style="border-color: green;">
<p style="border-color: -sharp7f0000;"><p style="border-color: -sharp003947;"><p style="border-color: -sharpcccc33;">
<p style="border-color: green;"><p style="border-color: yellow;"><p style="border-color: -sharp932132;">
<p style="border-color: -sharp00007f;"><p style="border-color: red;"><p style="border-color: -sharp432892;">
<p style="border-color: -sharp007f00;"><p style="border-color: blue;"><p style="border-color: green;">
<p style="border-color: -sharp7f0000;"><p style="border-color: -sharp003947;"><p style="border-color: -sharpcccc33;">
</div>
</div>
</body>
</html>