在许多业务场景中会遇到让一个页面在web端可以实现双向滚动,且在滚动的时候可以上部吸顶,左侧吸在最左边这中类似excel表现的述求。
但是excel移动端本身使用canvas来画的,所以能保持较好的体验和性能,那么脱离canvas,我们是否有别的方案可以去靠近实现呢?如何在移动端实现,并同时兼容安卓和ios系统?
如下图所以,可以左右移动,也支持上下移动,在移动的对应方向的顶部需要吸顶。在pc端实现较为简单,通过滚动就可以实现,在移动端要想实现这一套方案,并同时兼容不同系统,这里我踩了一些雷,下文将诉说实现这个的全部技术方案的改变和踩雷的一些点。
如上图所示,不就是横向滚动和竖向默认滚动吗?
移动端屏幕宽高固定,本就可以左右滚动,那么只需要元素本身的大小大于屏幕的宽高不就可以了吗?
设置一个div,宽大于screen.width, 高大于screen.height即可,最终demo大概效果如下图所示:
左右的确都相当的丝滑,能横着滚,也能竖着滚了,就是全方位也都能滚动,着实诧异了一会儿。
如果那么当我朝着某个方向滚动的时候,禁掉一个方向的滚动,就可以解决了。
但是容器嵌套就出问题了,横向滚动的时候,我们领容器高度变成视口高度,overflow-y设置为hidden,横向依旧可以滚动,纵向设置为禁止滚动,在chrome里模拟了一下,的确不错,在真机上测试的时候,发现安卓端正常,ios端一旦手动设置overflow-y,发现纵向原先滚动到的位置会丢失,纵向内容直接回到最顶部,即纵向scrollTop变成了0。
设置纵向滚动,横向overflow-x为hidden时,横向原先滚动的距离也会被清除,回到最左侧。
那么通过手动记录之前的滚动位置,在设置某一方向禁止滚动时,把高度给他还原回去,就能解决了。
思路是对的,但是会出现强烈的闪屏现象,尤其在这种数据密集型的页面上(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);
} else {
// 动画结束
touchTimes = 0;
// 动画结束后的回调
}
};
step();
}
当滚动到边界时,记得清空循环计算哦
当横向滚动到边界时,模拟ios的弹簧效果(安卓和ios端保持一致)
实现方式就是对3.3中的滚动到边界时做对应的处理。我们达到边界以后,在滚动距离上多加50~100个像素值,然后利用抛物线的原理:
利用两边的值,先慢慢靠近最高点,然后再回到对应y值上。
接手一个项目,要严谨一点,如果是之前没接触过这种技术方案开发的,应该拿到项目时先写个小demo,然后再去评估开发时间。
不然脑海中出现的技术方案可以让你当场拍板,但是在实践中会发现出现预估错误,可是开发排期影响的就是整个小team的时间,你的delay很可能导致大家的排期都被打乱,不得不从拼命加班抢回开发时间。
还要学会给自己留充足的buffer能够去试错,能够应对突发情况。
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/1v3Q0PCXBGWls_-ZB2asxQ
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。