html+js+css 实现拖拽工作进度
这里用到的js和css
tbl.js
bind()是JavaScript中的一个方法,用于创建一个新的函数,并将指定的对象作为新函数的上下文(this)绑定。在JavaScript中,函数的执行上下文(this)是在运行时确定的,取决于函数被调用的方式。使用bind()方法可以显式地指定函数的执行上下文,无论函数如何被调用,都会绑定到指定的对象上。12
bind()的用途
事件处理程序:在事件处理程序中,使用bind()可以确保函数在执行时绑定到正确的事件目标上。
回调函数:当将函数作为参数传递给其他函数时,使用bind()可以确保回调函数在执行时绑定到正确的对象上。
创建函数的拷贝:使用bind()可以创建一个新的函数,该函数与原函数具有相同的代码,但绑定到不同的对象上。1
bind()的语法和返回值
语法:function.bind(thisArg[,arg1[,arg2[,…]]])
thisArg:被绑定到函数上的对象,即当调用绑定后的函数时,函数中的this关键字会指向该对象。如果thisArg参数为null或undefined,则this关键字将指向全局对象(在浏览器中通常是window对象)。
arg1, arg2, …:要传递给函数的参数,这些参数将按照顺序传递给函数,并在调用函数时作为函数参数使用。
返回值:返回一个原函数的拷贝,并拥有指定的this值和初始参数。
event.originalEvent在JavaScript中用于访问原始的事件对象。在jQuery中,当事件处理程序被触发时,jQuery会对事件对象进行标准化处理,以便跨浏览器兼容。处理后的事件对象被保存在event对象的originalEvent属性中,这样开发者可以通过event.originalEvent访问到原始的事件对象。
使用场景和示例
在处理特定的事件时,原始事件对象可能包含一些jQuery处理后的对象中没有的信息。例如,在使用滚轮事件(mousewheel或DOMMouseScroll)时,不同浏览器有不同的属性来表示滚动的方向和距离。通过event.originalEvent,可以访问到这些原始的属性:
IE和Chrome:使用event.wheelDelta(向下滚动为负值)
Firefox:使用event.detail(向下滚动为正值)
event.target.style.backgroundColor 用于获取或设置触发事件的元素背景颜色。当某个事件(如点击事件)发生时,event.target 指向触发事件的元素,通过 style.backgroundColor 可以获取或设置该元素的背景颜色。
event.preventDefault()方法用于取消事件的默认行为。例如,当用户点击提交按钮时,可以阻止表单的提交。这个方法的作用是通知浏览器不要执行与事件关联的默认动作。如果事件的 cancelable属性为false,则不能阻止默认动作,调用该方法将不会有任何效果。12
使用场景:
表单提交:在用户点击提交按钮时,阻止表单的默认提交行为,可以通过AJAX发送数据,实现异步提交。
链接导航:在用户点击链接时,阻止默认的跳转行为,通过JavaScript自定义导航逻辑,实现更灵活的用户交互。
兼容性和替代方案:
Internet Explorer:preventDefault()方法在IE中不被支持,可以使用windo.event.returnVaule=false;作为替代方案来阻止默认行为。
style.css
html 全部源码:
浅谈移动设备交互体验之惯性滚动
很久以前,手机上的交互依赖键盘和触控笔。我们要查看一个很长很长的列表,必须使用非常难用的触控笔或键盘的上下左右键。后来黑莓发明了滚动球,缓解了大拇指按出茧的问题。
2007年,苹果推出iPhone。iPhone只有一个玻璃屏,没有触控笔,直接用手指操作,支持多手指。Multi-Touch这项技术在推出时被誉为和Mouse(Mac),Click wheel(iPod)一样革命性的发明。当然最近的3D Touch(Apple watch)也是革命性的。在推出iPhone之前,苹果已经做了多年的铺垫。2005年收购的小公司finger works就是专门做手势识别的团队,用macbook的人几乎是脱离鼠标的,因为其触控板非常好用,所用技术来自这家公司。
当时有很多程序猿和产品经理讨论这个技术如何实现。疯狂的Web开发者要在浏览器上实现基于鼠标中键的滚动效果:当很快地滚动中键并停止时,页面由于惯性,会继续往下滚动一段距离才停止。有一个专业名词用来描述,叫Momentum Scrolling。还有人用Web写了示例,用来模拟手指和屏幕交互过程中的数学逻辑,iScroll 和 Scrollability 都是不错的作品。头条的Web图集也有使用Javascript(以下简称JS)实现的惯性滚动代码。下面我们用最简单的Scrollability来讲解,如何实现惯性滚动。
一. 实现滚动
HTML代码:JS代码:页面中有四个元素,顶部的黑条,底部的黑条,黑条中的窗口A,以及窗口内一堆英文名列表B(可以想象成办公室的卷帘)。坐标系从窗口A左上角开始,横轴X(右边为正向),纵轴Y(下边为正向)。注意,这里Y轴的方向和数学课本里相反。手指在窗口A上移动,往下移动一段距离,得到的 distanceY > 0。代码由HTML,CSS和JS构成,HTML定义了两个黑条,窗口A和卷帘B。CSS定义了他们的颜色,位置等属性。Javascript则是重点要讲的,它用来控制手指和屏幕的交互。JS中定义了几个功能和变量,其中kBounceLimit这样以k开头的,是数学公式中的固定不变的参数。startX,startY,touchX,touchY用来记录手指位置,touchAnimator是负责操作卷帘B滚动的对象。
这几行代码表示,当用户手指触碰到屏幕时,会执行onTouchStart,去做一些事情。手指在屏幕上移来移去时,会执行onTouchMove。手指离开屏幕的瞬间,硬件会通知程序手指离开,此时执行onTouchEnd。touchstart和touchend都是瞬间事件,从手指按下,移动,抬起的一套过程中只会被通知一次,touchmove是连续触发的,移动1厘米,会收到几十个通知,告诉程序当前手指坐标x,y,时间点。
让卷帘随着手指移动的办法是,在touchstart时,记录手指位置y1;touchmove时根据得到y2,算出当前移动的距离distance=y2-y1,将卷帘在y轴上移动distance距离; touchmove不断触发,不断执行前面两步,把上一次的touchmove当作起始点,紧接着触发的touchmove当作后来的点,计算distance移动卷帘。
iPhone在处理滚动的过程中,当页面已经到最顶部时,再往下拉会有弹簧效果:手指拉了一个屏幕的距离,内容只移动了半屏。用这样的代码实现其效果:
velocity的含义是:手指在屏幕移动一段距离,触发n个touchmove事件,相邻两个事件的y坐标之差就是velocity(速度)。
打个比方,老李跑步,他的步长就是 velocity。当老李还没跑,想逃出森林公园南门时会有人把他往回拉。Velocity是1米,往回拉的弹性会给velocity打折,身体移动距离可能是0.8米,具体的折扣为:
(1.0 – (position – max) / bounceLimit)*kBounceLimit
position:当前卷帘移动到的位置,(逃出南门的距离)
parentOffsetHeight : 598 窗口A的高度
nodeOffsetHeight : 4602 卷帘B的长度
max:0
min:-4004 (parentOffsetHeight-nodeOffsetHeight,卷帘被挡住的长度,从下往上拉卷帘,最多移动的距离就是min值)
absMin = min
absMax = max
bounceLimit :窗口高度 parentOffsetHeight*kBounceLimit
kBounceLimit:0.75
转换后,速度velocity衰减的系数为 0.75 – position/ 598,当position越大,velocity打折越多,越难往下拖动。
二. 惯性和回弹
接着,我们用代码实现自由滚动和下拉时的回弹
在touchend时,加入takeoff()方法takeoff方法中,根据手指离开屏幕时的velocity计算后面滚动动画的代码:
savekeyframe方法会保存计算出来的每一帧动画,包含位置和时间点。
-
自由滚动时的状态:
-
在顶部回弹时的状态:position = easeOutExpo(decelStep, decelOrigin, decelDelta, kBounceTime);continues = ++decelStep <= kBounceTime && Math.floor(Math.abs(position)) > max;
迭代计算position的公式为缓动曲线easeOut,接受的四个参数为:decelStep :初始值为0,每次减速,自增1decelOrigin :decelStep为0时 position值decelDelta :decelStep为0时 max-positionkBounceTime :240对比linear,ease-in,ease-out和ease-in-out四个曲线,ease-out方程x=easeOut(t)在一开始有平缓的加速,在时间t到50%时,位置x已经快到达70%,在后续50%的时间内减速直到停止。符合我们平时看到的iOS滚动逻辑。function easeOutExpo(t, b, c, d) { return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b }continues的计算
自由滚动时:continues = Math.floor(Math.abs(velocity)*10) > 0; // Math.abs(velocity) < 0.1
顶部回弹时:continues = ++decelStep <= kBounceTime && Math.floor(Math.abs(position)) > max; // decelStep<=240加位置约束
底部回弹时:continues = ++decelStep <= kBounceTime && Math.ceil(position) < min; //同上
-
底部上拉的状态,同上。
-
saveKeyframe(!continues);time += kAnimationStep;
作用是根据diff判断是否保存这个关键帧,最后得到位置和时间的运动轨迹
-
根据keyframes得到运动轨迹,再使用实现滚动的代码,让页面运动起来。这里就不展开说明了
(gif图略卡,实际效果流畅很多)
三. 浏览器实现
苹果和谷歌在意识到这个需求后,为web开发者提供了原生的支持。
之前需要用iscroll等框架的需求,Chrome浏览器只需 overflow:scroll 一行代码即可。iOS设备需再加一行代码 -webkit-overflow-scrolling: touch;
原生实现的好处是
-
计算位置的过程要进行大量小数运算,这一点JS非常慢。
-
惯性滚动是苹果专利,原理涉及数学物理知识很多,远比web开发者模仿出来的要复杂,而且不开源。
-
如果滚动的内容非常长(手机通讯录,微信朋友圈等),要做延迟渲染,生成瓦片,贴图,销毁或者回收,内存管理,这些工作必须由系统支持,而不是业务支持。
-
iOS支持Scroll Snapping with CSS Snap Points(点击访问),在滚动结束时对齐到内部元素,只需要两行css代码。
随着手机硬件的发展,浏览器和操作系统在图形渲染,网络API,数据存储等方面的差距越来越小。而且浏览器面向业务,对底层架构的抽象更好,一行css,一个javascript对象可以替代几千行java代码(or 几百行swift代码?)。很多只在操作系统中提供的功能,例如消息推送,也已经在浏览器实现。
Web的开放性让很多公司都对其添砖加瓦。你很难想象微软会往Android仓库中贡献代码,或者谷歌给IE浏览器解决bug,但他们确实都在为HTML5标准做贡献。另一个例子是Adobe,他们希望将Photoshop中的滤镜,图层混合模式等功能提供给web开发者,于是提议做了css filter,css blender。
http://sarasoueidan.com/demos/css-blender/
还有很多简单好玩的东西,以后会在博客中慢慢写。如有描述错误和不当,请批评指正。
作者:王伟
本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com
文章为作者独立观点不代本网立场,未经允许不得转载。