もちろん、js ライブラリのソース コードを勉強することもできますし、自分でホイールを発明して試してみることもできます。そのプロセスは非常に興味深いものです... 次に、ページ要素のドラッグ アンド ドロップ機能を実装します
さっそく実装を始めましょう。ドラッグ オブジェクトの初期化に使用されるトップレベルのメソッドから始めましょう。このメソッドは次のように宣言されます。
function DragObject(cfg)
cfg に渡すオブジェクトを使用します。ここでは、Extjs の構成プロパティに少し似ています
el は、特定の要素の ID を直接 DOM オブジェクトにすることもできます。この例では、LowerBound と UpperBound を使用して要素をドラッグできます。これらは両方とも Position オブジェクトです。このオブジェクトのカプセル化については、次の関数を分析します。心配しないでください。)、入力がない場合、startCallback、moveCallback には制限がありません。 、endCallback はすべてコールバック関数で、attachLater は true か false です。よく分からない場合は調べてください。以下の分析の後、すぐに理解できると思います...
function Position(x, y) ) {
this.X = x;
thix.Y = y;
}
Position .prototype = {
コンストラクター: Position,
add : function(val) {
var newPos = new Position(this.X, this.Y);
if (val) {
newPos.X = val.Y;
return newPos(this.X, this.Y);
if (val) {
newPos.X -= val. >return
},
min : function(val) {
var newPos = new Position(this.X, this.Y);
if (val) {
newPos.X = this.X > X : this.X;
newPos.Y = this.Y > val.Y : this.Y>}
return
},
max : 関数(val) {
var newPos = new Position(this.X, this.Y);
if (val) {
newPos.X = this.X val.X ? this.X;
newPos.Y = this.Y ? val.Y;
return
},
bound : function( lower, upper) {
var newPos = this.max( lower);
return newPos. min(upper); 🎜>var newPos = new Position(this.X, this.Y);
if (isNaN(newPos.X))
newPos.X = 0;
if (isNaN(newPos.Y))
newPos.Y = 0;
return newPos;
if(typeof el == 'string')
el = document.getElementById(el);
el.style.left = this.X 'px' ;
el.style.top = this.Y 'px'
}
};座標点の単純なパッケージ。x、y 座標の 2 つの値を保存します。加算メソッドと減算メソッドを使用して他の座標点との演算を実行し、計算された新しい座標点をその関数として返します。名前が示すように、他の座標点と比較して小さい方の合計を返すために使用されます。 education.bound メソッドの値は、制限された範囲内の座標点を返します。属性 x と y は数値型で、それ以外の場合は 0 に設定されます。最後の適用メソッドは、属性 x と y を要素 style.left と top に適用することです。次に、残りのコードの大部分を取り出して調べました。
コードをコピー
コードは次のとおりです:
function DragObject(cfg) {
var el = cfg.el,
attachEl = cfg.attachEl,
lowerBound = cfg. lowerBound,
upperBound = cfg.upperBound,
startCallback = cfg.startCallback、
moveCallback = cfg.moveCallback、
endCallback = cfg.endCallback、
attachLater = cfg.attachLater;
if(typeof el == 'string')
el = document.getElementById(el);
if(!el) return;
if( lowerBound != 未定義 && upperBound != 未定義) {
var tempPos = lowerBound.min(upperBound);
upperBound = lowerBound.max(upperBound);
lowerBound = tempPos;
}
varcursorStartPos、
elementStartPos、
ドラッグ = false、
リスニング = false、
処分 = false;
functionragStart(eventObj) {
if(ドラッグ || !リスニング || 破棄) return;
ドラッグ = true;
if(startCallback)
startCallback(eventObj, el);
cursorStartPos =AbsoluteCursorPosition(eventObj);
elementStartPos = new Position(parseInt(getStyle(el, 'left')), parseInt(getStyle(el, 'top')));
elementStartPos = elementStartPos.check();
hookEvent(document, 'mousemove',ragGo);
hookEvent(document, 'mouseup',ragStopHook);
return cancelEvent(eventObj);
}
functionragGo(e) {
if(!dragging ||Dispose) return;
var newPos =AbsoluteCursorPosition(e);
newPos = newPos.add(elementStartPos)
.subtract(cursorStartPos)
.bound( lowerBound, upperBound);
newPos.apply(el);
if(moveCallback)
moveCallback(newPos, el);
return cancelEvent(e);
}
関数ドラッグストップフック(e) {
ドラッグストップ();
return cancelEvent(e);
}
functionragStop() {
if(!ドラッグ || 処分) return;
unhookEvent(document, 'mousemove',ragGo);
unhookEvent(document, 'mouseup',ragStopHook);
cursorStartPos = null;
elementStartPos = null;
if(endCallback)
endCallback(el);
ドラッグ = false;
}
this.startListening = function() {
if(listening || 破棄) return;
リスニング = true;
hookEvent(attachEl, 'mousedown',ragStart);
};
this.stopListening = function(stopCurrentDragging) {
if(!listening || 破棄)
return;
unhookEvent(attachEl, 'mousedown',ragStart);
リスニング = false;
if(stopCurrentDragging && ドラッグ)
dragStop();
};
this.dispose = function() {
if(dispose) return;
this.stopListening(true);
el = null;
attachEl = null;
lowerBound = null;
upperBound = null;
startCallback = null;
moveCallback = null;
endCallback = null;
処分 = true;
};
this.isDragging = function() {
ドラッグを戻す;
};
this.isListening = function() {
リスニングを返す;
};
this.isDissolved = function() {
破棄された戻り値;
};
if(typeofattachEl == 'string')
attachEl = document.getElementById(attachEl);
// 結果が存在しない場合、Dom オブジェクトに到達しない場合、その Dom オブジェクトに到達しない場合、
if(!attachEl)attachEl = el;
if(!attachLater)
this.startListening();
}
その中のいくつかの未解決の方法、往来下分析的過程中、会一给出....
我们先通过cfg来使用elおよびattachEl指向実際の Dom オブジェクト。attachEl が配置されていないか、該当要素が見つからない場合は、el が置き換えられます。 同時に、拖拽中に必要な量をいくつか用意しました。 cursorStartPos は、マウスの下の開始開始時刻のマウスの座標点を保存するために使用されます。 elementStartPos は、元素の開始時の開始点を保持するために使用されます。ドラッグ、リスニング、処分はいくつかの状態です。リスニング: 指ドラッグ オブジェクトの有無正在监听拖拽开開始イベント。ドラッグ: 元素是否正在被拖拽。破棄されました: ドラッグ オブジェクトは処理されました。再被処理できません。
代暗号の最後に、私は結果attachLaterがtrueでないことを確認しました、那么就调用startListening、これはドラッグオブジェクト内のパブリックメソッド定義です、让我们看下它的实现
this.startListening = function() {
if(listening ||処分) return;
リスニング = true;
hookEvent(attachEl, 'mousedown',ragStart);
};
前两行就是做个判断、如果已经开開始对拖拽事进行监听或者清理过了、就什么都不直做還。 リスニング状態が true の場合は、addEl のマウスダウン イベントに接続された dragStart 関数の開始が表示されます。 ここにhookEvent関数、我们来看它的样子:
関数フックイベント(el, イベント名, コールバック) {
if(typeof el == 'string')
el = document.getElementById(el)
if(!el); ;
if(el.addEventListener)
el.addEventListener(イベント名, コールバック, false);
else if (el.attachEvent)
el.attachEvent('on' イベント名, コールバック); 🎜>}
実際には、要素イベントを監視するためのクロスブラウザー パッケージを作成するだけです。同じ unhookEvent メソッドは次のとおりです。
function unhookEvent(el,eventName, callback) {
if(typeof el == 'string ')
el = document.getElementById(el);
if(!el) return;
if(el.removeEventListener)
el.removeEventListener(eventName, callback, false); else if(el.detachEvent)
el.detachEvent('on'eventName, callback);
}
次に、dragStart 関数の実装を見てみましょう。ドラッグ オブジェクトのプライベート関数
functionragStart (eventObj) {
if(ドラッグ || !listening || 破棄) return;
dragging = true;
if(startCallback)
startCallback(eventObj, el); (eventObj);
elementStartPos = new Position(parseInt(getStyle(el, 'left')), parseInt(getStyle(el, 'top'))); >hookEvent(document, 'mousemove', dumpHook);
return cancelEvent(eventObj);
この関数AttachEl が指す DOM オブジェクトが Mousedown イベントをキャプチャした後に呼び出されます。まず、ドラッグが進行中の場合、またはドラッグ イベントが監視されていない場合、ドラッグ オブジェクトがドラッグに適した状態であることを確認します。 「最後の処理」が完了したら、何も行いません。すべてが OK の場合は、ドラッグ ステータスを true に設定し、startCallback が定義されている場合は、mousedown イベントと el をパラメータとして呼び出します。マウスの絶対位置を特定し、それをcursorStartPosに保存します。次に、ドラッグされた要素の現在の上部と左側に移動し、それをPositionオブジェクトにカプセル化して、elementStartPosに保存します。 elementStartPos の属性は有効です。1 つは、mousemove イベントで、ドラッグの終了を表し、dragGo 関数が呼び出されます。ここでの el やattachEl など、ドラッグする要素ではなくイベントがドキュメントにバインドされているのはなぜなのか疑問に思われるかもしれませんが、要素への直接の Binding イベントを考慮すると、ブラウザの遅延により効果が影響を受ける可能性があります。したがって、イベントをドキュメントに直接バインドします。本当に理解していない場合は、おそらく影響は大きくありません。P.... 最後の文を読んでください cancelEvent(eventObj)
コードをコピーします
コードは次のとおりです。
return false;
}
はバブリングを停止し、デフォルトのイベントを防ぐために使用されます。これはセキュリティ上の考慮事項として理解できます。まず、absoluteCursorPosition を見て、次に getStyle を見てみましょう。
コードをコピーします
コードは次のとおりです。
functionAbsoluteCursorPosition(e) {
このメソッドはブラウザ内のマウスの絶対位置を取得するためにのみ使用されます。スクロール バーを考慮してください
コードをコピー
コードは次のとおりです以下のように:
function getStyle(el, property) {
if(typeof el == 'string')
el = document.getElementById(el);
if(!el || !property ) 戻り値;
var value = el.style[property];
if(!value) {
if(document.defaultView && document.defaultView.getComputedStyle) {
var css = document.defaultView .getComputedStyle(el, null);
value = css ? css.getPropertyValue(property) : null;
} else if (el.currentStyle) {
value = el.currentStyle[property]; >}
}
戻り値 == 'auto' ? '' : value;
}
要素の CSS 属性値を取得するために使用されます。したがって、スタイルは関係ありません。インラインで記述されているか、CSS で定義されているかにかかわらず、正しい値を取得することができます。もちろん、次のメソッドは実際にドラッグ アンド ドロップを処理します。 work:ragGo
functionragGo(e) {
if(!ドラッグ || 処分) return ;
var newPos = abstractCursorPosition(e);
newPos = newPos.add(elementStartPos)
.subtract(cursorStartPos)
.bound( lowerBound) 、upperBound);
if(moveCallback)
return
}
このメソッドは他のメソッドと同様に複雑ではありません。最初にステータスを確認し、ドラッグされていない場合、またはクリーンアップされている場合は、何も実行しません。マウス、要素の初期位置、マウスの初期位置、および結果点を計算するための制限された範囲 (upperBound、 lowerBound を設定する場合) apply メソッドを通じて、計算された座標を要素 style.top に割り当てます。 moveCallback が設定されている場合は、ドラッグ要素にその位置を決定させます。最後に、cancelEvent が来ます...ここでの新しい座標操作は、Position の各メソッドであるため、jquery の操作に似ています。オブジェクトは Position オブジェクトを返します... また、dragStart には、dragStopHook メソッドもあります
dragStop();
return cancelEvent( e);
}
関数dragStop() {
if(!ドラッグ ||破棄) return;
unhookEvent(document, 'mouseup',ragStopHook);
cursorStartPos = null; (endCallback)
endCallback(el);
dragging = false;
重要なのは、最初に dragStop メソッドを確認することです。 OK、イベントバインディングmousemoveとmouseupを削除し、ドラッグが終了したらcursorStartPosとelementStartPosの値を解放します。endCallbackを設定した後、それを呼び出し、最後にドラッグステータスをfalseに設定します。最後に、使用されるパブリック メソッドが指定されます。
コードをコピー
コードは次のとおりです:
dragStop();
};
this.dispose = function() {
if (dispose) return;
el = null;
lowerBound = null;
moveCallback = null; 🎜>処分 = true;
};
this.isDragging = function() {
ドラッグを返す;
this.isListening = function() {
リスニングを返す
};
this.isDissolved = function() {
returnDispose
};
stopListening は、ドラッグをリッスンするマウスダウン イベントを削除し、リスニングを設定します。 false をリッスンする状態。よく知られている stopCurrentDragging メソッドは、ドラッグ オブジェクトをドラッグしたくない場合に使用されます。次の 3 つの小さなメソッドを呼び出します。 isDragging、isListening、isDissolved を一目で確認して、関連するステータスを返すことができます。最後に、ソース コードへのドロップダウン リンクを提供します
ダウンロードしてクリックしてください
メッセージを残してコミュニケーションする友達を歓迎します。