[前端] HTML 拖拉功能的实现代码

1870 0
王子 2022-10-19 15:32:42 | 显示全部楼层 |阅读模式
基于 vue
此功能核心思想就是通过 JavaScript 代码控制 node 在页面上的左边距与顶边距,不同的的样式定位方式有不同的解决方案
本方案采用position: absolute定位方式的解决方案
css 样式的核心代码
  1. // 父容器核心样式
  2.   width: 100%;
  3.   height: 100%;
复制代码
  1. // 子容器核心样式
  2.   position: absolute;
  3.   top: 50%;
  4.   left: 50%;
  5.   transform: translate(-50%,-50%);
复制代码
父容器通过width && height字段占满整个浏览器的可视范围,子容器通过position: absolute属性开启在父容器内的绝对定位,在通过top && left && transform: translate(-50%, -50%)属性控制子容器在父容器内的绝对位置
JavaScript 逻辑控制的核心代码

首先分解下,要实现 node 的移动需要哪些步骤和对应的 event 事件
    子容器创建时,在父容器内的绝对位置鼠标按键按下时,onmousedown 事件鼠标移动时,onmousemove 事件鼠标按键弹起时,onmouseup 事件
只要使用 onMousedown、onMousemove和onMouseup 这三个事件,就可以实现最简单的移动
  1. /*
  2. * 在子容器创建的时候获取子容器相对于父容器的 top 和 left 位置
  3. */
  4. mounted () {
  5.   this.left = this.$refs.fatherBox.offsetLeft
  6.   this.top = this.$refs.fatherBox.offsetTop
  7. }
复制代码
  1. /*
  2. * 鼠标按下时
  3. * 1. 开启允许子容器移动的 flag
  4. * 2. 记录鼠标点击时的位置信息
  5. */
  6. mouseDown (e) {
  7.   // 设置允许弹窗移动的 flag
  8.   this.moveFlag = true
  9.   // 保存鼠标开始位置
  10.   this.startLeft = e.clientX - this.left
  11.   this.startTop = e.clientY - this.top
  12. }
复制代码
  1. /*
  2. * 鼠标移动时
  3. * 1. 判断 flag 是否允许子容器移动
  4. * 2. 设置弹框左边位置
  5. * 3. 设置弹框右边位置
  6. */
  7. move (e) {
  8.   // 判断 flag 是否允许移动
  9.   if (!this.moveFlag) return
  10.   // 设置弹框左边位置
  11.   this.left = e.clientX - this.startLeft
  12.   // 设置弹框右边位置
  13.   this.top = e.clientY - this.startTop
  14. }
复制代码
  1. /*
  2. * 鼠标按键弹起时
  3. * 1. 关闭允许子容器移动的 flag
  4. */
  5. mouseUp (e) {
  6.   this.flag = false
  7. }
复制代码
通过这几个方法就可以获取鼠标按下移动时,鼠标的top 和 left 的偏移量,通过把这偏移量暴露出去给父组件,父组件实时设置子组件的 top 和 left 值,来使得子容器跟随鼠标的移动
父组件部分代码

父组件通过设置子组件的 ref、zIndex 值,而且父组件的 backValue 方法会从子组件接收 zIndex 值,通过 zIndex 来识别具体的子组件实例
  1. /*
  2. * 父组件代码片段 jsx 版
  3. */
  4. export default {
  5.   props: {
  6.     playList: {
  7.       type: Array,
  8.       required: true
  9.     }
  10.   },
  11.   render () {
  12.     return (
  13.       <div style={{width: '100%', height: '100%'}} ref={'father'}>
  14.         {
  15.           this.playList && this.playList.map((item, index) => {
  16.             return (
  17.               <ChildComponents
  18.                 key={index}
  19.                 ref={index}
  20.                 zIndex={index}
  21.                 visible={true}
  22.                 backValue={this.backValue}
  23.                 info={item}
  24.                 width={600}
  25.                 height={400}
  26.               />
  27.             )
  28.           })
  29.         }
  30.       </div>
  31.     )
  32.   },
  33.   methods: {
  34.     backValue (left, top, zIndex) {
  35.       this.$refs[zIndex].$el.style.top = `${top}px`
  36.       this.$refs[zIndex].$el.style.left = `${left}px`
  37.     }
  38.   }
  39. }
