JavaScript ドラッグ アンド ドロップ効果コード_JavaScript スキル

WBOY
リリース: 2016-05-16 18:57:40
オリジナル
986 人が閲覧しました

このプログラムのプロトタイプは、画像カット エフェクトを作成していたときに作成されました。当時、いくつかの同様のエフェクトを参考にし、muxrwc と BlueDestiny から多くのことを学びました。
整理するたびに気分が良くなりますが、学んだ知識と同じように、どこかに改善の余地があり、どこかに間違いがあり、特定のニーズを実現する必要があることが時々わかります。
単純なドラッグ アンド ドロップだけが必要な人々もいることを考慮して、簡単に学習できるように SimpleDrag の簡略化されたバージョンがあります。
効果プレビュー
追記: maxthon で広告フィルタリングをオンにすると、フィルタリングされてしまう可能性があります (回避する方法があるかどうかはわかりません)。
プログラムの説明
[プログラム原理]
ここでは SimpleDrag を例にして基本原理を説明します。
まず、初期化プログラムでドラッグ アンド ドロップ オブジェクトが必要です。

コードをコピーします コードは次のとおりです。

this.Drag = $(drag);

最初にドラッグ アンド ドロップ オブジェクトに対するマウスの座標を記録する 2 つのパラメーターもあります。
コードをコピー コードは次のとおりです:

this._x = this._y = 0 ;

削除イベントを追加するために使用される 2 つのイベント オブジェクト関数もあります:
コードをコピーします コードは次のとおりです:

this._fM = BindAsEventListener (this, this.Move);
this._fS = Bind(this, this.Stop); 🎜> はそれぞれドラッグプログラムとドラッグ停止プログラムです。
ドラッグ アンド ドロップ オブジェクトの位置は絶対位置である必要があります:



コードをコピー コードは次のとおりです。 this.Drag.style.position = "absolute";

最後に、ドラッグ アンド ドロップの開始プログラムをドラッグ アンド ドロップのマウスダウン イベントにバインドします。 -drop object:
addEventHandler(this.Drag, "mousedown ", BindAsEventListener(this, this.Start));
ドラッグ アンド ドロップ オブジェクト上でマウスが押されると、Start プログラムがトリガーされます。ここでは、ドラッグ アンド ドロップ オブジェクトに対するマウスの座標が記録されます:



コードをコピー コードは次のとおりです:this._x = oEvent.clientX - this.Drag.offsetLeft;
this._y = oEvent.clientY - this.Drag.offsetTop ;


そして、_fM ドラッグ プログラムと _fS stop ドラッグ プログラムをそれぞれドキュメントのマウスムーブ イベントとマウスアップ イベントにバインドします:


コードをコピー コードは次のとおりです。addEventHandler(document, "mousemove", this._fM );
addEventHandler(document, "mouseup", this._fS) );


