ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript CSS改造学習 第6章 ドラッグ&ドロップ_基礎知識

JavaScript CSS改造学習 第6章 ドラッグ&ドロップ_基礎知識

WBOY
WBOYオリジナル
2016-05-16 18:34:07870ブラウズ

例のボックスの # リンクがアクティブな場合 (Tab キーと Enter キー、またはマウスのクリック)、矢印キーを使用してこの要素をドラッグできます。次に Enter または Esc をクリックして解放します。 (これらのキーは自由に変更してください。リリース キーを何に設定すればよいかわからないので、Enter と Esc が機能します)

を使用する

1. 記事の後ろにドラッグドロップオブジェクトをコピーします。

2. ここで必要な addEventSimple 関数とremoveEventSimple 関数をコピーします。

3. keyHTML 属性と keySpeed 属性を設定します (後述)。

4. ドラッグする要素に位置属性 (絶対または固定) があることを確認します。

5. すべてのドラッグ可能な要素をオブジェクトの initElement 関数に送信します。オブジェクトまたはオブジェクト ID の文字列を送信できます。例:

dragDrop.initElement('test');<br>dragDrop.initElement(document.getElementById('test2'));

6. 要素がドラッグされると、コードはドラッグされたクラスを自動的に追加します。いくつかの CSS 効果を追加できます。

7. ユーザーが要素を解放した後に何かをしたい場合は、releaseElement に独自の関数を追加できます。

プロパティ

2 つのプロパティを設定する必要があります。

keyHTML には、ドラッグする必要がある要素のキーボードからアクセスできるリンクのコンテンツが含まれています。 HTML をシンプルに保つために、シンプルなスタイルを持つクラスのみを追加します。 HTML は自由に構成できますが、キーボード ユーザーがドラッグ イベントをトリガーするには、フォーカスが必要なリンクが必要であることに注意してください。

keySpeed は、キーボードのドラッグの速度と、キーが押されるたびに移動するピクセル数を設定するために使用されます。私は 10 に設定するのが好きですが、他の値を試すこともできます。

ここにはさらに 7 つのプロパティがありますが、それらはすべてコード内にあります。これらは初期化中にすべて未定義に設定され、対応する関数によって設定されます。

オブジェクトをドラッグ


次のオブジェクトをページにコピーします。addEventSimple と RemoveEventSimple を忘れないでください。

コードをコピー コードは次のとおりです:

