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 相关文章推荐
js css样式操作代码(批量操作)
Oct 09 Javascript
对xmlHttp对象方法和属性的理解
Jan 17 Javascript
javascript中的数字与字符串相加实例分析
Aug 14 Javascript
js处理表格对table进行修饰
May 26 Javascript
在JavaScript中重写jQuery对象的方法实例教程
Aug 25 Javascript
DOM基础教程之使用DOM
Jan 19 Javascript
JavaScript文本框脚本编写的注意事项
Jan 25 Javascript
Mongoose经常返回e11000 error的原因分析
Mar 29 Javascript
node.js基于express使用websocket的方法
Nov 09 Javascript
使用bootstrap实现下拉框搜索功能的实例讲解
Aug 10 Javascript
HTML元素拖拽功能实现的完整实例
Dec 04 Javascript
vue 实现图片懒加载功能
Dec 31 Vue.js
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
杏林同学录(四)
2006/10/09 PHP
PHP四大安全策略
2014/03/12 PHP
php定时执行任务设置详解
2015/02/06 PHP
微信公众平台之快递查询功能用法实例
2015/04/14 PHP
使用PHP进行微信公众平台开发的示例
2015/08/21 PHP
用PHP去掉文件头的Unicode签名(BOM)方法
2017/06/22 PHP
关于递归运算的顺序测试代码
2011/11/30 Javascript
js 关键词高亮(根据ID/tag高亮关键字)案例介绍
2013/01/21 Javascript
javascript中in运算符用法分析
2015/04/28 Javascript
原生javascript实现自动更新的时间日期
2016/02/12 Javascript
jQuery插件cxSelect多级联动下拉菜单实例解析
2016/06/24 Javascript
input file上传 图片预览功能实例代码
2016/10/25 Javascript
谈谈Vue.js——vue-resource全攻略
2017/01/16 Javascript
Zepto实现密码的隐藏/显示
2017/04/07 Javascript
node.js中grunt和gulp的区别详解
2017/07/17 Javascript
JS跳转手机站url的若干注意事项
2017/10/18 Javascript
详解VUE里子组件如何获取父组件动态变化的值
2018/12/26 Javascript
使用Node.js实现一个多人游戏服务器引擎
2019/03/13 Javascript
分享一个vue项目“脚手架”项目的实现步骤
2019/05/26 Javascript
JS异步处理的进化史深入讲解
2019/08/25 Javascript
Vue.use()在new Vue() 之前使用的原因浅析
2019/08/26 Javascript
基于vue-draggable 实现三级拖动排序效果
2020/01/10 Javascript
vscode+gulp轻松开发小程序的完整步骤
2020/10/18 Javascript
vant组件中 dialog的确认按钮的回调事件操作
2020/11/04 Javascript
深入理解python中的浅拷贝和深拷贝
2016/05/30 Python
python GUI库图形界面开发之PyQt5窗口背景与不规则窗口实例
2020/02/25 Python
基于python实现计算且附带进度条代码实例
2020/03/31 Python
python中time包实例详解
2021/02/02 Python
浅谈css3中的前缀
2016/07/20 HTML / CSS
预订奥兰多和佛罗里达州公园门票:FloridaTix
2018/01/03 全球购物
苏格兰领先的多渠道鞋店:Begg Shoes
2019/10/22 全球购物
解除合同协议书
2014/04/17 职场文书
个人租房协议书(范本)
2014/10/14 职场文书
单位作风建设自查报告
2014/10/23 职场文书
乌镇导游词
2015/02/02 职场文书
有关花店创业的计划书模板
2019/08/27 职场文书