基于 vue
此功能核心思想就是通过 JavaScript 代码控制 node 在页面上的左边距与顶边距,不同的的样式定位方式有不同的解决方案
本方案采用position: absolute
定位方式的解决方案
css 样式的核心代码
- // 父容器核心样式
-
- width: 100%;
- height: 100%;
- // 子容器核心样式
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%,-50%);
父容器通过width && height
字段占满整个浏览器的可视范围,子容器通过position: absolute
属性开启在父容器内的绝对定位,在通过top && left && transform: translate(-50%, -50%)
属性控制子容器在父容器内的绝对位置
JavaScript 逻辑控制的核心代码
首先分解下,要实现 node 的移动需要哪些步骤和对应的 event 事件
- 子容器创建时,在父容器内的绝对位置
- 鼠标按键按下时,onmousedown 事件
- 鼠标移动时,onmousemove 事件
- 鼠标按键弹起时,onmouseup 事件
只要使用 onMousedown、onMousemove和onMouseup 这三个事件,就可以实现最简单的移动
- /*
- * 在子容器创建的时候获取子容器相对于父容器的 top 和 left 位置
- */
-
- mounted () {
- this.left = this.$refs.fatherBox.offsetLeft
- this.top = this.$refs.fatherBox.offsetTop
- }
- /*
- * 鼠标按下时
- * 1. 开启允许子容器移动的 flag
- * 2. 记录鼠标点击时的位置信息
- */
-
- mouseDown (e) {
- // 设置允许弹窗移动的 flag
- this.moveFlag = true
- // 保存鼠标开始位置
- this.startLeft = e.clientX - this.left
- this.startTop = e.clientY - this.top
- }
- /*
- * 鼠标移动时
- * 1. 判断 flag 是否允许子容器移动
- * 2. 设置弹框左边位置
- * 3. 设置弹框右边位置
- */
-
- move (e) {
- // 判断 flag 是否允许移动
- if (!this.moveFlag) return
-
- // 设置弹框左边位置
- this.left = e.clientX - this.startLeft
- // 设置弹框右边位置
- this.top = e.clientY - this.startTop
-
- }
- /*
- * 鼠标按键弹起时
- * 1. 关闭允许子容器移动的 flag
- */
-
- mouseUp (e) {
- this.flag = false
- }
通过这几个方法就可以获取鼠标按下移动时,鼠标的top 和 left 的偏移量,通过把这偏移量暴露出去给父组件,父组件实时设置子组件的 top 和 left 值,来使得子容器跟随鼠标的移动
父组件部分代码
父组件通过设置子组件的 ref、zIndex 值,而且父组件的 backValue 方法会从子组件接收 zIndex 值,通过 zIndex 来识别具体的子组件实例
- /*
- * 父组件代码片段 jsx 版
- */
-
- export default {
- props: {
- playList: {
- type: Array,
- required: true
- }
- },
- render () {
- return (
- <div style={{width: '100%', height: '100%'}} ref={'father'}>
- {
- this.playList && this.playList.map((item, index) => {
- return (
- <ChildComponents
- key={index}
- ref={index}
- zIndex={index}
- visible={true}
- backValue={this.backValue}
- info={item}
- width={600}
- height={400}
- />
- )
- })
- }
- </div>
- )
- },
- methods: {
- backValue (left, top, zIndex) {
- this.$refs[zIndex].$el.style.top = `${top}px`
- this.$refs[zIndex].$el.style.left = `${left}px`
- }
- }
- }
- <!-- 父组件代码片段 vue 文件版 -->
-
- <template>
- <div
- ref="father"
- style"width: 100%, height: 100%"
- >
- <ChildComponents
- v-for="(item, index) in playList"
- :key="index"
- :ref="index"
- :visible="true"
- :z-index="index"
- :back-value="backValue"
- :info="item"
- :close="close"
- :width="600"
- :height="400"
- />
- </div>
- </template>
- <script>
- export default {
- components: {
- VideoPlayerModal
- },
- props: {
- playList: {
- type: Array,
- required: true
- }
- },
- methods: {
- backValue (left, top, zIndex) {
- this.$refs[zIndex][0].$el.style.top = `${top}px`
- this.$refs[zIndex][0].$el.style.left = `${left}px`
- }
- }
- }
- </script>
设置子组件的围栏范围
这个功能只需要在 onmousemove 事件中进行判断 子容器的 top 和 left 是否超出浏览器的可视范围
- /*
- * 1. this.width 数据为父组件传递进来的 width 值,或者子组件本身设置的默认值
- * 2. this.height 数据为父组件传递进来的 height 值,或者子组件本身设置的默认值
- */
-
- move (e) {
- // 判断 flag 是否允许移动
- if (!this.moveFlag) return
-
- // 判断是否超出左边视图
- if (this.$refs.fatherBox.offsetLeft < this.width / 2) {
- // 禁止弹框移动
- this.moveFlag = false
- // 设置弹框左边位置
- this.left = this.width / 2 + 10
- // 调用回调函数把偏移量暴露给父组件
- this.backValue(this.left, this.top, this.zIndex)
- return
- }
-
- // 判断是否超出右边视图
- if (this.$refs.fatherBox.offsetLeft > document.body.clientWidth - this.width / 2) {
- // 禁止弹框移动
- this.moveFlag = false
- // 设置弹框右边位置
- this.left = document.body.clientWidth - this.width / 2 - 10
- // 调用回调函数把偏移量暴露给父组件
- this.backValue(this.left, this.top, this.zIndex)
- return
- }
-
- // 判断是否超出顶部视图
- if (this.$refs.fatherBox.offsetTop < this.height / 2 + 70) {
- // 禁止弹框移动
- this.moveFlag = false
- // 设置弹框顶部位置
- this.top = this.height / 2 + 70 + 10
- // 调用回调函数把偏移量暴露给父组件
- this.backValue(this.left, this.top, this.zIndex)
- return
- }
-
- // 判断是否超出底部视图
- if (this.$refs.fatherBox.offsetTop > document.body.clientHeight - this.height / 2 - 50) {
- // 禁止弹框移动
- this.moveFlag = false
- // 设置弹框底部位置
- this.top = document.body.clientHeight - this.height / 2 - 50 - 10
- // 调用回调函数把偏移量暴露给父组件
- this.backValue(this.left, this.top, this.zIndex)
- return
- }
-
- // 设置弹框左边位置
- this.left = e.clientX - this.startLeft
- // 设置弹框右边位置
- this.top = e.clientY - this.startTop
-
- // 调用回调函数把偏移量暴露给父组件
- this.backValue(this.left, this.top, this.zIndex)
- }
子组件还要设置一个当鼠标超出子容器时的 onmouseout 事件,用来防止不可预期的 bug 问题
- mouseOut (e) {
- this.moveFlag = false
- }
到此这篇关于HTML 拖拉功能的文章就介绍到这了,更多相关HTML 拖拉功能内容请搜索w3xue以前的文章或继续浏览下面的相关文章,希望大家以后多多支持w3xue!