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始終是麻煩的效果。做的時候需要仔細。否則會有各種問題。