Quark-Renderer----第十四篇

2021SC@SDUSC

综述

上次我们讨论了几何意义上的线之后,我们接下来进行讨论关于graphic包下的文件,这里面主要有drag、gradient、line、link、shape、transform等几个文件夹,分别代表着不同的图像图像操作,下面我们主要学习这几个包中的js内容。

graphic包

drag包

该包中主要有两个文件,分别是DragDropMgr.js和Draggable.js文件,其中DragDropMgr是全局拖拽管理器,支持同时拖拽多个元素,只需按住Ctrl 键就可以实现多选;另一个js文件是具体实现拖拽功能,所有需要拖拽功能的元素都可以mixin此类的实现,此实现依赖我们之前讲的事件处理机制,mixin此实现的类需要预先mixin eventful接口的默认实现,才能提供事件支持。下面我们对这两个类进行分开详细讨论。

DragDropMgr.js

这是一个工具类,作为一个全局的拖拽管理器,在该类中主要有构造函数、设置监听、停止监听、开始拖动、在拖动过程中、拖动结束、清除选中、获取当前选中的所有元素等这几个方法的作用,下面我们主要针对其中的关键信息进行分析。

startListen

开始监听的主要目的就是绑定鼠标监听,通过按下鼠标来触发事件,具体就是以下代码:进行了mousedown的事件绑定。

  startListen() {
    
    
    this.dispatcher.on('mousedown', this.dragStart, this);
    return this;
  }
stopListen

该函数主要的作用是停止监听,这个函数主要就是将所有监听都删除,同时将所有都归0,具体如下

  stopListen() {
    
    
    this.clearSelectionMap();
    this._draggingItem = null;
    this._dropTarget = null;
    this._x = 0;
    this._y = 0;

    this.dispatcher.off('mousedown', this.dragStart, this);
    this.dispatcher.off('pagemousemove', this.dragging, this);
    this.dispatcher.off('pagemouseup', this.dragEnd, this);
    return this;
  }

通过解除mousedown监听、pagemousemove监听、pagemouseup监听这三个监听,然后将解除后的对象返回,这是该函数的主要目的。

dragStart、draging、dragEnd

这三个函数发生在一个周期中,分别发生在拖拽开始、拖拽过程中以及拖拽结束。在拖拽开始时,先对该对象进行事件的绑定,首先判断事件是否被派遣,然后再将事件进行判断,判断是否按下Ctrl键以及选择元素,然后进行选择操作,分别确定他们的坐标,然后进行绑定pagemousemove、pagemouseup的操作,然后通过一个循环遍历所有的dispatcher,派遣到相应的任务事件。

dragStart(e) {
    
    
    let el = e.target;
    let event = e.event;
    this._draggingItem = el;

    if (!el) {
    
    
      this.clearSelectionMap();
      return;
    }

    if (!el.draggable) {
    
    
      return;
    }

    if (!event.ctrlKey && !this.selectionMap.get(el.id)) {
    
    
      this.clearSelectionMap();
    }
    el.dragging = true;
    this.selectionMap.set(el.id, el);

    this._x = e.offsetX;
    this._y = e.offsetY;
    this.dispatcher.on('pagemousemove', this.dragging, this);
    this.dispatcher.on('pagemouseup', this.dragEnd, this);

    this.selectionMap.forEach(el => {
    
    
      this.dispatcher.dispatchToElement(this.normalizeParam(el, e), 'dragstart', e.event);
    });
  }

然后就是拖拽中,这个没有什么内容,主要是确定当前的位置信息,然后绑定鼠标的位置重新赋给当前的拖拽物体,注意要时刻判断当前对象的draggingTtem书香是否与当前的dispatcher相同,然后在进行当前对象的dispatcher的事件分发代理,把事件分发给 canvas 中绘制的元素。这样就实现了实时的拖拽操作。

最后就是结束拖拽,该过程更为简单,主要是解除pagemousemove以及pagemouseup,然后判断当前的dispatcher绑定一个事件分发代理,把事件分发给 canvas 中绘制的元素。

  dragEnd(e) {
    
    
    this.selectionMap.forEach(el => {
    
    
      el.dragging = false;
      this.dispatcher.dispatchToElement(this.normalizeParam(el, e), 'dragend', e.event);
    });
    this.dispatcher.off('pagemousemove', this.dragging, this);
    this.dispatcher.off('pagemouseup', this.dragEnd, this);

    if (this._dropTarget) {
    
    
      this.dispatcher.dispatchToElement(this.normalizeParam(this._dropTarget, e), 'drop', e.event);
    }

    this._dropTarget = null;
  }

dragDropMgr总结

该js主要是全局拖拽管理器,处理的是对于一般情况下的拖拽,包括开始监听、停止监听、开始拖拽、正在拖拽、结束拖拽等事件的处理,实现全局拖拽的大致实现。

Draggable.js

该文件主要是一个提供拖拽功能,所有需要拖拽的都可以混入该类的实现,该类实现了依赖事件机制。其中最重要的就只有一个move方法。

在该方法中,主要的目的就是移动元素,获取元素的x、y坐标,以及事件,然后通过匹配,是否是水平或者竖直然后对x以及y进行赋值,然后this.trigger('moving', this); 设置位置属性动画时触发移动事件。this.dirty();把元素标记为dirty,然后更新数据,同时触发afterMove事件,调用afterMove函数,这个函数相当于一个钩子函数,主要是在元素发生移动之后执行。类似于Vue.js中的vm生命周期中的钩子。

总结

以上我们主要对Drag中的两个js文件进行了分析,这两个文件主要是设计拖拽功能的实现,我们从他的关键方法进行了分析处理,然后这些内容又有对于事件部分的涉及,在了解事件处理以后,我们对于这部分内容的认知更加明朗,分析也更加容易。

猜你喜欢

转载自blog.csdn.net/qq_53259920/article/details/122194834
今日推荐