美文网首页
封装一个拖曳&缩放组件

封装一个拖曳&缩放组件

作者: 菜鸟的平凡之路 | 来源:发表于2020-07-03 15:38 被阅读0次

常用的第三方组件

  1. vue-drag-resize
    2.vue-draggable-resizeable

自己手写一个自定义拖曳&缩放组件

    /**
 * @author ddwei
 * @description 拖拽缩放插件
 */
export default class Drag_scale {
  constructor(target, options) {
    this._init(target, options);
  }

  /**
   * 初始化绑定节点
   * @param {HTMLElement|String} target 目标元素
   * @param {Object} options 选项
   */
  _init(target, options) {
    if (!target) throw new Error("el为必填项");

    this.el =
      typeof target === "string" ? document.querySelector(target) : target;

    this._defaultOptions = {
      rotate: 0, // 图旋转角度
      minScale: 1, // 最小缩放比例
      maxScale: 3 // 最大缩放比例
    };

    this.options = {
      ...this._defaultOptions,
      ...options
    };

    // 缩放
    this.maxScale = this.options.maxScale;
    this.minScale = this.options.minScale;
    this.scale = this.options.scale || 1; // 初始缩放比例设置为1

    // 拖拽
    this.dragTransformX = 0;
    this.dragTransformY = 0;
    //拖拽历史点
    this.lastDragPoint = {
      x: 0,
      y: 0
    };

    this.rotate = this.options.rotate;

    this.eventList = [
      {
        name: "mousemove",
        handler: this._handleDragMove.bind(this)
      }
    ];

    // 绑定事件对象
    this.el.addEventListener("mousedown", e => {
      this._handleDragStart(e);
      this.eventList.forEach(({ name, handler }) => {
        this.el.addEventListener(name, handler, false);
      });
    });

    // 鼠标抬起解绑move事件
    this.el.addEventListener("mouseup", e => {
      this._cleanEvent(this.eventList);
    });
  }
  /**
   * 处理缩放,旋转,拖拽
   */
  _setTransform(x, y, scale, rotate, transition = false) {
    if (!this.el) return;

    const text = `transform:scale(${scale}) rotate(${rotate}deg) translate3d(${x}px,${y}px,0);transform-origin:center;)`;
    const cssText = transition ? text + "transition:0.3s;" : text;

    this.el.setAttribute("style", cssText);
  }

  /**
   * 设置缩放比例
   * @param {Number} scale 缩放比例
   */
  setScale(scale) {
    let s = parseFloat(scale);
    if (isNaN(s)) return;

    if (s < this.minScale) s = this.minScale;
    if (s > this.maxScale) s = this.maxScale;

    this.scale = s;

    this._setTransform(
      this.dragTransformX,
      this.dragTransformY,
      this.scale,
      this.rotate
    );
  }
  /**
   * scale + 0.1
   */
  makeScaleAddZeroPointOne() {
    let newScale = this.scale + 0.1;
    this.setScale(newScale);
  }

  /**
   * scale - 0.1
   */
  makeScaleSubtractZeroPointOne() {
    let newScale = this.scale - 0.1;
    this.setScale(newScale);
  }

  /**
   * 旋转api
   * @param   {Number}  direction  方向 1顺时针 -1逆时针
   */
  rotateHandler(direction = 1) {
    if (![1, -1].includes(direction)) return;

    this.rotate = this.rotateFormat(this.rotate + direction * 90);

    this._setTransform(
      this.dragTransformX,
      this.dragTransformY,
      this.scale,
      this.rotate
    );
  }

  /**
   * 旋转角度处理
   * @return  {Number}  旋转角
   */
  rotateFormat(angle) {
    if (typeof angle !== "number" || isNaN(angle)) return;

    const temp = angle % 360;
    const newAngle = temp < 0 ? temp + 360 : temp;

    return Math.abs(newAngle);
  }

  // 解绑事件
  _cleanEvent(eventList) {
    if (!this.el || eventList.length == 0) return;
    eventList.forEach(({ name, handler }) => {
      this.el.removeEventListener(name, handler, false);
    });
  }
  /**
   * 处理指针结束
   * @param {MouseEvent|TouchEvent} e 事件对象
   * @returns void
   */
  _handlePointerEnd(e) {
    // 解绑相关事件
    this._cleanEvent(this.eventList);
  }

  /**
   * 获取事件相对触发对象的偏移值
   * @param {MouseEvent|TouchEvent} e 事件对象
   * @returns 偏移值对象
   */
  _getPointOffset(e) {
    if (e instanceof MouseEvent) {
      return {
        x: e.offsetX,
        y: e.offsetY
      };
    } else if (e instanceof TouchEvent) {
      const { touches, target } = e;

      const { clientX, clientY } = touches[0];
      const { left, top } = target.getBoundingClientRect();

      return {
        x: clientX - left,
        y: clientY - top
      };
    }
  }

  /**
   * 处理拖拽开始
   */
  _handleDragStart(e) {
    this.lastDragPoint = this._getPointOffset(e);
  }

  /**
   * 处理拖拽移动
   */
  _handleDragMove(e) {
    const { x, y } = this._getPointOffset(e);

    const { x: lastX, y: lastY } = this.lastDragPoint;

    this.dragTransformX += x - lastX;
    this.dragTransformY += y - lastY;

    this._setTransform(
      this.dragTransformX,
      this.dragTransformY,
      this.scale,
      this.rotate
    );
  }

  // 绑定事件对象
  _bindEvent() {
    // this._handleDragStart = this._handleDragStart.bind(this)
    // this._handleDragMove = this._handleDragMove.bind(this)
    // this._handlePointerEnd = this._handlePointerEnd.bind(this)
  }
}

  • 使用方式
    new Drag_scale($el)

相关文章

  • 封装一个拖曳&缩放组件

    常用的第三方组件 vue-drag-resize2.vue-draggable-resizeable 自己手写一个...

  • React Native 点击图片放大,缩放功能,组件封装

    create by CWP @ScrolImage 图片浏览显示组件封装,仅限iOS可以缩放,不支持安卓*先看效果...

  • 高级-任务3

    封装一个轮播组件 封装一个曝光加载组件 封装一个 Tab 组件 封装一个 Modal 组件

  • Angular+PhotoSwipe实现图片预览组件

    先前写过一篇文章:【组件篇】ionic3图像手指缩放滑动预览,是原来封装的一个组件的原型,后来用ionic4后,这...

  • 面向对象实战

    题目1: 封装一个轮播组件轮播组件题目2: 封装一个曝光加载组件曝光加载组件题目3: 封装一个 Tab 组件Tab 组件

  • Web37.面向对象实战

    题目1:封装一个轮播组件 题目2:封装一个曝光加载组件 题目3:封装一个Tab组件 题目4:封装一个日历组件 题目...

  • 封装(面向对象)

    题目1: 封装一个轮播组件 轮播封装 题目2: 封装一个曝光加载组件 曝光加载 题目3: 封装一个 Tab 组件 ...

  • 高级任务三

    题目1: 封装一个轮播组件 轮播 题目2: 封装一个曝光加载组件 曝光 题目3: 封装一个 Tab 组件 tab 组件

  • 面向对象实战

    1.封装一个轮播组件 轮播组件效果 2.封装一个曝光加载组件 曝光组件效果 3.封装一个 Tab 组件 Tab栏切...

  • 面向对象实战

    题目1: 封装一个轮播组件封装轮播组件(效果)代码题目2: 封装一个曝光加载组件封装曝光加载(效果)代码题目3: ...

网友评论

      本文标题:封装一个拖曳&缩放组件

      本文链接:https://www.haomeiwen.com/subject/irvsqktx.html