イベントがウィンドウ ドキュメント全体で有効であることを確認するには、イベントをドキュメントにバインドする必要があることに注意してください。イベントがドラッグ アンド ドロップ オブジェクトにのみバインドされている場合、ドラッグが速すぎて接触できなくなる可能性があります。 。
ドキュメント上でマウスを移動すると、移動プログラムがトリガーされます。ドラッグを実装するプログラムは次のとおりです。
ドラッグアンドドロップオブジェクトに設定する必要がある左と上の値は、現在のマウスの座標値とドラッグ開始時のマウスの相対座標値の差によって取得できます:
this .Drag.style.left = oEvent.clientX - this._x "px";
this.Drag.style.top = oEvent.clientY - this._y "px"
最後にマウスを放すと、ドラッグ アンド ドロップを終了するには、プログラムの停止がトリガーされます。
ここでの主な機能は、スタート プログラムでドキュメントに追加されたイベントを削除することです。
removeEventHandler(document, "mousemove", this._fM);
removeEventHandler(document, "mouseup", this. _fS );
このような単純なドラッグ アンド ドロップ プログラムが完成しました。その他の拡張機能と詳細について説明します。
【ドラッグアンドドロップロック】
ロックには、水平ロック(LockX)、垂直ロック(LockY)、完全ロック(Lock)の3種類があります。
これは比較的簡単です。移動でロックされているかどうかを判断し、完全にロックされている場合は直接戻るだけです。
if(!this.LockX){ this.Drag.style.left = ; }
if(!this.LockY){ this.Drag.style.top = ; }
[トリガーオブジェクト]
トリガー オブジェクトは、ドラッグ アンド ドロップ プログラムをトリガーするために使用され、プログラムの Handle 属性を通じて設定されます。場合によっては、ドラッグ アンド ドロップ オブジェクト全体をトリガーに使用する必要がない場合があります。この場合、トリガー オブジェクトが必要になります。
トリガー オブジェクトを使用した後も、ドラッグ アンド ドロップ オブジェクトは移動されますが、トリガー オブジェクトはドラッグ アンド ドロップをトリガーするために使用されます (一般的な使用法は、トリガー オブジェクトをドラッグ アンド ドロップ オブジェクトに入れることです)。
追記: トリガー オブジェクトのもう 1 つの使用法は、同じハンドルを設定することで、1 つのトリガー オブジェクトで複数のドラッグ アンド ドロップ オブジェクトを同時にドラッグ アンド ドロップすることです。
【範囲制限】
範囲制限を設定するには、まず Limit を true に設定する必要があります。範囲制限には固定範囲制限とコンテナ範囲制限の 2 種類があり、主に Move プログラムで設定します。
原理は、比較した値が範囲を超えた場合、ドラッグ&ドロップしたオブジェクトが設定範囲内に収まるように左と上に設定する値を修正するというものです。
[固定範囲制限]
コンテナの範囲制限とは、ドラッグ&ドロップで上下左右の範囲を指定することです。
各属性の意味は次のとおりです。
上 (mxTop): 上端の限界;
下 (mxBottom): 上端のオフセット高さの限界;
右 (mxRight) ) :left offsetWidth 制限。
範囲の設定が間違っていると、上下または左右が同時に範囲を超える可能性があります。範囲パラメータを修正するための修復プログラムがプログラム内にあります。
修復プログラムはプログラムの初期化と開始プログラムで実行されます。修復プログラムの mxRight と mxBottom を修正します。
this.mxRight = Math.max(this.mxRight, this.mxLeft this.Drag.offsetWidth) ;
this.mxBottom = Math.max(this.mxBottom, this.mxTop this.Drag.offsetHeight);
ここで、mxLeft offsetWidth と mxTop offsetHeight はそれぞれ mxRight と mxBottom の最小範囲値です。
範囲パラメーターに従って移動パラメーターを修正します。
iLeft = Math.max(Math.min(iLeft, mxRight - this.Drag.offsetWidth), mxLeft);
iTop = Math.max(Math) .min( iTop, mxBottom - this.Drag.offsetHeight), mxTop);
左上側には大きな値を、右下側には小さな値を取ります。
【コンテナスコープ制限】
コンテナスコープ制限とは、スコープを一つのcontainer_mxContainerに制限することです。
プログラムは相対位置を使用してコンテナの範囲制限を設定するため、ドラッグ アンド ドロップ オブジェクトを _mxContainer に含める必要があることに注意してください (コンテナの外側にある場合は、絶対位置を使用する必要があり、より面倒になります) ) また、コンテナ空間はドラッグ アンド ドロップ オブジェクトよりも大きいため、これについては説明する必要はありません。
原理は固定範囲制限と似ていますが、範囲パラメータがコンテナの属性に従って設定される点が異なります。
コンテナが設定されると、修復プログラムは自動的に位置を相対位置に設定します:
!this._mxContainer || CurrentStyle(this._mxContainer).position == "relative" || .style.position = "relative");
ps: 最終スタイルを取得するために CurrentStyle が使用されます (詳細については、ここの最終スタイルのセクションを参照してください)。
プログラムの実行前にドラッグアンドドロップオブジェクトの左と上が設定されているが、コンテナが相対に設定されていない場合、相対が自動的に設定されるとシフトが発生するため、プログラムは修復を実行することに注意してください。この状況を防ぐには、初期化中にプログラムを実行します。値を正しく取得するには、相対値を設定する前に offsetLeft と offsetTop を取得する必要があるため、Start プログラムで _x と _y を設定する前に Repair を実行する必要があります。
相対的な配置により、コンテナ スコープの場合、範囲パラメータの上下左右の値はそれぞれ 0、clientHeight、0、clientWidth になります。
clientWidth と clientHeight は、コンテナーの表示部分の幅と高さです (詳細については、ここを参照してください)。
为了容器范围能兼容固定范围的参数,程序中会获取容器范围和固定范围中范围更小的值:
Code
mxLeft = Math.max(mxLeft, 0);
mxTop = Math.max(mxTop, 0);
mxRight = Math.min(mxRight, this._mxContainer.clientWidth);
mxBottom = Math.min(mxBottom, this._mxContainer.clientHeight);
因为设置相对定位的关系,容器_mxContainer设置过后一般不要取消或修改,否则很容易造成移位异常。
【鼠标捕获】
我在一个拖放实例中看到,即使鼠标移动到浏览器外面,拖放程序依然能够执行,仔细查看后发现是用了setCapture。
鼠标捕获(setCapture)是这个程序的重点,作用是将鼠标事件捕获到当前文档的指定的对象。这个对象会为当前应用程序或整个系统接收所有鼠标事件。
使用很简单:
this._Handle.setCapture();
setCapture捕获以下鼠标事件:onmousedown、onmouseup、onmousemove、onclick、ondblclick、onmouseover和onmouseout。
程序中主要是要捕获onmousemove和onmouseup事件。
msdn的介绍中还说到setCapture有一个bool参数,用来设置在容器内的鼠标事件是否都被容器捕获。
容器就是指调用setCapture的对象,大概意思就是:
参数为true时(默认)容器会捕获容器内所有对象的鼠标事件,即容器内的对象不会触发鼠标事件(跟容器外的对象一样);
参数为false时容器不会捕获容器内对象的鼠标事件,即容器内的对象可以正常地触发事件和取消冒泡。
而对于容器外的鼠标事件无论参数是什么都会被捕获,可以用下面这个简单的例子测试一下(ie):
Code


