用过iphone
的都知道,ios
系统有一个重要的功能——辅助触控,可以让我们在触摸屏幕有困难或需要自适应配件的情况下使用iphone
.
辅助触控中,悬浮球充当着重要角色,它置顶悬浮在屏幕边缘,可任意移动,既不影响用户正常操作系统,又能提供许多功能的快速入口.
实际上,在很多app
我们也能看到类似的交互,例如微信前几个版本的浮窗效果.
那么原生js
怎么实现这一交互效果呢?
实现思路
-
实现悬浮球的拖拽,原理是改变球的位置.如果以绝对定位
(position: absolute)
的方式来决定小球的位置,那么关键就是计算和改变top
和left
属性; -
手指触屏有三个关键事件:
touchstart
:触屏时触发事件touchmove
:在屏幕上移动触发事件touchend
:手指离开屏幕触发事件
三个事件都接受
event
参数,我们通常使用这个参数拿到当前的触屏点,并获取有关信息(如当前触屏点距离屏幕边缘的距离) -
如下图,小球从
A
点拖动到B
点(暂且先只考虑水平方向的拖动,垂直方向是同理的),我们已知的信息有x1 = e.targetTouches[0].clientX
,即触屏点A
到屏幕左边缘的距离;l1 = ball.offsetLeft
,即小球在A
点时的左偏移量;x2 = e.targetTouches[0].clientX
,即触屏点B
到屏幕左边缘的距离;
那么,关键就是求得小球在
B
点时的左偏移量l2
,很简单的距离差运算,可得l2 = x2 - (x1 - l1)
;
-
再将小球的样式属性
left
设置为l2
,实现了小球位置的改变.this.style.left = l2 + 'px';
-
将小球拖动到某个位置松开,有以下几种情况:
const ballWidth = this.offsetWidth; // 悬浮球宽度 const ballHeight = this.offsetHeight; // 悬浮球高度 const l = this.offsetLeft; // 手指离开屏幕时悬浮球左偏移量 const h = this.offsetTop; // 手指离开屏幕时悬浮球上偏移量 const clientWidth = document.documentElement.clientWidth; // 屏幕宽度 const clientHeight = document.documentElement.clientHeight; // 屏幕高度
-
小球移出屏幕左侧,松开时弹回最左
if (l <= 0) { this.style.left = 0 + 'px'; }
-
小球移出屏幕右侧,松开时弹回最右
if (l >= clientWidth - ballWidth) { this.style.left = clientWidth - ballWidth + 'px'; }
-
悬浮球移出屏幕顶部,松开时弹回最顶部
if (h <= 0) { this.style.top = 0; }
-
悬浮球移出屏幕底部,松开时弹回最底部
if (h >= clientHeight - ballHeight) { this.style.top = clientHeight - ballHeight + 'px'; }
-
悬浮球在屏幕范围内松开,未移过屏幕二分之一的宽度,弹回最左,否则弹回最右
if (l <= (clientWidth - ballWidth) / 2) { this.style.left = 0 + 'px'; } else { this.style.left = clientWidth - ballWidth + 'px'; }
-
-
为小球弹回添加过渡效果
(transition)
,使其弹回效果更加平滑,提升交互体验.但是需要注意,小球在拖动的过程中,不需要有过渡.因此,我们只需要在touchend
事件中添加transition
样式(保证弹回时有过渡效果)this.style.transition = 'all 0.3s ease';
并在
touchstart
事件中把过渡效果删除:this.style.transition = 'none';
-
我们还可以在
touchend
事件中添加定时器,让小球在未操作的情况下,3s
后自动变半透明: