Vue实现拖动鼠标改变DIV高度

需求:模拟微信PC客户端的聊天窗口-发送框,通过拖动发送框的上沿,可手动调节高度。
想起 element-ui 的 table 组件,列可以通过拖动改变宽度,于是去扒源码...

1.思路剖析:

element-ui 思路:

表格-列边缘,拖出一条线(可见),线随着鼠标的拖动而移动,当鼠标放开,线消失,列重置宽度。

我的思路:

文本框-上边缘,添加一条线(不可见),鼠标拖动线时,实时改变文本框-包裹框的高度,从而改变文本框的高度。

2.注意事项:

  • 涉及的鼠标事件:mousedown、mousemove、mouseup。
  • mousedown 时,需要禁止用户选择网页中的文字和拖动元素;mouseup 时恢复。
  • 文本框-包裹框 = 文本框 + 线,文本框的 height 需设为 calc(100% - 线高度)。

3.代码实战:

body {
  padding-top: 200px;
}
.drag-textarea {
  position: absolute;
  bottom: 200px;
  width: 300px;
  height: 250px;
}
.drag-textarea .resize-line {
  height: 5px;
  cursor: move;
}
.drag-textarea textarea {
  width:100%;
  /* 重点属性 */
  height: calc(100% - 5px);
  padding: 0;
  border: 1px solid #333;
  resize: none;
}
// 枚举 - 文本框 wrap 最大/小高度
const TextAreaWrap = {
  MaxHeight: 400,
  MinHeight: 150
};

new Vue({
  data () {
    return {}
  },
  methods: {
    /**
     * 处理鼠标按下事件
     *
     * @param {MouseEvent} 鼠标事件
     */
    handleMouseDown (event) {
      // 禁止用户选择网页中文字
      document.onselectstart = () => false;
      // 禁止用户拖动元素
      document.ondragstart = () => false;

      // 保存鼠标最后移动的位置(Y轴)
      this.dragState = {
        // 鼠标开始移动的位置(Y轴)
        'startMouseTop': event.clientY,
        // 鼠标最后移动的位置(Y轴)
        'endMouseTop': event.clientY
      };

      // 绑定鼠标移动事件
      document.addEventListener('mousemove', this.handleMouseMove);
      // 绑定鼠标放开事件
      document.addEventListener('mouseup', this.handleMouseUp);
    },

    /**
     * 处理鼠标移动事件
     *
     * @param {MouseEvent} 鼠标事件
     */
    handleMouseMove (event) {
      const { rTextareaWrap, rResizeLine } = this.$refs;
      // 获取鼠标最后移动的位置(Y轴)
      const { endMouseTop } = this.dragState;
      // 获取当前的文本框高度
      const oldTextAreaHeight = rTextareaWrap.getBoundingClientRect().height;
      // 新的文本框高度
      let newTextAreaHeight = 0;

      // 计算鼠标移动的距离
      const distance = Math.abs(
        parseInt(((endMouseTop - event.clientY) * 100).toString(), 10) / 100
      );

      // 若鼠标向上移动
      if (endMouseTop > event.clientY) {
        // 发送框高度达到最大
        if (oldTextAreaHeight >= TextAreaWrap.MaxHeight)
        {
          // 修改光标为可被向下移动
          rResizeLine.style.cursor = 's-resize';
          return false;
        }

        // 计算新的发送框高度
        newTextAreaHeight = oldTextAreaHeight + distance;
      }
      // 若鼠标向下移动
      else
      {
        // 发送框高度达到最小
        if (oldTextAreaHeight <= TextAreaWrap.MinHeight)
        {
          // 修改光标为可被向上移动
          rResizeLine.style.cursor = 'n-resize';
          return false;
        }

        // 计算新的发送框高度
        newTextAreaHeight = oldTextAreaHeight - distance;
      }

      // 兼容鼠标快速拖动的情况:新的发送框高度不能超过最大值
      if (newTextAreaHeight > TextAreaWrap.MaxHeight)
      {
        newTextAreaHeight = TextAreaWrap.MaxHeight;
      }

      // 兼容鼠标快速拖动的情况:新的发送框高度不能小于最小值
      if (newTextAreaHeight < TextAreaWrap.MinHeight)
      {
        newTextAreaHeight = TextAreaWrap.MinHeight;
      }

      // 修改发送框高度
      rTextareaWrap.style.height = newTextAreaHeight + 'px';
      // 修改光标为可移动
      rResizeLine.style.cursor = 'move';

      // 更新鼠标最后移动的位置(Y轴)
      this.dragState.endMouseTop = event.clientY;
    },

    /**
     * 处理鼠标放开事件
     */
    handleMouseUp () {
      // 移除鼠标移动事件
      document.removeEventListener('mousemove', this.handleMouseMove);
      // 移除鼠标放开事件
      document.removeEventListener('mouseup', this.handleMouseUp);
      // 允许用户选择网页中文字
      document.onselectstart = null;
      // 允许用户拖动元素
      document.ondragstart = null;
    }
  }
}).$mount('#app')

你可能感兴趣的:(Vue实现拖动鼠标改变DIV高度)