dragDrop = {
keyHTML: '#',
keySpeed: 10, // キーを押すごとのピクセルイベント
initialMouseX: 未定義、
initialMouseY: 未定義、
startX: 未定義、
startY: 未定義、
dXKeys: 未定義、
dYKeys: 未定義、
draggObject:未定義、
initElement: function (要素) {
if (typeof element == 'string')
element = document.getElementById(element);
element.onmousedown =ragDrop.startDragMouse;
element.innerHTML =ragDrop.keyHTML;
var links = element.getElementsByTagName('a');
var lastLink = links[links.length-1];
lastLink.relativeElement = 要素;
lastLink.onclick =ragDrop.startDragKeys;
},
startDragMouse: function (e) {
dragDrop.startDrag(this);
var evt = e ||ウィンドウ.イベント;
dragDrop.initialMouseX = evt.clientX;
dragDrop.initialMouseY = evt.clientY;
addEventSimple(document,'mousemove',dragDrop.dragMouse);
addEventSimple(document,'mouseup',dragDrop.releaseElement);
false を返します。
},
startDragKeys: function () {
dragDrop.startDrag(this.popularElement);
dragDrop.dXKeys = ドラッグドロップ.dYKeys = 0;
addEventSimple(document,'keydown',dragDrop.dragKeys);
addEventSimple(document,'keypress',dragDrop.switchKeyEvents);
this.blur();
false を返します。
},
startDrag: function (obj) {
if (dragDrop.draggedObject)
dragDrop.releaseElement();
dragDrop.startX = obj.offsetLeft;
dragDrop.startY = obj.offsetTop;
dragDrop.draggedObject = obj;
obj.className = 'ドラッグ';
},
dragMouse: function (e) {
var evt = e ||ウィンドウ.イベント;
var dX = evt.clientX -ragDrop.initialMouseX;
var dY = evt.clientY -ragDrop.initialMouseY;
dragDrop.setPosition(dX,dY);
false を返します。
},
dragKeys: function(e) {
var evt = e ||ウィンドウ.イベント;
var key = evt.keyCode;
スイッチ (キー) {
case 37: // left
case 63234:
dragDrop.dXKeys -=ragDrop.keySpeed;
休憩;
ケース 38: // 上
ケース 63232:
dragDrop.dYKeys -=ragDrop.keySpeed;
休憩;
ケース 39: // 右
ケース 63235:
dragDrop.dXKeys =ragDrop.keySpeed;
休憩;
case 40: // down
case 63233:
dragDrop.dYKeys =ragDrop.keySpeed;
休憩;
ケース 13: // 入力
ケース 27: // エスケープ
dragDrop.releaseElement();
false を返します。
デフォルト:
trueを返します。
}
dragDrop.setPosition(dragDrop.dXKeys,dragDrop.dYKeys);
if (evt.preventDefault)
evt.preventDefault();
false を返します。
},
setPosition: function (dx,dy) {
dragDrop.draggedObject.style.left =ragDrop.startX dx 'px';
dragDrop.draggedObject.style.top =ragDrop.startY dy 'px';
},
switchKeyEvents: function () {
// Opera および Safari 1.3 の場合
removeEventSimple(document,'keydown',dragDrop.dragKeys);
removeEventSimple(document,'keypress',dragDrop.switchKeyEvents);
addEventSimple(document,'keypress',dragDrop.dragKeys);
},
releaseElement: function() {
removeEventSimple(document,'mousemove',dragDrop.dragMouse);
removeEventSimple(document,'mouseup',dragDrop.releaseElement);
removeEventSimple(document,'keypress',dragDrop.dragKeys);
removeEventSimple(document,'keypress',dragDrop.switchKeyEvents);
removeEventSimple(document,'keydown',dragDrop.dragKeys);
dragDrop.draggedObject.className =ragDrop.draggedObject.className.replace(/dragged/,'');
dragDrop.draggedObject = null;
}
}

ドラッグとは
ドラッグは、画面上の要素を移動する方法です。要素を移動するには、要素に位置属性 (絶対属性または固定属性) が必要です。これにより、要素の座標 (style.top および style.left) を変更することで移動できるようになります。
(理論的にはposition:relativeも可能ですが、ほとんど役に立ちません。さらに、計算には追加のデータが必要ですが、ここでは書きませんでした)
座標の設定は非常に簡単です。設定する必要があるのはこのコードです。さらに難しい部分です。コードのほとんどは、この問題を処理するように設計されています。
また、使いやすさを維持することも重要です。従来、マウスで要素をドラッグするのが最善の方法ですが、マウスを持たないユーザーも考慮する必要があるため、キーボードの可用性も確保する必要があります。

基本
最初にいくつかの基本を見てみましょう
要素の初期化
すべてのドラッグ アンド ドロップ コードは、要素を初期化することから始まります。この作業は次の文字で完了します:
コードをコピー コードは次のとおりです:

initElement: function ( element) {
if (typeof element == 'string')
element = document.getElementById(element);
element.onmousedown =ragDrop.startDragMouse
element.innerHTML =ドラッグドロップ.keyHTML;
var links = element.getElementsByTagName('a');
var lastLink = リンク[links.length-1];
lastLink.onclick = ragDrop.startDragKeys;
},

関数が文字列を受け取った場合、それは要素 ID として処理されます。次に、この要素に onmousedown イベントを設定して、コードのマウス部分を開始します。このキーワードを startDragDrop で機能させるため、ここでは従来のイベント登録方法を使用していることに注意してください。

次に、ユーザー定義の keyHTML を要素に追加します。このリンクはキーボード イベントをトリガーするために使用されると思います。次に、このリンクのキーボード トリガー プログラムを設定します。次に、メイン要素を関連要素に保存します。これは後で必要になります。

今、コードはユーザーアクションを待っています

