Ext的 Resize 和 Drag 界面非常漂亮,很多朋友想把它用到自己的地方,却不想用整个Ext ,所以本文特别对这2个效果进行制作。让我们先看下效果:

1. 修正一些认识。
很多朋友肯能认为拖动时的虚线和透明窗口是为了美观,但其实它们更为了效率。如果窗口里有很多元素,如果经常改变大小,会导致内部元素经常重新布局,最后导致效果卡得不能用。
2. 复习上文的拖动。
上文介绍了如何实现拖动,最终我们可以通过如下代码实现拖动:
elem.on('dragstart', function(){});
3. resizer 节点。
resize时见到的虚框其实是一个和窗口没关的div,我们把这个div称为代理层。 (div-proxy)
当鼠标按下角落时 - 显示代理,并附在窗口上 - 当鼠标移动, 改变代理大小。 - 当鼠标放开 - 隐藏代码, 设置窗口大小。
4. 拖动句柄。
所谓的句柄就是八个可触发resize的小东西,这些东西可用<div>实现:
<div class="x-resizable-lt">
</div>
<div class="x-resizable-t">
</div>
<div class="x-resizable-rt">
</div>
<div class="x-resizable-l">
</div>
<div class="x-resizable-r">
</div>
<div class="x-resizable-lb">
</div>
<div class="x-resizable-b">
</div>
<div class="x-resizable-rb">
</div>
每个滑块:
.x-resizable-lt, .x-resizable-t, .x-resizable-rt, .x-resizable-l, .x-resizable-r, .x-resizable-lb, .x-resizable-b, .x-resizable-rb {
overflow: hidden;
width: 6px;
height: 6px;
position: absolute;
}
.x-resizable-lt {
top: 0;
left: 0;
z-index: 2;
cursor: nw-resize;
}
.x-resizable-t {
width: 100%;
top: 0;
left: 0;
z-index: 1;
cursor: n-resize;
}
.x-resizable-rt {
top: 0;
right: 0;
cursor: ne-resize;
}
.x-resizable-l {
left: 0;
cursor: w-resize;
}
.x-resizable-r {
right: 0;
cursor: e-resize;
}
.x-resizable-lb {
bottom: 0;
left: 0;
z-index: 2;
cursor: sw-resize;
}
.x-resizable-b {
width: 100%;
bottom: 0;
left: 0;
cursor: s-resize;
}
.x-resizable-rb {
bottom: 0;
right: 0;
cursor: se-resize;
}
这样,便可见到这些句柄。
原理不多说了,看代码就知道。
5. 绑定事件-开始拖动
以右滑块例,
document.queryOne('.x-resizable-r').on('dragstart', function(e){
showProxy(); // 显示代理
}
document.queryOne('.x-resizable-r').on('dragmove', function(e){
resize(); // 更改代理的大小
});
document.queryOne('.x-resizable-r').on('dragend', function(e){
hideProxy(); // 显示代理
});
function showProxy(){
$('proxy').show(); // 显示代理
$('proxy').setBound( $('elem').getBound() ); // 更改位置和大小 (具体实现见本系列(五))
}
function resize(e){
resizeEl(e, $('proxy'); // 根据e修改大小。
}
function hideProxy(e){
$('proxy').hide(); // 显示代理
resizeEl(e, $('elem'));
}
function resizeEl(e, tg){ // 根据e修改大小。
tg.resizeBy( e.delta );
if({'x-resizable-l':1, 'x-resizable-t':1}[e.target.className]) { // 如果是左上方向,需同时移动偏移位置。
tg.moveBy( e.delta.plus(-1) ); // 移动的方向和大小改变的是相反。
}
}
6. 以上是对 left - top - bottom - right 实现,那角落如何处理(以右下角例)。
其实在上面已经藏着玄机。 当鼠标按下右下角的滑块,其实也按了右滑块,下滑块。所以,把右下角的滑块事件转为右滑块,下滑块的结合(同时进行)
这是 Ext未使用的方法, 有个优点,就是节约代码。
所以上面的代码已经实现了每个角落的事件。
最后说个细节:
鼠标在拖到时,希望保持箭头方向,但除部分浏览器,其它浏览器会随文本更新鼠标样式。
最简单是方法为 设置 document.body.setStyle('cursor', 'resizer-x')
但这时 Chrome 仍然按因 select 更改鼠标 。
Ext 采用 layer 式处理, 即 在拖到前,全局加上 layer(透明,全局) 全部拖动都在 layer 上触发,这样兼容任何浏览器。
resize始终是麻烦的效果。做的时候需要仔细。否则会有各种问题。
浙公网安备 33010602011771号