Web前端最全前端页面双向滚动方案,这操作真香

结束

一次完整的面试流程就是这样啦,小编综合了腾讯的面试题做了一份前端面试题PDF文档,里面有面试题的详细解析,分享给小伙伴们,有没有需要的小伙伴们都去领取!

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

思路是对的,但是会出现强烈的闪屏现象,尤其在这种数据密集型的页面上(ios页面也闪,低端安卓机没做尝试,meta30存在一定延迟的闪屏)。

  改变方案

双向滚动到此基本上算是失败了。

单向滚动肯定没问题,另一个方向我们可以使用模拟滚动的方式来自己写一套"滚动"效果。

首先我们判断横向滚动和纵向滚动那一方向使用原生滚动呢?

我选择了纵向,纵向数据体量大,容易有滚动的诉求,横向存在数据量不足可能不需要滚动。

效果如下图所示:

左侧第一列和顶部第一行吸顶这里使用了css的属性 position:sticky。

也有人可以考虑使用一些特殊布局,例如左侧做绝对定位,右侧内容自行滚动等。

模拟滚动的方式,我们采用touch事件来仿造,通过touchStart、touchMove、touchEnd 这3个事件来模拟scroll事件。

首先在touchStart中获取手指头接触到屏幕的点的 (x,y) 坐标,然后在touchMove事件中获取屏幕出点的第二个触点的(x,y)坐标,来获取触摸方向。

//获得角度

function getAngle(angx, angy) {

return Math.atan2(angy, angx) * 180 / Math.PI;

};

function getDirection(startx, starty, endx, endy) {

const angx = endx - startx;

const angy = endy - starty;

let result = 0;

//如果滑动距离太短

if (Math.abs(angx) < 2 && Math.abs(angy) < 2) {

return result;

}

const angle = getAngle(angx, angy);

if (angle >= -150 && angle <= -30) {

return ‘top’;

} else if (angle > 30 && angle < 150) {

return ‘down’;

} else if ((angle >= 150 && angle <= 180) || (angle >= -180 && angle < -150)) {

return ‘left’;

} else if (angle >= -30 && angle <= 30) {

return ‘right’

}

}

由于大家在使用手机时,横向滑动的行为轨迹并非是一个水平180度的横线,所以在这里设定了一定值,例如多少角度到多少角度认为是横向滚动。

方向定好,多少角度这个可以根据自己业务上的判断做修改。

连续触摸滑动的坐标轴我们已经能拿到了,通过css3的transform来使元素进行移动,通过不断修改移动的值达到元素滚动的效果。

这里有一点需要注意,并非我们触摸划过多少像素,元素就移动多少像素,这里还涉及一个速度和距离的概念。

还有我们手指头松开以后,元素应该还会滚动一部分,然后速度慢慢降下来,直到0为止。

先分析一直处于触点滑动这个阶段,我们并非划过多少像素,元素就跟着滚动多少像素,这里看情况来放大或者缩小这里的滚动值,体现给用户的感受就是滑的快还是划得慢。

我们由于横向数据量并不大,所以这里我们所有滚动距离都做了一定缩小处理。

// 代码只留个框架

function rowScrollAction(scrollDirection, endx, isEnding = false) {

scrollGap = (endx - startx) * 0.85; // 每个滚动距离都乘上0.85

let scrollLen = preX + scrollGap; // preX为之触摸之前已经滚动到的位置

if (isEnding) {

scrollLen = endx

}

if (scrollDirection === ‘right’) {

}

if (scrollDirection === ‘left’) {

}

}

这里还需要注意的点是,如果已经滚动到横向边界了,那么就不允许在滚动了,这里需要特殊处理一下。

那么触摸结束以后,元素还应该按照惯性继续向对应方向进行滚动,速度慢慢下降,直到结束为止。

速度不能直线下降,不能是一次函数,因为:y=ax+b

a代表加速度,加速的值一直不变,那么就会匀速降下去,体验上并不好,这里选择了二次函数的概念。

如图所示,慢慢靠近目标值,那么就要口子朝下的抛物线,且是对称轴左侧的这一部分函数。根据函数定义:

通过a、b参数来产出一个对应计算函数:

// 将"当前时间"映射[0, 1]间(currentTime /= duration)

// 根据缓入公式计算出"当前时间"应该移动的百分比(currentTime * currentTime)

// 根据"总移动长度"和"移动百分比"算出应移动的具体值(changeValue * …)

// 加上初始位置(+ startValue)

function easeOut(currentTime, startValue, changeValue, duration) {

currentTime /= duration;

return -changeValue * currentTime * (currentTime - 2) + startValue;

}

本业务场景中的实现代码如下:

/**

  • target: 滚动最终像素值

*/

const scrollAnimation = (target) => {

function easeOut(t, b, c, d) {

return -c * (t /= d) * (t - 2) + b; // 用时间t做x变量

}

var toTarget = target;

var endTimer = 500;

var startTimer = 0;

var step = function () {

let value = easeOut(startTimer, preX, toTarget, endTimer); // 返回一个距离值

// rowScrollAction(tempDirection, value, true); 执行对应元素滚动多少像素的方法

startTimer += 25;

if (startTimer <= endTimer) {

// 继续运动

requestAnimationFrame(step);

最后

小编的一位同事在校期间连续三年参加ACM-ICPC竞赛。从参赛开始,原计划每天刷一道算法题,实际上每天有时候不止一题,一年最终完成了 600+:

凭借三年刷题经验,他在校招中很快拿到了各大公司的offer。

入职前,他把他的刷题经验总结成1121页PDF书籍,作为礼物赠送给他的学弟学妹,希望同学们都能在最短时间内掌握校招常见的算法及解题思路。

整本书,我仔细看了一遍,作者非常细心地将常见核心算法题和汇总题拆分为4个章节。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

而对于有时间的同学,作者还给出了他结合众多数据结构算法书籍,挑选出的一千多道题的解题思路和方法,以供有需要的同学慢慢研究。

  • 12
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值