基于 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,拖拉功能

免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
千金楼资源网 Copyright www.htabc.com

评论“HTML 拖拉功能的实现代码”

暂无“HTML 拖拉功能的实现代码”评论...

《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线

暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。

艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。

《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。