mouseover

<script>document.body.setCapture();</script>


这里的参数是true,一开始body会捕获所有鼠标事件,即使鼠标经过div也不会触发onmousemove事件。
换成false的话,div就可以捕获鼠标事件,就能触发div的onmousemove事件了。
拖放结束后还要使用releaseCapture释放鼠标,这个可以放在Stop程序中:
this._Handle.releaseCapture();
setCapture是ie的鼠标捕获方法,对于ff也有对应的captureEvents和releaseEvents方法。
但这两个方法只能由window来调用,而且muxrwc说这两个方法在DOM2里已经废弃了,在ff里已经没用了。
不过ff里貌似会自动设置取消鼠标捕获,但具体的情形就不清楚了,找不到一个比较详细的介绍,谁有这方面的资料记得告诉我啊。
下面都是我的猜测,ff的鼠标捕获相当于能自动设置和释放的document.body.setCapture(false)。
因为我测试下面的程序,发现ie和ff效果是差不多的:
ie:
Code



<script> <br>document.body.onmousedown=function(){this.setCapture(false)} <br>document.body.onmouseup=function(){this.releaseCapture()} <br>document.onmousemove=function(){aa.innerHTML+=1} <br></script>


ff:
Code



<script> <br>document.onmousemove=function(){aa.innerHTML> <br></html> 🎜>残念ながら、信頼できる情報の参照がなければ、推測することしかできませんが、まだ理解していないことがたくさんあり、後で勉強します。 <br>ff2 ではマウス キャプチャにバグがあることに注意してください。ドラッグ アンド ドロップ オブジェクト内にテキスト コンテンツがなく、ブラウザの外にドラッグ アンド ドロップすると、キャプチャは失敗します。 <br><font size='1px'> などの空のテキストをドラッグ アンド ドロップ オブジェクトに挿入します。これは解決できますが、このバグは ff3 で修正されました。 <br>[フォーカスロスト] <br>通常の状況では、マウス キャプチャでイベントを正常にキャプチャできますが、ブラウザ ウィンドウのフォーカスが失われた場合、キャプチャは失敗します。 <br>フォーカス損失を引き起こす可能性のある操作には、ウィンドウの切り替え (Alt タブを含む)、アラート、ポップアップ、その他のポップアップ フォームが含まれることを一時的にテストしました。 <br>フォーカスを失った場合、ドラッグ アンド ドロップを終了するために Stop プログラムを同時に実行する必要がありますが、フォーカスを失った場合は、mouseup イベントをキャプチャできません。つまり、_fS をトリガーできません。 <br>幸いなことに、IE にはキャプチャが失敗したときにトリガーされる onlosecapture イベントがあります。<br>addEventHandler(this._Handle, "losecapture", this._fS); >そしてそれをStopプログラムに移動します 例外: <br>removeEventHandler(this._Handle, "losecapture", this._fS); <br>ただし、ffには同様のメソッドがありませんが、muxrwcは代わりのwindow.onblurイベントを見つけます。 losscapture なので、Start プログラムで設定できます: <br>addEventHandler(window, "blur", this._fS); <br>Stop プログラムで削除: <br>removeEventHandler(window, "blur", this. _fS); <br>これには window.onblur イベントもあり、losecapture の代わりに window.onblur を使用するとコードを節約できます。 <br>その後、いくつかのテストを行ったところ、基本的に、losecapture をトリガーするあらゆる状況が同時に window.onblur をトリガーし、機能するようであることがわかりました。 <br>そこで、losecapture の代わりに window.onblur を使用するようにプログラムを修正しましたが、テスト後に問題が発生したことがわかりました。alt タブを使用して別のウィンドウに切り替えると、ドラッグは続行できますが、フォーカスは失われるはずです。この時。 。 <br>そこで、テスト コードとプログラム コードを 1 つずつ削除したところ、DTD が使用されている場合、再びフォーカスを取得するまで window.onblur がトリガーされないことがわかりました。 <br>次のコードを使用してテストできます: <br><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1 /DTD/xhtml1-transitional.dtd"> <br><script>window.onblur=function(){alert(1)}</script>
他のプログラムに切り替えた後、再び切り替えます。いずれにしても、IE で window.onblur を使用するのは理想的ではありません。
[デフォルト アクションをキャンセル]
選択状態のテキスト コンテンツ、接続、画像に対するドラッグ アンド ドロップ操作により、システムのデフォルト アクションがトリガーされます。たとえば、IE で画像上でマウスをドラッグすると、禁止された操作状態。このドラッグ アンド ドロップ手順は実行できませんでした。
ただし、IE で setCapture を設定すると、ユーザー インターフェイスを介したマウスによるドラッグ アンド ドロップ操作やコンテンツの選択が禁止されます。
setCapture の後は、ドキュメントのコンテンツをドラッグ アンド ドロップして選択することはできません。たとえば、ondragstart はシステムのデフォルトのアクションを指します。
ただし、setCapture のパラメータが false の場合でも、コンテナ内のオブジェクトは引き続きイベントをトリガーできるため (詳細については、「マウス キャプチャ」セクションを参照)、setCapture のパラメータを true に設定するか、デフォルト値を維持する必要があります。
ffのマウスキャプチャにはこの機能がありませんが、preventDefaultを使用してイベントのデフォルトアクションをキャンセルすることで解決できます:
oEvent.preventDefault();
ps: PreventDefault はマウスアップ損失を引き起こしますが、ff3 のテストでは見つかりませんでした。マウスアップ損失を見つけたら、必ず教えてください。
【選択のクリア】
setCapture 設定後はつまりコンテンツの選択が禁止されますが、設定前に選択されていたコンテンツはクリアされず、設定後は他の方法でコンテンツを選択することもできます。
の場合たとえば、Ctrl a を使用してコンテンツを選択します。
追記: onkeydown、onkeyup、onkeypress イベントはマウス キャプチャの影響を受けません。
ff はマウスダウン時に元の選択コンテ​​ンツをクリアできますが、マウスをドラッグして Ctrl + を押してもコンテンツの選択は継続されます。
ただし、システムのデフォルトのアクションをキャンセルした後は、この選択はドラッグ アンド ドロップ操作には影響しません。この設定は主にエクスペリエンスを向上させるためのものです。
以前は、ドラッグアンドドロップオブジェクトの選択を無効にする方法を使用して目的を達成しました。つまり、IEのドラッグアンドドロップオブジェクトのonselectstartをfalseを返すように設定し、スタイルMozUserSelect(css)を設定しました。 :-moz-user-select) を FF で none にします。
但这种方法只能禁止拖放对象本身被选择,后来找到个更好的方法清除选择,不但不影响拖放对象的选择效果,还能对整个文档进行清除:
ie:document.selection.empty()
ff:window.getSelection().removeAllRanges()
为了防止在拖放过程中选择内容,所以把它放到Move程序中,下面是兼容的写法:
window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
【margin】
还有一个情况,当拖放对象设置了margin,那么拖放的时候就会错位(给SimpleDrag的拖放对象设置margin就可以测试)。
原因是在Start程序设置_x和_y时是使用offset获取的,而这个值是包括margin的,所以在设置left和top之前要减去这个margin。
但如果在Start程序中就去掉margin那么在Move程序中设置范围限制时就会计算错误,
所以最好是在Start程序中获取值:
this._marginLeft = parseInt(CurrentStyle(this.Drag).marginLeft) || 0;
this._marginTop = parseInt(CurrentStyle(this.Drag).marginTop) || 0;
在Move程序中设置值:
this.Drag.style.left = iLeft - this._marginLeft + "px";
this.Drag.style.top = iTop - this._marginTop + "px";
要注意margin要在范围修正之后再设置,否则会错位。
【透明背景bug】
在ie有一个透明背景bug(不知算不算bug),可以用下面的代码测试:
Code






