Vue实现仿iPhone悬浮球的示例代码


Posted in Javascript onMarch 13, 2020

悬浮球插件简单的效果图:

很遗憾,没找到太好的视频转gif的软件,压缩出来的大小超过了限制,就不放图了

可以参考其他人的图,效果一致:

Vue实现仿iPhone悬浮球的示例代码

简单实用案例:

<!-- 给定一个初始位置position,插槽中填写想滑动的部分 -->
<xuanfuqiu :position="position">
	<d-add-button @click="addPigFarm" add-item="猪场"></d-add-button>
</xuanfuqiu>

原理示意图

请结合代码注释来理解

Vue实现仿iPhone悬浮球的示例代码

悬浮球插件代码如下:

<template>
  <div>
    <div class="xuanfu" id="moveDiv" :style="position"
      @mousedown="down" @touchstart="down"
      @mousemove="move" @touchmove="move"
      @mouseup="end" @touchend="end">
      <slot></slot>
    </div>
  </div>
</template>

<script>
export default {
  name: "",
  components: {},
  props: {
    // 通过position来设置初始定位
    position: {
      type: Object,
      default: function() {
        return {
          top: "32.25rem",
          left: "18.34375rem"
        }
      }
    },
    // 通过fixed来禁用自由移动
    fixed: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      flags: false,
      positionTemp: { x: 0, y: 0 },  // 记录手指点击的位置
      nx: '', ny: '', dx: '', dy: '', xPum: '', yPum: '',
    }
  },
  watch: {},
  computed: {},
  methods: {
    // 实现移动端拖拽
    down(){
      if (this.fixed) {
        return
      }

      this.flags = true;
      var touch;
      // 该if判断是用touch还是mouse来移动
      if (event.touches) {
        touch = event.touches[0];
      } else {
        touch = event;
      }
      this.positionTemp.x = touch.clientX;  // 手指点击后的位置
      this.positionTemp.y = touch.clientY;
      
      this.dx = moveDiv.offsetLeft;  // 移动的div元素的位置
      this.dy = moveDiv.offsetTop;
      
      // console.log("moveDiv.offsetLeft", moveDiv.offsetLeft)
      // console.log("touch.clientX", touch.clientX)
    },
    move(){
      if(this.flags) {
        var touch ;
        if(event.touches){
          touch = event.touches[0];
        }else {
          touch = event;
        }
        this.nx = touch.clientX - this.positionTemp.x;  // 手指移动的变化量
        this.ny = touch.clientY - this.positionTemp.y;
        
        this.xPum = this.dx + this.nx;  // 移动后,div元素的位置
        this.yPum = this.dy + this.ny;
        
        let windowWidth = document.documentElement.clientWidth
        let windowHeight = document.documentElement.clientHeight
        // console.log("window.clientWidth", windowWidth)
        // console.log(this.xPum)
        // console.log(" moveDiv.clientWidth", moveDiv.clientWidth)
        
        if (this.xPum > 0 && (this.xPum + moveDiv.clientWidth < windowWidth)) {
        	// movediv的左右边,未出界
          moveDiv.style.left = this.xPum + "px";
        } else if (this.xPum <= 0) {
          // 左边出界,则左边缘贴边
          moveDiv.style.left = 0 + "px";
        } else if (this.xPum + moveDiv.clientWidth >= windowWidth) {
          // 右边缘出界
          moveDiv.style.left = (windowWidth - moveDiv.clientWidth) + "px";
          // console.log("dx", windowWidth - moveDiv.clientWidth)
        }
        // 上下未出界
        if (this.yPum > 0 && (this.yPum + moveDiv.clientHeight < windowHeight)) {
          moveDiv.style.top = this.yPum +"px";
        } else if (this.yPum <= 0) {
          // 上边缘出界
          moveDiv.style.top = 0 + "px"
        } else if (this.yPum + moveDiv.clientHeight >= windowHeight) {
          // 下边缘
          // console.log("windowHeight:", windowHeight)
          // console.log("moveDiv.clientHeight:", moveDiv.clientHeight)
          // console.log(this.yPum + moveDiv.clientHeight)
          moveDiv.style.top = windowHeight - moveDiv.clientHeight + "px"
        }

        // 阻止页面的滑动默认事件,为了只让悬浮球滑动,其他部分不滑动;如果碰到滑动问题,1.2 请注意是否获取到 touchmove, 系统默认passive: true,无法使用preventDefault
        // document.addEventListener("touchmove", function(){
        //  event.preventDefault();
        // }, { passive: false });
        // document.addEventListener("mousemove", function(){
        //   event.preventDefault();
        // }, { passive: false });
        document.addEventListener("touchmove", this.preventDefault, { passive: false })
        document.addEventListener("mousemove", this.preventDefault, { passive: false })
      }
    },
    //鼠标释放时候的函数,鼠标释放,移除之前添加的侦听事件,将passive设置为true,不然背景会滑动不了
    end(){
      this.flags = false
      // 注意事项,在添加和删除监听事件时,其function必须是同名的函数,不能为匿名函数。
      document.removeEventListener('touchmove',this.preventDefault, false)
      document.removeEventListener('mousemove',this.preventDefault, false)
      // 下面两句是保证在移除监听事件后,除了悬浮球的部分还能够滑动,如果不添加,则无法滑动
      document.addEventListener("touchmove", function(e) {
        window.event.returnValue = true
      })
      document.addEventListener("mousemove", function(e) {
        window.event.returnValue = true
      })
    },
    preventDefault(e) {
      e.preventDefault()
    }
  },
  created() {},
  mounted() {}
}
</script>

<style lang="scss" scoped>
.xuanfu {
  /* 如果碰到滑动问题,1.3 请检查 z-index。z-index需比web大一级*/
  z-index: 999;
  position: fixed; // 这里的定位方式有待考量,fixed的话存在未知设置不合理,跑出屏幕不显示的问题
}
</style>

到此这篇关于Vue实现仿iPhone悬浮球的示例代码的文章就介绍到这了,更多相关Vue 悬浮球内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
jQuery 源码分析笔记(2) 变量列表
May 28 Javascript
JQuery的ready函数与JS的onload的区别详解
Nov 21 Javascript
JavaScript将数据转换成整数的方法
Jan 04 Javascript
node.js中的fs.readFile方法使用说明
Dec 15 Javascript
《JavaScript DOM 编程艺术》读书笔记之JavaScript 简史
Jan 09 Javascript
setTimeout内不支持jquery的选择器的解决方案
Apr 28 Javascript
requireJS使用指南
Apr 27 Javascript
javaScript事件学习小结(四)event的公共成员(属性和方法)
Jun 09 Javascript
js简单实现图片延迟加载的方法
Jul 19 Javascript
Javascript点击按钮随机改变数字与其颜色
Sep 01 Javascript
vue移动端路由切换实例分析
May 14 Javascript
记一次用ts+vuecli4重构项目的实现
May 21 Javascript
AI小程序之语音听写来了,十分钟掌握百度大脑语音听写全攻略
Mar 13 #Javascript
vue动态渲染svg、添加点击事件的实现
Mar 13 #Javascript
创建nuxt.js项目流程图解
Mar 13 #Javascript
微信小程序中的上拉、下拉菜单功能
Mar 13 #Javascript
JavaScript实现公告栏上下滚动效果
Mar 13 #Javascript
使用vue实现HTML页面生成图片的方法
Mar 12 #Javascript
JavaScript实现随机点名器
Mar 25 #Javascript
You might like
无数据库的详细域名查询程序PHP版(3)
2006/10/09 PHP
PHP中动态显示签名和ip原理
2007/03/28 PHP
连接到txt文本的超链接,不直接打开而是点击后下载的处理方法
2009/07/01 PHP
php绝对路径与相对路径之间关系的的分析
2010/03/03 PHP
Jquery zTree 树控件异步加载操作
2016/02/25 Javascript
jQuery插件zTree实现的多选树效果示例
2017/03/08 Javascript
angular2+nodejs实现图片上传功能
2017/03/27 NodeJs
JS笛卡尔积算法与多重数组笛卡尔积实现方法示例
2017/12/01 Javascript
微信小程序当前时间时段选择器插件使用方法详解
2018/12/28 Javascript
JS实现的雪花飘落特效示例
2019/12/03 Javascript
如何在JavaScript中使用localStorage详情
2021/02/04 Javascript
python批量修改文件后缀示例代码分享
2013/12/24 Python
小结Python用fork来创建子进程注意事项
2014/07/03 Python
详解Python3中yield生成器的用法
2015/08/20 Python
Python爬虫辅助利器PyQuery模块的安装使用攻略
2016/04/24 Python
利用Python批量生成任意尺寸的图片
2016/08/29 Python
JSONLINT:python的json数据验证库实例解析
2017/11/28 Python
Python简单实现查找一个字符串中最长不重复子串的方法
2018/03/26 Python
详谈在flask中使用jsonify和json.dumps的区别
2018/03/26 Python
对python numpy数组中冒号的使用方法详解
2018/04/17 Python
python nmap实现端口扫描器教程
2020/05/28 Python
python属于解释型语言么
2020/06/15 Python
python中if嵌套命令实例讲解
2021/02/25 Python
HTML5实时语音通话聊天MP3压缩传输3KB每秒
2019/08/28 HTML / CSS
HTML5的语法变化介绍
2013/08/13 HTML / CSS
家乐福巴西网上超市:Carrefour巴西
2016/10/31 全球购物
英国No.1体育用品零售商:SportsDirect.com
2019/10/16 全球购物
大四本科生的自我评价
2013/12/30 职场文书
市优秀教师事迹材料
2014/02/05 职场文书
环保宣传标语
2014/06/12 职场文书
2014年扫黄打非工作总结
2014/12/03 职场文书
2014司机年终工作总结
2014/12/05 职场文书
论文答辩开场白大全
2015/05/27 职场文书
再次探讨go实现无限 buffer 的 channel方法
2021/06/13 Golang
C#连接ORACLE出现乱码问题的解决方法
2021/10/05 Oracle
特别篇动画《总之就是非常可爱 ~制服~》PV公开,2022年夏季播出
2022/04/04 日漫