基本的な位置情報
次の方法を使用する予定です: まず、ドラッグされた要素の初期位置を読み取り、それを保存しますstartX と startY で。次に、マウスの移動位置またはキーボード制御による移動位置を計算して、初期位置からの要素の移動範囲を決定します。

image startX と startY は、マウスとキーボードのイベントで使用される startDrag 関数によって設定されます。

コードをコピー コードは次のとおりです。
startDrag: function (obj) {
if (ドラッグドロップ.ドラッグオブジェクト)
ドラッグドロップ.releaseElement();
ドラッグドロップ.startX = obj.offsetTop;
ドラッグドロップ.ドラッグオブジェクト = obj; obj.className = 'dragged';
},


まず、要素がドラッグされた状態にある場合は、それを解放します (これについては後で説明します)。
次に、関数は開始位置 (offsetLeft と offsetTop) で要素の座標を見つけ、後で使用できるようにそれらを startX と startY に保存します。
次に、オブジェクトへの参照をdraggedObjectに保存します。次に、ドラッグされたクラスをそれに追加します。これにより、CSS を通じてドラッグ スタイルを設定できるようになります
ユーザーがマウスまたはキーボードを使用して要素をドラッグするとき、コードの最も複雑な部分は、位置の変更を追跡することです。次に、dX と dY (X と Y の変化) が与えられます。次に、startX と startY を追加して、要素の現在位置を取得します。
次の関数を使用して位置を設定します:



コードをコピーします コードは次のとおりです: setPosition: function (dx,dy) {
ドラッグドロップ.draggedObject.style.left = ドラッグドロップ.スタートX dx 'px';
ドラッグドロップ.ドラッグオブジェクト.スタイル.トップ = ドラッグドロップ.スタートY 'px ';
}、


この関数は、マウスとキーボードの動きと初期位置によって計算された dX と dY を使用して、要素の新しい位置を設定します。
この部分は非常に単純です。複雑な部分は、マウス部分とキーボード部分の処理が大きく異なります。

マウス部分のコード
マウス部分の計算はキーボードに比べて複雑ですが、ブラウザの互換性の点では大きな問題はありません。それでは、マウス部分から始めます。
イベント
まず、イベントについて説明します。当然のことながら、オブジェクトの選択、ドラッグ、およびドラッグのアクションを完了するには、ドラッグ プロセス中にマウスダウン、マウスムーブ、およびマウスアップが必要です。
この一連のイベントは、要素のドラッグを必要とするマウスダウン イベントから始まります。したがって、すべてのドラッグ要素は、ドラッグが開始されたことを示すためにこのイベントを必要とします。
コードをコピー コードは次のとおりです。
element.onmousedown =ragDrop.startDragMouse; 🎜>
ただし、mousemove イベントと Mouseup イベントは要素ではなくドキュメント全体に設定する必要があります。ユーザーがマウスを素早く、必死に動かし、ドラッグした要素を見失う可能性があるからです。要素に設定すると、マウスが要素上にないために制御不能になる可能性があり、使いやすさにとっては良くありません。
ドキュメント上でmousemoveとmouseupを設定すると、そのような問題は発生しません。マウスがどこにあっても、要素はmousemoveとmouseupに応答します。これはとても使いやすいです。
また、mousemoveとmouseupはドラッグ開始後にのみ設定でき、ユーザーが要素を放したときに削除できます。 Mousemove は多くのシステム リソースを消費するため、このコードは非常にクリーンでシステム リソースを節約します。
Mousedown
ドラッグ要素でマウスダウン イベントが発生すると、startDragMouse 関数の実行が開始されます:

まず、前に説明した startDrag が実行されます。次に、マウスの座標を見つけて、initialMouseX とinitialMouseY に保存します。後でマウスの位置をこれと比較します。

最後に false が返されます。これは、デフォルトのマウス イベント (テキストの選択) を防ぐために使用されます。煩わしいので、ドラッグ時にテキストが選択されることを望まなくなりました。

image

次に、ドキュメントのmouseupイベントハンドラとmousemoveイベントハンドラを設定します。ドキュメントには独自の Mouseup および Mousemove イベント ハンドラーがある可能性があるため、addEventSimple 関数を使用して、元のイベント ハンドラーが失敗するのを防ぎます。

