结合弹框拖拽功能感受pointer-events的“穿透”

1,788 阅读1分钟

这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战

前言

需求:实现弹框可拖拽移动,内嵌的聊天对话框为iframe。 image.png

问题

遇到的问题:由于内嵌的是iframe,当鼠标按下快速移动时(鼠标脱离外框),鼠标事件失效,造成的直观感受是拖动卡顿,左右移动还行,但是快速下移就失效。

原因分析

左右移动时鼠标始终在边框淡蓝色区域,快速下移时鼠标脱离淡蓝色区域并移到iframe的元素上鼠标事件失效

解决办法

pointer-events 值none表示鼠标事件“穿透”该元素并且指定该元素“下面”的任何东西。(MDN)

因此,在鼠标按下mousedown时设置iframe的pointer-events值为none,使得事件能够穿透整个框。鼠标松开事件mouseup为unset。

另外在弹框拖拽移动时,底图地图也会跟着移动,设置思路同iframe相同。

完整功能代码:

<template>
  <div
    class="draggable-div"
    :id="domId"
    @mousedown="handleMouseDown"
    :style="dragStyleStr"
  >
    <slot></slot>
  </div>
</template>

<script>
export default {
  name: 'DraggableDiv',
  data() {
    return {
      dragStyleStr: '',
      dragMes: {},
      domId: ''
    };
  },
  props: {
    artDomId: String
  },
  mounted() {
    this.domId = this.artDomId ? this.artDomId : new Date().getTime();
  },
  methods: {
    handleMouseDown(e) {
      const ele = document.getElementById('chatPanelIframe');
      ele.style.pointerEvents = 'none';
      this.bus.$emit('setPan', false);
      const that = this;
      const oBox = document.getElementById(this.domId);
      this.dragMes.disX = e.clientX - oBox.offsetLeft;
      this.dragMes.disY = e.clientY - oBox.offsetTop;
      document.onmousemove = e => {
        let left = e.clientX - this.dragMes.disX + 'px';
        let top = e.clientY - this.dragMes.disY + 'px';
        this.dragStyleStr = `left: ${left};top: ${top}`;
      };
      document.onmouseup = () => {
        this.bus.$emit('setPan', true);
        ele.style.pointerEvents = 'auto';
        document.onmousemove = document.onmouseup = null;
      };
      e.preventDefault();
    }
  }
};
</script>

<style lang="scss" scoped>
.draggable-div {
  position: fixed;
  z-index: 9999;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
</style>

总结

以上就是开发弹框拖拽时遇到的一些问题,供大家参考。可能开发过程中遇到地图比较少,此处只是举个例子,可以举一反三,比如在处理滚动条时也可以用相同的思路。