网站建设管理工作小结,邯郸网站seo,郑州餐饮网站建设公司排名,建网站的软件优帮云在移动端#xff0c;如果你使用过 overflow: scroll 生成一个滚动容器#xff0c;会发现它的滚动是比较卡顿#xff0c;呆滞的。为什么会出现这种情况呢#xff1f;
因为我们早已习惯了目前的主流操作系统和浏览器视窗的滚动体验#xff0c;比如滚动到边缘会有回弹#…在移动端如果你使用过 overflow: scroll 生成一个滚动容器会发现它的滚动是比较卡顿呆滞的。为什么会出现这种情况呢
因为我们早已习惯了目前的主流操作系统和浏览器视窗的滚动体验比如滚动到边缘会有回弹手指停止滑动以后还会按惯性继续滚动一会手指快速滑动时页面也会快速滚动。而这种原生滚动容器却没有就会让人感到卡顿。
首先让我们来看一下它是怎样让滚动更流畅的吧。
htmlheadmeta charsetUTF-8 /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/title/headbodydiv idapp/divtemplate idtpldivclasswrapperrefwrappertouchstart.preventonStarttouchmove.preventonMovetouchend.preventonEndtouchcancel.preventonEndmousedown.preventonStartmousemove.preventonMovemouseup.preventonEndmousecancel.preventonEndmouseleave.preventonEndtransitionendonTransitionEndul classlist refscroller :stylescrollerStyleli classlist-item v-foritem in list{{item}}/li/ul/div/templatestylebody,ul {margin: 0;padding: 0;}ul {list-style: none;}.wrapper {width: 100vw;height: 100vh;overflow: hidden;}.list {background-color: #70f3b7;}.list-item {height: 40px;line-height: 40px;width: 100%;text-align: center;border-bottom: 1px solid #ccc;}/stylescript srchttps://cdn.jsdelivr.net/npm/vue2/scriptscriptconsole.log(Vue, sss);new Vue({el: #app,template: #tpl,computed: {list() {let list [];for (let i 0; i 100; i) {list.push(i);}return list;},scrollerStyle() {return {transform: translate3d(0, ${this.offsetY}px, 0),transition-duration: ${this.duration}ms,transition-timing-function: this.bezier,};},},data() {return {minY: 0,maxY: 0,wrapperHeight: 0,duration: 0,bezier: linear,pointY: 0, // touchStart 手势 y 坐标startY: 0, // touchStart 元素 y 偏移值offsetY: 0, // 元素实时 y 偏移值startTime: 0, // 惯性滑动范围内的 startTimemomentumStartY: 0, // 惯性滑动范围内的 startYmomentumTimeThreshold: 300, // 惯性滑动的启动 时间阈值momentumYThreshold: 15, // 惯性滑动的启动 距离阈值isStarted: false, // start锁};},mounted() {this.$nextTick(() {this.wrapperHeight this.$refs.wrapper.getBoundingClientRect().height;this.minY this.wrapperHeight -this.$refs.scroller.getBoundingClientRect().height;});},methods: {onStart(e) {const point e.touches ? e.touches[0] : e;this.isStarted true;this.duration 0;this.stop();this.pointY point.pageY;this.momentumStartY this.startY this.offsetY;this.startTime new Date().getTime();},onMove(e) {if (!this.isStarted) return;const point e.touches ? e.touches[0] : e;const deltaY point.pageY - this.pointY;this.offsetY Math.round(this.startY deltaY);const now new Date().getTime();// 记录在触发惯性滑动条件下的偏移值和时间if (now - this.startTime this.momentumTimeThreshold) {this.momentumStartY this.offsetY;this.startTime now;}},onEnd(e) {if (!this.isStarted) return;this.isStarted false;if (this.isNeedReset()) return;const absDeltaY Math.abs(this.offsetY - this.momentumStartY);const duration new Date().getTime() - this.startTime;// 启动惯性滑动if (duration this.momentumTimeThreshold absDeltaY this.momentumYThreshold) {const momentum this.momentum(this.offsetY,this.momentumStartY,duration);this.offsetY Math.round(momentum.destination);this.duration momentum.duration;this.bezier momentum.bezier;}},onTransitionEnd() {this.isNeedReset();},momentum(current, start, duration) {const durationMap {noBounce: 2500,weekBounce: 800,strongBounce: 400,};const bezierMap {noBounce: cubic-bezier(.17, .89, .45, 1),weekBounce: cubic-bezier(.25, .46, .45, .94),strongBounce: cubic-bezier(.25, .46, .45, .94),};let type noBounce;// 惯性滑动加速度const deceleration 0.003;// 回弹阻力const bounceRate 10;// 强弱回弹的分割值const bounceThreshold 300;// 回弹的最大限度const maxOverflowY this.wrapperHeight / 6;let overflowY;const distance current - start;const speed (2 * Math.abs(distance)) / duration;let destination current (speed / deceleration) * (distance 0 ? -1 : 1);if (destination this.minY) {overflowY this.minY - destination;type overflowY bounceThreshold ? strongBounce : weekBounce;destination Math.max(this.minY - maxOverflowY,this.minY - overflowY / bounceRate);} else if (destination this.maxY) {overflowY destination - this.maxY;type overflowY bounceThreshold ? strongBounce : weekBounce;destination Math.min(this.maxY maxOverflowY,this.maxY overflowY / bounceRate);}return {destination,duration: durationMap[type],bezier: bezierMap[type],};},// 超出边界时需要重置位置isNeedReset() {let offsetY;if (this.offsetY this.minY) {offsetY this.minY;} else if (this.offsetY this.maxY) {offsetY this.maxY;}if (typeof offsetY ! undefined) {this.offsetY offsetY;this.duration 500;this.bezier cubic-bezier(.165, .84, .44, 1);return true;}return false;},// 停止滚动stop() {const matrix window.getComputedStyle(this.$refs.scroller).getPropertyValue(transform);this.offsetY Math.round(matrix.split())[0].split(, )[5]);},},});/script/body
/html
可以发现在增加惯性滚动边缘回弹等效果之后明显流畅、舒服了很多。那么这些效果是怎么实现的呢在用户滑动操作结束时还会继续惯性滚动一段。首先看一下源码中的函数这是 touchend 事件的处理函数也就是用户滚动操作结束时的逻辑。