点击div的背景会触发不了事件(点击边框或div里面的对象是可以触发的)。
到底什么时候会出现这个bug呢,再用下面的代码测试:
Code











测试代码中我把背景颜色(包括body)设成灰色,首先可以看出在蓝色div(测试对象)内只要触发点是在灰色上面,就能触发事件;相反,在其他不是背景的地方,即使是边框、图片,也不能触发事件。
就像是把灰色的背景的补到蓝色div上来,而且仅仅是背景能这样,多奇怪的设定啊。
这里要说明的是body比较特别,不管背景是不是透明,只要触发点是直接在body上就能触发事件。
我的结论是如果触发事件的对象背景是透明的,而事件的触发点不在对象内的元素上,也不是直接在body上,而且透明背景外没有非透明背景的话,那么事件触发就会失败。
这个结论写得不太好,因为我都不知改怎么表达这奇怪的设定,希望各位能明白。
ps:这里设置图片背景跟颜色背景效果是一样的。
那最好解决的方法就是给对象设一个非透明背景,但有时需求正好是要透明的,那怎么办呢?
首先想到的是加上背景色后设置完全透明,但这样连边框,容器内的对象等都完全透明了,不够好。
如果能保证触发点直接在body或非背景上也可以,如果这个也不能保证呢?
我想到的一个解决方法是在容器里面加一个层,覆盖整个容器,并设置背景色和完全透明:
Code
with(this._Handle.appendChild(document.createElement("div")).style){
width = height = "100%"; backgroundColor = "#fff"; filter = "alpha(opacity:0)";
}
到这里又不得不说ie6的一个渲染bug,用下面的代码测试(ie6):
Code