Mousemove
これで、ユーザーがマウスを移動すると、dragMouse 関数が実行されます。


コードをコピー コードは次のとおりです。
dragMouse: function (e) {
var evt = e || window.event;
var dX = evt.clientX - ドラッグドロップ.initialMouseX;
var dY = evt.clientY -
ドラッグドロップ.setPosition(dX) ,dY) ;
は false を返します;


这个函数会读取鼠标现在的坐标,然后减去之前的坐标,把得到的dX和dY传递给sePosition。

然后通过返回false来阻止鼠标选择文本的默认属性。

image

Mouseup

当用户松开鼠标的时候,会调用releaseElement。我们后面讨论。

 

键盘部分代码

现在我们开始更复杂的键盘部分代码。不像鼠标拖拽那样,键盘拖拽并没有一个标准。虽说基本的交互不是太复杂,但是最好还是简要说明一下。

基本交互

用来拖拽的键最好是方向键,这很简单。

激活和释放元素是比较有技巧的,在这里我的代码还需要加强。

我觉得如果用键盘来激活的话就应该使用一个我添加的额外的链接。这里没有太多选择:因为链接能够在所有的浏览器里面获得焦点(好吧,表单也可以,你也可是选择复选框),而且把一个链接放置在可拖拽的元素里面也是合乎逻辑的(你可以放在任何地方,但是如何让用户知道那个是用来激活拖拽的呢?)。

我假设当用户点击enter或者Esc的时候释放元素,至少我没找到其他合适的键。你想选择其他的话可以在这里查找键盘代码

case 13: // enter<br>case 27: // escape<br>	dragDrop.releaseElement();<br>	return false;

 

事件

点击可以激活元素。当鼠标点击链接或者当元素获得焦点的时候点击enter键就能激活。所以键盘代码的激活可以使点击enter键或者点击链接。

(严格来说,当你用鼠标点击链接的时候,元素先被鼠标事件激活然后释放了然后再被键盘模式激活。)

事件的其余部分也非常的模糊。当你想检测方向键的时候键盘事件尤为麻烦。

首先我们需要一个允许重复点击的事件,因为用户可能按着方向键不放,那么事件就需要一遍遍的触发,这样拖拽才能继续。所以我们使用keypress事件。

不幸的是,IE在keypress的情况下不支持方向键。在IE里面keydown会重复发生,看起来我们需要使用keydown事件了。

你可能才到事情没那么简单。在Opera和Safari里面keydown事件只能触发一次,所以当用户按下键之后,元素移动一次之后就不动了。在这些浏览器中我们需要keypress。

所以理想情况下,我们使用keypress,如果不支持就是用keydown。但是怎么切换事件呢?你又怎么知道keypress在这个时候不能用呢?

我的解决办法就是给keypress事件设置一个事件处理程序。如果这个程序执行了说明支持keypress,我们就可以安全的切换了。

startDragKeys函数用来设置keydown和keypress事件:

复制代码 代码如下:

addEventSimple(document,'keydown',dragDrop.dragKeys);
addEventSimple(document,'keypress',dragDrop.switchKeyEvents);

首先keydown触发完成拖拽的dragKeys函数。这是第一个触发的事件,而且元素总会移动。然后我们做其他的话,那么元素在Opera和Safari1.3里面移动一次以后就会停止。
这就是为什么我们还需要keypress。第一个keypress事件会触发switchKeyEvents函数,这个函数会调整事件处理程序:
复制代码 代码如下:

switchKeyEvents: function () {
    removeEventSimple(document,'keydown',dragDrop.dragKeys);
    removeEventSimple(document,'keypress',dragDrop.switchKeyEvents);
    addEventSimple(document,'keypress',dragDrop.dragKeys);
},

他会先删除掉原来的事件处理程序,然后将keypress设置为触发dragKeys。因为这个函数只会在支持他的浏览器里面执行,所以我们只在这些浏览器里面将keydown改为keypress。
初始键盘代码
当用户点击了连接激活了元素,那么就会调用startDragKeys。
复制代码 代码如下:

