五步掌握Ext的拖放(上)

简介: 五步掌握Ext的拖放 5 Steps to Understanding Drag and Drop with Ext JS September 13, 2009 by Jay Garcia 翻译:frank 那么多的交互设计模式中,“拖放(Drag and Drop)”模式是开发者感觉比较不错的。

五步掌握Ext的拖放
5 Steps to Understanding Drag and Drop with Ext JS

September 13, 2009 by Jay Garcia 翻译:frank

那么多的交互设计模式中,“拖放(Drag and Drop)”模式是开发者感觉比较不错的。用户日常在进行拖放操作的时候,真的是想都不用想地就可以轻松搞掂了,易学易用,非常直观。下文中,不是我们断言,只要将下面五个步骤的要义领会在心,拖放不再是一件难事。

定义拖放

拖动(drag)的动作,就是鼠标的点击动作发生了,点击在某些UI元素身上,就可以按着不放,同时也可以移动着鼠标;放下(drop)的动作,就是在拖动动作开始后,但鼠标按钮松开了——就是放下的动作。

宏观而言,拖放的操作可用下面的流程图来描述。

 

为加速开发,Ext JS本来就提供了 Ext.dd 以实现拖放的支持。在本博文中,我们将围绕拖放行动的“触发、无效置下和成功置下”的这几个方面问题,以及其中事件消息编程,还有修改外观的问题进行讨论。

拖放类的组织构成

初涉Ext.dd的文档部分大家觉得会有些怕怕的,但是,如果我们稍加一点耐心去观察其中的源码,那么我们会发现许多类都继承于DragDrop 类,并由此分为“Drag拖动的”和“Drop置下的”这两大类别。分类所针对的对象就是单个或多个节点其拖放的行为模式,——从类的组织来看可以看到这样的结果。

 

我们打算从最简单的DOM节点单个拖放的知识点来展开讨论,为的是更好地降低的学习曲线,适合初学者。切入正题,那就是分别利用DD DDTarget 类扩展出基本的自定义拖放行为。

然而,我们必须先介绍一下例程以及例程的目标是如何。

话说这个例子……

假设有这样的一个需求,客户是一个间汽车出租公司,出租cars小汽车和trucks卡车。他希望这些汽车有三种状态可选择:available可用的、rented已出租的、in repaire处于维修中的。作为类别划分,cars和trucks分别只能在其所属的“available”容器中。

一开始,第一目标是使得cars和trucks“可拖动”的状态,对此我们将会使用DD ;第二,我们要让rentedrepair vehicle 作为“可投放(可置下)”的目标地方,对此我们将会使用DDTarget 。最后,我们将安排两个拖放组(drag drop groups)把小车和卡车区分开来,各自属于不同的“available”投放容器就不会相互搞错。

这个例程的HTML和CSS已经做好,可以在这儿 下载。下载后,就可以开始拖动这些小车和卡车的操作了。

第一步:开始拖动

要使得汽车所在的DIV可拖动,得先要获取这些DIV集合。获取后,集合是一个数组,我们遍历它以此建立DD 实例。下面源码是该步骤的过程。

// 创建一个重写拖动行为的对象,稍后再试。 var overrides = {}; // 配置cars可拖动的 var carElements = Ext.get('cars').select('div'); Ext.each(carElements.elements, function(el) { var dd = new Ext.dd.DD(el, 'carsDDGroup', { isTarget : false }); // 复制overrides对象到刚刚创建的DD实例 Ext.apply(dd, overrides); }); var truckElements = Ext.get('trucks').select('div'); Ext.each(truckElements.elements, function(el) { var dd = new Ext.dd.DD(el, 'trucksDDGroup', { isTarget : false }); Ext.apply(dd, overrides); });

所有的拖放类其参与的模式皆是“方法重写(methods overridings)”。上述声明了一个空的overrides的对象,以待后面安排的动作方法,就覆盖到这个对象身上。这就是强调代码签名(code segment)的原因。

欲查询cars容器中的全体子div元素,我们可使用DomQuery 选取元素的函数。

要让cars和trucks元素变为可拖动的(dragable),我们创建了新的DD 实例,所传入的参数就是cars和trucks的DOM元素,还有说明其所隶属于的拖放组,也就是说小汽车应对应着小汽车拖放组、卡车应对应着卡车拖放组。拖放组(group)是什么呢?先买个关子,——等下我们便知道拖放组怎么设置有多重要了,特别在定义rentedrepair 置下目标的时候。

注意我们重写DD 对象的时候使用了Ext.apply ,这是一个增加对象的属性或方法的函数,十分方便。

在继续下一步之前,我们得花点时间分析一下拖动元素时屏幕将会发生些什么,进而明白所以然之后才会对接下来的代码在理解上,游刃有余。

说说拖动的元素怎么个拖动法

先要说明的是,当移动car或truck的时候,移到哪就摆放在哪,因为我们例子是一步一步来,从简单到复杂,所以这时候的例子正是纯粹的“拖动(drag)”,也就是说我们把拖放的过程从中拆分了。那么移动或拖动到某个目的地是不是就是一个合法之目的地,符不符合我们程序限定之要求呢?这就是有效置下和无效置下的区别了。相对地,我们仅此理解了“无效置下(invalid drop)”即可清楚有效置下的逻辑。

下面插图来自FireBug 的HTML检测面板,通过高亮的效果告知正在拖动的div元素,即Camaro元素(估计某个汽车品牌)。

 

点击上面的图片 测试拖动操作。.

注意观察拖动的过程中,我们看到元素底下的style样式属性有了三个新的CSS值:position、top和left,其中定义position为相对位置relative便可以将元素在页面上移来移去。移到的同时,top、left的数值也在变化,不断更新(此二值为元素的参照坐标)。由此可见,拖动的原理就在于定义这三项值的问题上。

拖动手势完成之后,style属性仍保持不变,当然再拖动的话,style又会新变化,但按道理来说,我们应该不是这样,而是在无效drop的状态下令元素回到原来的位置。在设置好合法置下目标之前,任何置下动作都可被认为是无效的drop。

第二步:修复无效置下

修复无效的drop,其实就是让拖动了的元素“归位”。怎么个“归位”法?既然前面修改了元素的style样式,那么“归位”就是恢复style为拖动之前的数值。最简单的制作方法,便是在鼠标按钮松开的事件触发后,拖动着的那个元素马上消失,然后在原来的位置重新出现。照这样简单的做法不是不行,就是显得比较生硬,最好还是用Ext.Fx 产生出渐变的过程,为求整个过程显得平滑一些。

提一提哪些方法我们要重写的repair方法:b4StartDrag , onInvalidDrop endDrag。

对overrides对象加入下列的方法。

// 获取在拖动的那个元素 b4StartDrag : function() { // Cache the drag element if (!this.el) { this.el = Ext.get(this.getEl()); } // 先记下原始坐标,后面有用 this.originalXY = this.el.getXY(); }, // 不在一个拖放组里面的就是无效drop onInvalidDrop : function() { // Set a flag to invoke the animated repair this.invalidDrop = true; }, // 拖动操作结束后执行 endDrag : function() { // 无效置下真正的逻辑 if (this.invalidDrop === true) { // Remove the drop invitation this.el.removeClass('dropOK'); // 定义动画的配置项对象 var animCfgObj = { easing : 'elasticOut', duration : 1, scope : this, callback : function() { // Remove the position attribute this.el.dom.style.position = ''; } }; // 应用动画 this.el.moveTo(this.originalXY[0], this.originalXY[1], animCfgObj); delete this.invalidDrop; } }, 首先是b4StartDrag 方法。顾名思义,它开始拖放前被调用。某种程度上也是一个事件。它的作用是记下元素原来的XY坐标,也就是被拖动前的位置。归位的时候就凭着这个坐标;其次endDrag 则是一个无效置下invalidDrop的通知方法。无效drop前面已经说过了,表示在不同一个DD组的区域投放,通通视作无效的投放。这里只是设置实例属性invalidDrop 为true,简单地标识一下;最后一个重写的方法endDrag ,每一次结束拖动的时候都会调用,此时元素不能通过鼠标的控制进行拖动了。如果不是成功地到达目的地,应该根据XY的坐标回到原来的位置。该例子中我们采用了elasticOut 的动画美化一下效果。

 

点击上面的图片 就可以演示动画修饰过的修改过程。

OK,修复drop的过程就到此完成了。接下来的步骤是 创建置下对象,相当于“目的地、目标(drop target)”,形成置下的接纳点,并定义有效地置下过程。

欲知完整DD教程,请看下回分解

目录
相关文章
|
30天前
|
测试技术 数据库 C++
Qt C++拖放事件探索之旅:多方法深入解析
Qt C++拖放事件探索之旅:多方法深入解析
115 1
|
3月前
第十四章:Element-ui组件库
第十四章:Element-ui组件库
36 0
|
JavaScript 前端开发
原生js制作选项卡详解,适合无基础的人学习
原生js制作选项卡详解,适合无基础的人学习
109 0
原生js制作选项卡详解,适合无基础的人学习
【C#】【桌面应用开发】拖拽文件到文本框获得所拖拽文件的路径
【C#】【桌面应用开发】拖拽文件到文本框获得所拖拽文件的路径
193 0
【C#】【桌面应用开发】拖拽文件到文本框获得所拖拽文件的路径
|
JavaScript 前端开发 开发者
Element UI(桌面组件库)之 三大灵魂拷问
Element UI(桌面组件库)之 三大灵魂拷问
459 0
Element UI(桌面组件库)之 三大灵魂拷问
Ext1.X的CheckboxSelectionModel默认全选之后不允许编辑的BUG解决方案
Ext1.X的CheckboxSelectionModel默认全选之后不允许编辑的BUG解决方案,ext 的CheckboxSelectionModel在后台默认选中之后,前台就不允许编辑的bug是存在的,因为CheckboxSelectionModel没有Disabled="true"的设置,只能想办法弥补,毕竟不能直接给GridPanel设置Disabled="true"这样的话,整个GridPanel都成灰色的了,显然不能满足用户的需求,不科学的界面如图:   那么怎么样处理这个问题呢。
850 0