<script>setTimeout("aa.style.height=200",0)</script>
ie7 その結果、内側のdivの高さを100%に設定しているのに、外側のdivの高さを変更すると、何らかの理由で埋まっていないことがわかります。
この div がドラッグ オブジェクトで、突然その半分がドラッグできなくなった場合、それは間違いなく機能しません。
幸いなことに、BlueDestiny が解決策を教えてくれました。オブジェクトのオーバーフローを非表示に設定すると、内部の div が自動的に再び埋められます。
BlueDestiny は、「この問題の原因は、IE6 のレンダリングの問題です。特定の CSS プロパティを通じて、DOM を変更して再度レンダリングすることができます。
このバグは、zoom を使用することで解決することもできます。」と述べています。 dom を再レンダリングすることです。
このバグがプログラムに現れることがわかった場合は、プログラムのオプション パラメーター Transparent を true に設定すると、そのようなレイヤーが自動的に挿入されます。
ここで少し知識を加えます。注意していただければ、上記のテスト コードで HTML の背景色を設定していることがわかります。
この背景色を削除すると、背景色がページ全体に設定されることがわかりますが、ページの背景色を設定するために常に body が使用されてきましたが、ここでは疑問が生じます。 bodyは赤枠の部分ですが、なぜ設定するのでしょうか? 背景色はページ全体に適用でき、htmlの背景色を設定すると「正常に」表示されます。
この理由は、CSS21 の w3c 標準の背景セクションからわかります。
ただし、HTML ドキュメントの場合、HTML ドキュメントの場合は、作成者が HTML 要素ではなく BODY 要素の背景を指定することをお勧めします。そのルート HTML 要素の計算値が「background-color」の「transparent」、「background-image」の「none」である場合、ユーザー エージェントは代わりに、その HTML 要素の最初の BODY 要素の子からのこれらのプロパティの計算値を使用する必要があります。キャンバスの背景をペイントする必要があり、その BODY 要素の背景をペイントすることはできません。このような背景は、ルート要素のみにペイントされる場合と同じ位置に固定されている必要があります。これは、XHTML ドキュメントには適用されません。 🎜>我英それはひどいので、翻訳してみてください:
HTML ドキュメントの場合、作成者 (これはブラウザのプロデューサーに対して) が HTML 要素の代わりに BODY 要素の背景を使用することをお勧めします。 HTML ドキュメント (HTML 要素) のルート要素の 'background-color' が 'transparent' で、'background-image' が 'none' の場合 (これら 2 つはたまたまデフォルト値です)、HTML 要素は背景の設定時に取得される最初の BODY 子要素の属性値。その要素の背景は表示されなくなります。
最後の 2 つの文は理解するのが難しいですが、理由を説明するには十分です。
【iframe】
ページに iframe が埋め込まれている場合、iframe 上でのマウスキャプチャに問題が発生するため注意が必要です。
たとえば、ドラッグ アンド ドロップ コンテナ内の iframe 上ですばやく移動してドロップした場合、またはコンテナの外側の iframe にマウスをドラッグした場合、とにかくマウスは iframe 上にあります (他の iframe がないことに注意してください)
まず、マウスが iframe 上にある場合、ドラッグすることはできませんが、ウィンドウのぼかしはもちろん、losecapture もトリガーされません。これは IE と FF で同じです。
次に、IE では、iframe をさらに数回こすると、IE が停止する可能性があります (理由は不明)。
ここに私が考えたいくつかの方法があります:
ページの iframe を非表示にします。これは比較的単純ですが、iframe 内の重要な情報も非表示になる可能性があり、ページ レイアウトの位置がずれる可能性があります。ユーザー エクスペリエンスが低い。
iframe にマウスを移動した後、ドラッグ アンド ドロップをキャンセルする。これは難しいことではないが、ユーザー エクスペリエンスも良くない。
各 iframe は透明なレイヤーで覆われているため、非常に悪い。各 iframe の位置とサイズを計算する必要があるため、ページ全体を透明レイヤーで覆うのが比較的簡単です。
LightBox コンテンツの表示効果を模倣するために作成したオーバーレイは、ここで適用できます。まず、透明なオーバーレイをインスタンス化します。
var ol = new OverLay({ Opacity: 0 }); 次に、ol を追加します。 onStart イベントと onStop イベントで Show() と ol.Close() を使用してオーバーレイを表示または非表示にします。そのため、iframe 内でドラッグ アンド ドロップがトリガーされない限り、問題はありません。
他にもっと良い方法がある場合は、アドバイスをお願いします。
とりあえずはここまでです。ちょっとしたドラッグ アンド ドロップでこれほど多くの知識が得られるとは思いませんでした。
スクロールなどについてはまだ検討していません。必要に応じて後で検討します。