startDragKeys: function () {
ragDrop.startDrag(this.popularElement);
dragDrop.dXKeys =ragDrop.dYKeys = 0;
addEventSimple(document,'keydown',dragDrop. ragKeys);
addEventSimple(document,'keypress',dragDrop.switchKeyEvents);
return false;


前に説明した startDrag 関数を呼び出します。彼は、ドラッグされる要素である関連要素をこの関数に渡します。
次に、dXKeys と dYKeys を 0 に設定します。これらの変数は、要素の変位を追跡するために使用されます。
次に、上で説明したイベント ハンドラーを設定します。
次に、クリックしたリンクからフォーカスを外します。 Enter キーで要素が解放されるため、これを行いますが、フォーカスが削除されていない場合、ユーザーが Enter キーをクリックすると要素は解放されますが、リンクは Enter で再度クリックされ、再びドラッグ可能になります。焦点を外すと、問題はなくなります。
最後に false を返して、デフォルトのアクションを防止します。
キーボードによるドラッグ
dragKeys はキーボードのドラッグを担当します:


dragKeys: function(e) {
var evt = e ||
var key = evt.keyCode;


キーボードのキーの値。
次に、switch ステートメントを使用して、何をするかを決定します。この部分の目的は、要素の位置を設定して移動できるように、dXKeys と dYKeys の値を更新することです。


switch (key) {
case 37: // 左
ケース 63234:
ドラッグドロップ.dXKeys -= ドラッグドロップ.keySpeed
ブレーク;
ケース 38: // 上
ケース 63232:
ドラッグドロップ.dYKeys - = ドラッグドロップ.keySpeed;
ケース 39: // 右
ケース 63235:
ドラッグドロップ.keySpeed 4 0: // down
case 63233:
ragDrop.dYKeys =ragDrop.keySpeed;
break;


作成者は keySpeed を設定することによって各移動のピクセル サイズを決定します。ユーザーが左矢印キーをクリックすると、keySpeed が減算されます。



このコードには、ケース 63232 ~ 63235 が含まれています。 Safari 1.3 では標準の 37 ~ 40 の矢印キー値が使用されないためです (Safari 3 ではすでにサポートされています)。
image

コードをコピー
コードは次のとおりです:case 13: // と入力します。 case 27: // エスケープ dragDrop.releaseElement(); return false;

ユーザーが Enter キーまたは Esc キーをクリックすると、releaseElement() 関数が呼び出されます。要素を解放するキーを変更したい場合は、ここに追加できます。




コードをコピーします
コードは次のとおりです。デフォルト: return true; 🎜>} ユーザーが別のキーを押すと、デフォルトのアクションが実行され、機能が終了します。



コードをコピー

コードは次のとおりです。 ragDrop.setPosition(dragDrop.dXKeys,dragDrop) .dYKeys)
dXKeys と dYKeys が更新されたので、それらを setPosition() 関数に送信して要素の位置を変更します。

コードをコピー コードは次のとおりです。
if (evt.preventDefault)
evt.preventDefault ();
return false;
},

最後に、ユーザーが下矢印キーをクリックすると、上記の実行後にページが下にスクロールします。コード。これは、W3C 互換ブラウザではPreventDefault によって、IE では false を返すことによって実装されます。


要素の解放
ユーザーが要素を解放すると、関数 releaseElement が呼び出されます。コードによって設定されたすべてのイベント ハンドラーを削除し、ドラッグされたクラスを削除し、draggedObject をクリーンアップして、ユーザーのアクションを待ちます。
コードをコピー コードは次のとおりです。

releaseElement: function() {
RemoveEventSimple(document ,'mousemove',dragDrop.dragMouse);
removeEventSimple(document,'mouseup',dragDrop.releaseElement);
removeEventSimple(document,'keypress',dragDrop.dragKeys); document,'keypress',dragDrop.switchKeyEvents);
removeEventSimple(document,'keydown',dragDrop.dragKeys);
dragDrop.draggedObject.className =ragDrop.draggedObject.className.replace(/dragged/,'') );
DragDrop.draggedObject = null;
}

ユーザーが要素を解放した後に、ここに関数を追加できます。
翻訳アドレス:
http://www.quirksmode.org/js/dragdrop.html 転載のために以下の情報を保管してください
著者: Beiyu (tw:@rehawk)
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。