复制代码
  1. <!-- 父组件代码片段 vue 文件版 -->
  2. <template>
  3.   <div
  4.     ref="father"
  5.     style"width: 100%, height: 100%"
  6.   >
  7.     <ChildComponents
  8.       v-for="(item, index) in playList"
  9.       :key="index"
  10.       :ref="index"
  11.       :visible="true"
  12.       :z-index="index"
  13.       :back-value="backValue"
  14.       :info="item"
  15.       :close="close"
  16.       :width="600"
  17.       :height="400"
  18.     />
  19.   </div>
  20. </template>
  21. <script>
  22. export default {
  23.   components: {
  24.     VideoPlayerModal
  25.   },
  26.   props: {
  27.     playList: {
  28.       type: Array,
  29.       required: true
  30.     }
  31.   },
  32.   methods: {
  33.     backValue (left, top, zIndex) {
  34.       this.$refs[zIndex][0].$el.style.top = `${top}px`
  35.       this.$refs[zIndex][0].$el.style.left = `${left}px`
  36.     }
  37.   }
  38. }
  39. </script>
复制代码
设置子组件的围栏范围

这个功能只需要在 onmousemove 事件中进行判断 子容器的 top 和 left 是否超出浏览器的可视范围
  1. /*
  2. * 1. this.width 数据为父组件传递进来的 width 值,或者子组件本身设置的默认值
  3. * 2. this.height 数据为父组件传递进来的 height 值,或者子组件本身设置的默认值
  4. */
  5. move (e) {
  6.   // 判断 flag 是否允许移动
  7.   if (!this.moveFlag) return
  8.   // 判断是否超出左边视图
  9.       if (this.$refs.fatherBox.offsetLeft < this.width / 2) {
  10.         // 禁止弹框移动
  11.         this.moveFlag = false
  12.         // 设置弹框左边位置
  13.         this.left = this.width / 2 + 10
  14.         // 调用回调函数把偏移量暴露给父组件
  15.         this.backValue(this.left, this.top, this.zIndex)
  16.         return
  17.       }
  18.       // 判断是否超出右边视图
  19.       if (this.$refs.fatherBox.offsetLeft > document.body.clientWidth - this.width / 2) {
  20.         // 禁止弹框移动
  21.         this.moveFlag = false
  22.         // 设置弹框右边位置
  23.         this.left = document.body.clientWidth - this.width / 2 - 10
  24.         // 调用回调函数把偏移量暴露给父组件
  25.         this.backValue(this.left, this.top, this.zIndex)
  26.         return
  27.       }
  28.       // 判断是否超出顶部视图
  29.       if (this.$refs.fatherBox.offsetTop < this.height / 2 + 70) {
  30.         // 禁止弹框移动
  31.         this.moveFlag = false
  32.         // 设置弹框顶部位置
  33.         this.top = this.height / 2 + 70 + 10
  34.         // 调用回调函数把偏移量暴露给父组件
  35.         this.backValue(this.left, this.top, this.zIndex)
  36.         return
  37.       }
  38.       // 判断是否超出底部视图
  39.       if (this.$refs.fatherBox.offsetTop > document.body.clientHeight - this.height / 2 - 50) {
  40.         // 禁止弹框移动
  41.         this.moveFlag = false
  42.         // 设置弹框底部位置
  43.         this.top = document.body.clientHeight - this.height / 2 - 50 - 10
  44.         // 调用回调函数把偏移量暴露给父组件
  45.         this.backValue(this.left, this.top, this.zIndex)
  46.         return
  47.       }
  48.       // 设置弹框左边位置
  49.       this.left = e.clientX - this.startLeft
  50.       // 设置弹框右边位置
  51.       this.top = e.clientY - this.startTop
  52.       // 调用回调函数把偏移量暴露给父组件
  53.       this.backValue(this.left, this.top, this.zIndex)
  54. }
复制代码
子组件还要设置一个当鼠标超出子容器时的 onmouseout 事件,用来防止不可预期的 bug 问题
  1. mouseOut (e) {
  2.   this.moveFlag = false
  3. }
复制代码
到此这篇关于HTML 拖拉功能的文章就介绍到这了,更多相关HTML 拖拉功能内容请搜索中国红客联盟以前的文章或继续浏览下面的相关文章,希望大家以后多多支持中国红客联盟!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2025 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行