使用説明
インスタンス化の際に必要なパラメータはドラッグ アンド ドロップ オブジェクトの 1 つだけです:
new SimpleDrag("idDrag");
には次のオプションのパラメータと属性があります。
属性: デフォルト値 // 説明
ハンドル: "", // トリガーオブジェクトを設定します (設定されていない場合はオブジェクトのドラッグアンドドロップを使用します)
Limit: false, // 範囲制限を設定するかどうか (それは本当です。次のパラメータが便利です。負の数も可能です)
mxLeft:0,//左制限
mxRight:9999,//右制限
mxTop:0,//上制限
mxBottom:9999,//下限
mxContainer:"",//コンテナ内の制限を指定
LockX:false,//水平方向のドラッグ&ドロップをロックするかどうか
LockY:false,/ /垂直ドラッグアンドドロップをロックするかどうか
Lock:false, //ロックするかどうか
Transparent: false, //透明にするかどうか
onStart:function(){},//開始時に実行move
onMove:function(){},//移動時に実行
onStop:function(){}//移動終了時に実行
属性 Drag は、透明なドラッグ アンド ドロップ オブジェクトです。また、mxContainer は初期化後に設定できません。

プログラム コード
コード
コードをコピー コードは次のとおりです。

var isIE = (document.all) ? true : false;
var $ = function (id) {
return "string" == typeof id ? document.getElementById(id) : id;
};
var Class = {
create: function() {
return function() { this.initialize.apply(this, argument); }
}
}
var Extend = function(destination, source) {
for (source の var プロパティ) {
destination[property] = source[property];
}
}
var Bind = function(object, fun) {
return function() {
return fun.apply(object, argument);
}
}
var BindAsEventListener = function(object, fun) {
return function(event) {
return fun.call(object, (event || window.event));
}
}
var CurrentStyle = function(element){
return element.currentStyle || document.defaultView.getComputedStyle(要素, null);
}
function addEventHandler(oTarget, sEventType, fnHandler) {
if (oTarget.addEventListener) {
oTarget.addEventListener(sEventType, fnHandler, false);
} else if (oTarget.attachEvent) {
oTarget.attachEvent("on" sEventType, fnHandler);
} else {
oTarget["on" sEventType] = fnHandler;
}
};
function removeEventHandler(oTarget, sEventType, fnHandler) {
if (oTarget.removeEventListener) {
oTarget.removeEventListener(sEventType, fnHandler, false);
} else if (oTarget.detachEvent) {
oTarget.detachEvent("on" sEventType, fnHandler);
} else {
oTarget["on" sEventType] = null;
}
};
//拖放程序
var Drag = Class.create();
Drag.prototype = {
//拖放对象
initialize: function(drag, options) {
this.Drag = $(drag);//拖放对象
this. _x = this._y = 0;//记录鼠标相对拖放出オブジェクトの位置
this._marginLeft = this._marginTop = 0;//记录margin
//イベント对オブジェクト(定置撤去イベント用)
this._fM = BindAsEventListener(this, this.Move);
this._fS = Bind(this, this.Stop);
this.SetOptions(オプション);
this.Limit = !!this.options.Limit;
this.mxLeft = parseInt(this.options.mxLeft);
this.mxRight = parseInt(this.options.mxRight);
this.mxTop = parseInt(this.options.mxTop);
this.mxBottom = parseInt(this.options.mxBottom);
this.LockX = !!this.options.LockX;
this.LockY = !!this.options.LockY;
this.Lock = !!this.options.Lock;
this.onStart = this.options.onStart;
this.onMove = this.options.onMove;
this.onStop = this.options.onStop;
this._Handle = $(this.options.Handle) || this.ドラッグ;
this._mxContainer = $(this.options.mxContainer) || null;
this.Drag.style.position = "絶対";
//透明
if(isIE && !!this.options.Transparent){
//充填拖放对象
with(this._Handle.appendChild(document.createElement("div") ).style){
幅 = 高さ = "100%";背景色 = "#fff";フィルター = "アルファ(不透明度:0)";
}
}
//修正范围
this.Repair();
addEventHandler(this._Handle, "mousedown", BindAsEventListener(this, this.Start));
},
//設置默认プロパティ
SetOptions: function(options) {
this.options = {//默认值
Handle: "",//設置触発行对象(不
Limit: false,//設置范围制限(true の場合は下面パラメータ有用、可数)
mxLeft: 0,//左边制限
mxRight: 9999, //右边制限
mxTop: 0,//上边制限
mxBottom: 9999,//下边制限
mxContainer: "",//指定制限在容器内
LockX: false,//锁定水平方向拖放かどうか
LockY: false,//锁定垂直方向かどうか
Lock: false,//锁定かどうか
Transparent: false,//透明かどうか
onStart: function( ){},//移動開始時間の実行
onMove: function(){},//移動時間の開始
onStop: function(){}//移動時間の終了
};
Extend(this.options, options || {});
},
//準備备拖アニメーション
Start: function(oEvent) {
if(this.Lock){ return;
this.Repair();
//记录ネズミ标相对拖放オブジェクトの位置
this._x = oEvent.clientX - this.Drag.offsetLeft;
this._y = oEvent.clientY - this.Drag.offsetTop;
//记录マージン
this._marginLeft = parseInt(CurrentStyle(this.Drag).marginLeft) || 0;
this._marginTop = parseInt(CurrentStyle(this.Drag).marginTop) || 0;
//mousemove時移動mouseup時停止
addEventHandler(document, "mousemove", this._fM);
addEventHandler(document, "mouseup", this._fS);
if(isIE){
//焦点丢失
addEventHandler(this._Handle, "losecapture", this._fS);
//設置ネズミ标捕获
this._Handle.setCapture();
}else{
//焦点丢失
addEventHandler(window, "blur", this._fS);
//默认動作を阻止します
oEvent.preventDefault();
};
//附加程序
this.onStart();
},
//補正範囲
Repair: function() {
if(this.Limit){
//補正誤差範囲パラメータ
this.mxRight = Math.max(this.mxRight , this.mxLeft this.Drag.offsetWidth);
this.mxBottom = Math.max(this.mxBottom, this.mxTop this.Drag.offsetHeight);
//コンテナがある場合、位置は相対位置に設定し、オフセットを取得する前に
を設定します。this._mxContainer || CurrentStyle(this._mxContainer).position == "relative" || (this._mxContainer.style.position = "relative") ;
}
},
//ドラッグ
移動: function(oEvent) {
//ロックされているかどうかを判断します
if(this.Lock){ this.Stop( ); return; } ;
//選択をクリア
? window.getSelection().removeAllRanges() : document.selection.empty(); iLeft = oEvent.clientX - this._x, iTop = oEvent.clientY - this._y
//範囲制限を設定します
if(this.Limit){
//範囲パラメータを設定します
var mxLeft = this.mxLeft , mxRight = this.mxRight, mxTop = this.mxTop, mxBottom = this.mxBottom;
//コンテナが設定されている場合は、範囲パラメータを修正します
if(!!this._mxContainer) {
mxLeft = Math.max(mxLeft, 0);
mxTop = Math.max(mxTop, 0);
mxRight = Math.min(mxRight, this._mxContainer.clientWidth); mxBottom = Math.min( mxBottom, this._mxContainer.clientHeight);
};
//移動パラメータを修正します
iLeft = Math.max(Math.min(iLeft, mxRight - this.Drag. offsetWidth), mxLeft);
iTop = Math.min(iTop, mxBottom - this.Drag.offsetHeight), mxTop);
}
// 位置と正しいマージンを設定します
if(!this.LockX ){ this.Drag.style.left = iLeft - this._marginLeft "px"; }
if(!this.LockY){ this.Drag.style.top = iTop - this. _marginTop "px"; }
//追加プログラム
this.onMove();
//ドラッグを停止
Stop: function() {
//イベントを削除
removeEventHandler( document, "mousemove", this._fM);
removeEventHandler(document, "mouseup", this._fS);
if(isIE){
removeEventHandler(this._Handle, " losscapture", this._fS);
this._Handle.releaseCapture();
}else{
removeEventHandler(window, "blur", this._fS);
};
/ /追加プログラム
this.onStop();
}
};


テストコード:
コード



コードをコピーします
コードは次のとおりです: #idContainer{ border:10px width:600px; :300px;}
# idDrag{ ボーダー:5px ソリッド #C4E3FD; 幅:50px; 左:50px;}
#idHandle{カーソル:高さ: :25px; オーバーフロー:非表示;}

id="idHandle">


🎜>
>
>

ドラッグ アンド ドロップのステータス: 開始されていません< ;/span>
< ;script>
varrag = new Drag("idDrag", { mxContainer: "idContainer", ハンドル: "idHandle", Limit: true,
onStart: function(){ $("idShow").innerHTML = "ドラッグ アンド ドロップを開始"; },
onMove: function(){ $("idShow").innerHTML = "left:" this.Drag.offsetLeft ";top:" this.Drag.offsetTop; },
onStop: function(){ $("idShow").innerHTML = "ドラッグ アンド ドロップを終了" }
$("idReset"); onclick = function(){
drag.Limit = true;
drag.mxLeft =rag.mxTop = 0;
drag.mxBottom = 9999; LockY = ドラッグ.ロック = false;
}
$("idLock").onclick = function(){ ドラッグ.Lock = true; }
$("idLockX").onclick = function() { ドラッグ.LockX = true; }
$("idLockY").onclick = function(){ ドラッグ.LockY = true; }
$("idLimit").onclick = function(){ = ドラッグ.mxBottom = 200;ドラッグ.リミット = true; }
$("idLimitOff").onclick = function(){ ドラッグ.リミット = false;



ソース:php.cn
前の記事:マウスを移動すると、表示効果のリストが拡大されます_ナビゲーション メニュー ネチズンは歌うのが大好きです 次の記事:全選択、全選択解除、機能コード削除のための包括的なJSチェックボックス_JavaScriptスキル
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
最新の問題
関連トピック
詳細>
人気のおすすめ
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート