一入前端深似海,从此红尘是路人系列第十二弹之移动端模拟IOS虚拟按钮效果
用过苹果的大家都知道,苹果公司做了一个虚拟按钮,让页面上的挂件可被拖拽并吸附到屏幕边框处,降低挂件对用户的干扰。该效果如果用JavaScript进行实现又该如何实现呢,接下来我将分享给大家。首先上一张效果图
一、思路来源
首先体验过该虚拟按钮的都知道,它是根据距离屏幕边距进行一个位移判断的。当手从屏幕中放开的时候,对边距判断后进行动态效果操纵,这里动态我们将用到transform进行控制,代码也是纯原生JavaScript。这里我们也只是做一个移动效果的模拟,对于其中的一些功能并没有添加进来。
二、代码编写
1、html
<div class="i-pendant" id="pendant"> <div class="drag"></div> </div>
2、css
.i-pendant { width: 60px; height: 60px; border-radius: 5px; background: #999; position: fixed; top: 300px; right: 0; z-index: 90; -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); -webkit-transition-property: -webkit-transform; transition-property: -webkit-transform; transition-property: transform; transition-property: transform, -webkit-transform; -webkit-transition-delay: 0s; transition-delay: 0s; -webkit-transition-timing-function: ease-out; transition-timing-function: ease-out; } .drag { width: 80%; height: 80%; margin: 10%; border-radius: 100%; background: #fff; }
3、JavaScript
首先我们需要先获取虚拟按钮,并定义一些全局状态,方便之后的拖拽判定
var pendant = document.getElementById("pendant"); var posX = parseInt(pendant.offsetLeft); var posY = parseInt(pendant.offsetTop); var screenWidth = document.documentElement.clientWidth; var screenHeight = document.documentElement.clientHeight; // 判断手势按下状态 var state = { type: null }; //检测是否move事件 var isMove = false;
定义不同手势对应的事件
var Events = { // 手势按下 onmousedown: function (event) {}, // 手势抬起 onmouseup: function (event) {}, // 手势移动 onmousemove: function (event) {} };
接下来我们需要做的就是一一实现这些手势事件,手势按下事件实现:
// 手势按下 onmousedown: function (event) { state.type = 'down'; screenWidth = document.documentElement.clientWidth; screenHeight = document.documentElement.clientHeight; var _touchs = event.targetTouches[0]; posX = _touchs.clientX; posY = _touchs.clientY; isMove = false; }
手势抬起事件实现:
// 手势抬起 onmouseup: function (event) { if (isMove) { var _top = posY, _left = posX; state.type = 'up'; if ((posY + parseInt(pendant.clientHeight) / 2) <= (screenHeight / 2)) { //在上半部分 if ((posX + parseInt(pendant.clientWidth) / 2) <= (screenWidth / 2)) { //在左半部分 if ((posY + parseInt(pendant.clientHeight) / 2) <= (posX + parseInt(pendant.clientWidth) / 2)) { //靠近上方 _top = 0; } else { //靠近左边 _left = 0; } } else { //在右半部分 if ((posY + parseInt(pendant.clientHeight) / 2) <= (screenWidth - (posX + parseInt(pendant.clientWidth) / 2))) { //靠近上方 _top = 0; } else { //靠近右边 _left = (screenWidth - parseInt(pendant.clientWidth)); } } } else { //下半部分 if ((posX + parseInt(pendant.clientWidth) / 2) <= (screenWidth / 2)) { //在左半部分 if ((screenHeight - (posY + parseInt(pendant.clientHeight) / 2)) <= (posX + parseInt(pendant.clientWidth) / 2)) { //靠近下方 _top = (screenHeight - parseInt(pendant.clientHeight)); } else { //靠近左边 _left = 0; } } else {//在右半部分 if ((screenHeight - (posY + parseInt(pendant.clientHeight) / 2)) <= (screenWidth - (posX + parseInt(pendant.clientWidth) / 2))) { //靠近上方 _top = (screenHeight - parseInt(pendant.clientHeight)); } else { //靠近右边 _left = (screenWidth - parseInt(pendant.clientWidth)); } } } setTransform(_left, _top); } else { if (!!event) { //点击事件触发入口 console.log('touch event'); } } }
手势移动事件实现:
// 手势移动 onmousemove: function (event) { isMove = true; // 如果这个元素的位置内只有一个手指的话 var _top = posY, _left = posX; state.type = 'move'; if (event.targetTouches.length === 1) { event.preventDefault();// 阻止浏览器默认事件,重要 var touch = event.targetTouches[0]; if ((touch.clientY) <= 0) { //超过顶部 _top = 0; } else if (touch.clientY > (screenHeight - parseInt(pendant.clientHeight))) {//超过底部 _top = screenHeight - parseInt(pendant.clientHeight); } else { _top = touch.clientY - parseInt(pendant.clientHeight) / 2; } if (touch.clientX <= 0) { //超过左边 _left = 0; } else if (touch.clientX > (screenWidth - parseInt(pendant.clientWidth))) { //超过右边 _left = screenWidth - parseInt(pendant.clientWidth); } else { _left = touch.clientX - parseInt(pendant.clientWidth) / 2; } setTransform(_left, _top); } }
我们在手势事件中可以看到一个函数叫setTransform,接下来我们将实现它:
/** * @param {[type]} _left [左偏移] * @param {[type]} _top [顶部偏移] */ function setTransform(_left, _top) { posX = _left; posY = _top; if (state.type === 'up') { pendant.style.webkitTransitionDuration = '.2s'; } else { pendant.style.webkitTransitionDuration = '0s'; } pendant.style.webkitTransform = 'translate3d(' + posX + 'px,' + posY + 'px,0)'; }
最后我们还需要对虚拟按钮进行一个参数的初始化
//初始化虚拟按钮参数 function init() { screenWidth = document.documentElement.clientWidth; screenHeight = document.documentElement.clientHeight; var _top = posY, _left = posX; if ((posY + parseInt(pendant.clientHeight)) > screenHeight) { //窗口改变适应超出的部分 _top = (screenHeight - parseInt(pendant.clientHeight)); } if ((posX + parseInt(pendant.clientWidth)) > screenWidth) { //窗口改变适应超出的部分 _left = (screenWidth - parseInt(pendant.clientWidth)); } //把样式的top、left赋值到transform去 setTransform(_left, _top); pendant.style.top = 0; pendant.style.left = 0; state.type = 'init'; Events.onmouseup(null); }
最后我们调用一下init方法,虚拟按钮拖动效果就模拟出来了。小伙伴还不赶紧去试一下看看,是不是和苹果的虚拟按钮拖动起来是一样的效果呢。如果觉得好用或者好玩的话,记得给qiangdada点个赞哦↖(^ω^)↗
原文发布时间为:2017年01月18日
原文作者: qiangdada
本文来源:开源中国 如需转载请联系原作者

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
C# 操作Word书签(二)——插入图片、表格到书签;读取、替换书签
概要 书签的设置可以帮助我们快速的定位某段文字,使用起来很方便,也很节省时间。在前一篇文章“C# 如何添加/删除Word书签”中介绍了插入、删除书签的方法,本篇文章将对C# 操作Word书签的功能做进一步介绍。示例内容将包含以下要点: 在现有书签位置插入图片 在现有书签位置插入表格 读取书签位置的文档内容 替换现有书签位置内容 使用工具 Spire.Doc for .NET 6.1 Visual Studio ps:下载安装该类库后,注意添加引用Spire.Doc.dl到项目程序,dll文件可在安装路径的Bin文件夹中获取。 示例代码(供参考) 测试文档如下: 【示例1】 在现有书签位置插入图片 步骤 1: 添加using指令 using Spire.Doc; using Spire.Doc.Documents; using Spire.Doc.Fields; using System.Drawing; 步骤 2 :主要代码段 //创建实例,加载文档 Document document = new Document(); document.LoadFromFile("test.d...
- 下一篇
前端路由的简单实现
概念 路由这个概念首先出现在后台。传统MVC架构的web开发,由后台设置路由规则,当用户发送请求时,后台根据设定的路由规则将数据渲染到模板中,并将模板返回给用户。因此,用户每进行一次请求就要刷新一次页面,十分影响交互体验。 ajax 的出现则有效解决了这一问题。ajax (asynchronous javascript and xml),浏览器提供的一种技术方案,采用异步加载数据的方式以实现页面局部刷新,极大提升了用户体验。 而异步交互体验的更高版本就是 SPA——单页应用,不仅页面交互无刷新,甚至页面跳转之间也可以无刷新。为了实现 SPA,因此便有了 前端路由 的概念。 实现 Angular,React,Vue 都有 前端路由 的概念,但是前端路由究竟是如何实现的呢?且看下面代码: /** * Created by lonelydawn on 2018-04-03. * javascript version: ES 6 */ import homepage from '../views/homepage.html' import product from '../views/prod...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- 设置Eclipse缩进为4个空格,增强代码规范
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS6,CentOS7官方镜像安装Oracle11G
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2全家桶,快速入门学习开发网站教程