ææ³æä½
æ¬ææä¸ä¸èªªæææ³åæ¥é©ç使¥ã
The drag operations described in this document use the DataTransfer interface. This document does not use the DataTransferItem interface nor the DataTransferItemList interface.
Draggable 屬æ§
ç¶²é 䏿äºé è¨çææ³è¡çºï¼ä¾å¦æå鏿ãåçæè¶ é£çµï¼ç¶ææ³åçæè¶ é£çµæï¼åçæè¶ é£çµç URL æè¢«ç¶ä½ææ³ä½æ¥ä¸ææå¸¶çè³æï¼èå ¶ä»é¡åå ç´ åå¿ é å¦å¤èçæè½ææ³ï¼è©¦è©¦çé¸æç¶²é æä¸é¨åï¼ç¶å¾æä½æ»é¼ éµä¾é²è¡ææ³ï¼ä¾æ OS ä¸åï¼æè¨±ææä¸äºè·èæ»é¼ ç§»åçææï¼ä½éå å åªæ¯é è¨ææè¡çºï¼å¯¦é䏿²æä»»ä½è³æè·èè¢«ææ³ã
In HTML, apart from the default behavior for images, links, and selections, no other elements are draggable by default. In XUL, all elements are draggable.
é¤äºæå鏿ãåçæè¶ é£çµä¹å¤ï¼æ²æå ç´ é è¨æ¯å¯ææ³çãæä»¥è¦è®ä¸åå ç´ å¯ä»¥ææ³ï¼æå¹¾ä»¶äºå¿ é è¦åï¼
- 卿³è¦ææ³çå
ç´ ä¸è¨å®
draggable屬æ§çºtrueã - 註å
dragstartäºä»¶ä¹äºä»¶èçå¨ã Set the drag datawithin the listener defined above.
以䏿¯ä¸æ®µç°¡å®çç¯ä¾ã
<div
draggable="true"
ondragstart="event.dataTransfer.setData('text/plain', 'This text may be dragged')">
This text <strong>may</strong> be dragged.
</div>
draggable çº true å¾ï¼è©² DIV å ç´ ä¾¿å¯ä»¥ææ³ï¼åä¹ï¼åè¥ draggable çº false æç¡è¨å®åä¸å¯ææ³ï¼åªæå ¶ä¸ä¸å«çæåå¯ä»¥è¢«é¸æãdraggable 屬æ§é©ç¨æ¼ä»»ä½å ç´ ï¼ä¸è¬ä¾èªªé è¨çº falseï¼é¤äºåçåé£çµé è¨çº trueï¼æä»¥èªªå¦ææ³è¦é»æ¢åçåé£çµè¢«ææ³ï¼åå¯ä»¥è¨å® draggable çº falseã
è«æ³¨æï¼ä¸æ¦å ç´ è¢«å®çºå¯ææ³ä¹å¾ï¼å ¶ä¸å §å«çæåæå ¶ä»å ç´ ä¾¿ç¡æ³å平叏䏿¨£ç¨æ»é¼ 鏿ï¼ä½¿ç¨è ä¹è½å¤ æ¹ç¨éµç¤ææä½ Alt éµæé æ»é¼ é²è¡é¸æã
è³æ¼ XUL å ç´ åæ¯é è¨ç坿æ³ã
<button
label="Drag Me"
ondragstart="event.dataTransfer.setData('text/plain', 'Drag Me Button');"></button>
éå§ææ³
䏿¹ç¯ä¾å¨ dragstart 註åä¸åäºä»¶èçå¨ã
<div
draggable="true"
ondragstart="event.dataTransfer.setData('text/plain', 'This text may be dragged')">
This text <strong>may</strong> be dragged.
</div>
ç¶ææ³ä½æ¥éå§ï¼dragstart äºä»¶æè§¸ç¼ï¼ç¶å¾æåå¯ä»¥å¨äºä»¶èçå¨ä¸æºå好æåæè¦æå¸¶çè³æãæ³è¦çææ³å饿æï¼ä¸éåºæ¬ä¸å ¶å¯¦åªéè¦æºåè³æå°±å¥½ï¼å çºé è¨ææ³å饿æå·²ç¶è¶³ä»¥æä»å¤§å¤æ¸ççæ³ï¼æ¤å¤ï¼æåä¹å¯ä»¥æ¹å¨ä¸ä¸å±¤ç¶å ç´ è¨»åäºä»¶èçå¨ï¼å çºææ³äºä»¶æä¸åå³é ( Bubble up ) ã
ææ³è³æ
ææçææ³äºä»¶ç©ä»¶é½æä¸å dataTransfer 屬æ§ï¼éåå±¬æ§æ¯ç¨ä¾æå¸¶è³æã
ç¶ææ³æï¼è³æå¿ é åè¢«ææ³ç®æ¨ä½é£çµï¼æ¯å¦èªªææ³æåæ¡ä¸åç½é¸æçæåï¼é£éº¼æåæ¬èº«ä¾¿æ¯é£çµè³æï¼åçï¼ææ³é£çµæ URL 便æ¯é£çµè³æã
è³æå å«å ©åé¨åï¼ä¸æ¯è³æåæ (ææ ¼å¼)ãäºæ¯è³æå¼ãæè¬è³æåæ æ¯ç¨æåæè¿°è³æåæ (å¦text/plain代表æåè³æ)ï¼èè³æå¼åæ¯æåï¼è¦å å ¥ææ³è³æéè¦æä¾è³æçåæ åå §å®¹å¼ï¼æäºè³æå¾ï¼æåå¯ä»¥å¨ dragenter æ dragover äºä»¶èçå¨ä¸ï¼ééæª¢æ¥è³æåæ 便±ºå®æ¯å¦å¯ä»¥æ¥åå¾çºçæ¾ç½®æä½ï¼æ¯å¦èªªåªæ¥åé£çµé¡è³æçææ³ç®æ¨å(drop target)ï¼ææª¢æ¥è³æåæ æ¯å¦çºtext/uri-listã
è³æåæ ç¬¦å MIME åæ ï¼å¦text/plainæimage/jpegççï¼èæåèªå·±ä¹å¯ä»¥èªå®ç¾©å ¶ä»åæ ï¼æå¸¸ä½¿ç¨çåæ è«è¦æ¨è¦ææ³è³æåæ ã
ä¸è¶ææ³ä½æ¥ä¸å¯ä»¥æå¸¶å¤åå¤ç¨®åæ çè³æï¼æä»¥æåå¯ä»¥èªå®ç¾©èªå·±çåæ åæï¼éæä¾å ¶ä»è³æçµ¦ä¸èªå¾èªå®ç¾©è³æåæ çå ¶ä»ææ³ç®æ¨å使ç¨ãé常æéç¨çè³æææ¯æåé¡åè³æã
å¼å«setDataæ¹æ³ï¼å³å ¥è³æåæ åè³æï¼é樣就å¯ä»¥æå¸¶æ³è¦çè³æäºï¼
event.dataTransfer.setData("text/plain", "Text to drag");
ä¸ä¾è³ææ¯ãText to dragãæåï¼åæ æ¯ text/plainã
å¼å«å¤æ¬¡ setData æåå°±å¯ä»¥æå¸¶å¤ç¨®è³æã
var dt = event.dataTransfer;
dt.setData("application/x-bookmark", bookmarkString);
dt.setData("text/uri-list", "http://www.mozilla.org");
dt.setData("text/plain", "http://www.mozilla.org");
é裡å å ¥äºä¸ç¨®è³æï¼ç¬¬ä¸ç¨®æ¯èªå®ç¾©çãapplication/x-bookmarkãï¼éç¶ææ´è±å¯çå §å®¹å¯ä½¿ç¨ï¼ä½åªææåèªå·±èªèï¼èå¦å¤æååçºå ¶ä»ç¶²ç«ææç¨å å ¥äºå ©ç¨®æ¯è¼å¸¸è¦çè³æï¼ãtext/uri-listã以åãtext/plainãã
妿å°åä¸ç¨®è³æåæ å å ¥å ©æ¬¡è³æï¼åæ°å è³ææå代èè³æã
å¼å«clearDataææ¸ é¤è³æã
event.dataTransfer.clearData("text/uri-list");
妿å¼å« clearData ææå³å ¥è³æåæ ï¼ååªææ¸ é¤è©²åæ è³æï¼å¦ææ²æå³å ¥ä»»ä½åæ ï¼åææè³æçæè¢«æ¸ é¤ã
è¨å®ææ³åç
ç¶ææ³é²è¡ä¸ï¼ä»¥ææ³å
ç´ çºåºç¤ï¼ä¸ååéæçåçæèªåç¢çåºä¾ï¼ä¸¦ä¸è·èæ»é¼ ç§»åã妿æ³è¦ï¼æåä¹å¯ä»¥å¼å« setDragImage() 便宿åèªå·±çææ³ä½¿ç¨åçã
event.dataTransfer.setDragImage(image, xOffset, yOffset);
setDragImage éè¦ä¸å忏ï¼ä¸æ¯åç便º(é常æ¯åçå ç´ ï¼ä½ä¹å¯ä»¥æ¯ canvas å ç´ æå ¶ä»å ç´ )ï¼ææ³ä½¿ç¨åçæä¾ç §åç便ºå¨è¢å¹ä¸æé¡¯ç¤ºç樣åç¢çï¼äºå䏿¯åçç¸å°æ¼æ»é¼ ææ¨çä½ç½®ä½ç§»éã
ä¸é乿¯è½å¤ ä½¿ç¨æä»¶å¤é¨çåçæ canvas å ç´ ï¼ç¶éè¦éé canvas å ç´ ç¢ç客製åçæï¼éåæå·§å¾æç¨ï¼å¦ä¸ç¯ä¾æç¤ºï¼
function dragWithCustomImage(event) {
var canvas = document.createElementNS(
"http://www.w3.org/1999/xhtml",
"canvas",
);
canvas.width = canvas.height = 50;
var ctx = canvas.getContext("2d");
ctx.lineWidth = 4;
ctx.moveTo(0, 0);
ctx.lineTo(50, 50);
ctx.moveTo(0, 50);
ctx.lineTo(50, 0);
ctx.stroke();
var dt = event.dataTransfer;
dt.setData("text/plain", "Data to Drag");
dt.setDragImage(canvas, 25, 25);
}
ä¸é¢æåç canvas æ¯ 50 x 50px 大å°ï¼ç¶å¾æåä½ç§»ä¸å 25 è®åçè½å¨æ»é¼ ææ¨ä¸å¤®ã
ææ³ææ
ææ³ä½æ¥æå¥½æ©ç¨®ï¼copy 使¥ä»£è¡¨è¢«ææ³è³ææè¢«è¤è£½ä¸ä»½å°ææ³ç®æ¨åï¼move 使¥ä»£è¡¨ç§»åè¢«ææ³çè³æï¼link 使¥ä»£è¡¨ææ³ä¾æºååææ³ç®æ¨åææç¨®éä¿ã
å¨ dragstart äºä»¶ä¸å¯ä»¥è¨å®effectAllowed屬æ§ï¼æå®ææ³æºé å 許ç使¥ã
event.dataTransfer.effectAllowed = "copy";
ä¸é¢åªæ copy 被å 許ï¼ä½éæå ¶ä»ç¨®é¡ï¼
åªè½ç§»åæé£çµã
- none
-
ä¸å 許任ä½ä½æ¥ã
- copy
-
åªè½è¤è£½ã
- move
-
åªè½ç§»åã
- link
-
åªæé£çµã
- copyMove
-
åªè½è¤è£½æç§»åã
- copyLink
-
åªè½è¤è£½æé£çµã
- linkMoveall
-
è¤è£½ãç§»åæé£çµçå¯ã
effectAllowed 屬æ§é è¨ææä½æ¥é½æ¥åï¼å¦ all å¼ã
å¨ dragenter æ dragover äºä»¶ä¸ï¼æåå¯ä»¥èç±æª¢æ¥ effectAllowed ä¾ç¥éé£äºä½æ¥æ¯è¢«å 許çï¼å¦å¤ï¼å¦ä¸åç¸éè¯çdropEffectå±¬æ§æè©²è¦æ¯ effectAllowed çå ¶ä¸ä¸å使¥ï¼ä½æ¯ dropEffect 䏿¥åå¤é使¥ï¼åªå¯ä»¥æ¯ none, copy, move å linkã
dropEffect å±¬æ§æå¨å¨ dragenter 以å dragover äºä»¶ä¸åå§åçºä½¿ç¨è æ³è¦å·è¡ç使¥ææï¼ä½¿ç¨è è½å¤ ééæéµ(ä¾å¹³å°ä¸åï¼éå¸¸æ¯ Shift æ Ctrl éµ)ï¼å¨è¤è£½ãç§»åã飿¥ä½æ¥ä¹éåæï¼åææ»é¼ ææ¨ä¹æè·èç¸æè®æï¼ä¾å¦è¤è£½ä½æ¥çæ»é¼ ææå¤åºä¸å+ç符èã
effectAllowed å dropEffect 屬æ§å¯ä»¥å¨ dragenter æ dragover äºä»¶ä¸æ´æ¹ï¼æ´æ¹ effectAllowed 屬æ§è½è®ææ³ä½æ¥åªè½å¨æ¯æ´è¢«å è¨±ä½æ¥é¡åçææ³ç®æ¨ä¸å·è¡ï¼å¥½æ¯èªª effectAllowed çº copyMove ç使¥å°±æé»æ¢ä½¿ç¨è é²è¡ link é¡åç使¥ã
æåä¹å¯ä»¥æ´æ¹ dropEffect ä¾å¼·è¿«ä½¿ç¨è å·è¡æé 使¥ï¼èä¸æè©²è¦æ¯ effectAllowed æåèç使¥ã
event.dataTransfer.effectAllowed = "copyMove";
event.dataTransfer.dropEffect = "copy";
ä¸é¢çç¯ä¾ä¸ copy å°±æ¯æè¢«å·è¡ç使¥ææã
è¥ effectAllowed æ dropEffect çº noneï¼é£éº¼æ²ææ¾ç½®ä½æ¥å¯ä»¥è¢«å·è¡ã
æå®ææ³ç®æ¨
dragenter å dragover äºä»¶å°±æ¯ç¨ä¾æå®ææ³ç®æ¨åï¼ä¹å°±æ¯æ¾ç½®è³æçç®æ¨åï¼çµå¤§å¤æ¸çå ç´ é è¨çäºä»¶é½ä¸åæ¾ç½®è³æã
æä»¥æ³è¦æ¾ç½®è³æå°å ç´ ä¸ï¼å°±å¿ é åæ¶é è¨äºä»¶è¡çºãåæ¶é è¨äºä»¶è¡çºè½å¤ èç±åå³ false æå¼å«event.preventDefaultæ¹æ³ã
<div ondragover="return false">
<div ondragover="event.preventDefault()"></div>
</div>
é常æååªæå¨é©ç¶çææ©é»æéè¦å¼å« event.preventDefault æ¹æ³ãåæ¶é è¨äºä»¶è¡çºï¼æ¯å¦èªªè¢«ææ³é²ä¾çæ¯é£çµãæä»¥æª¢æ¥è¢«ææ³é²ä¾çç©ä»¶ï¼ç¶ç¬¦åæ¢ä»¶å¾åä¾åæ¶é è¨äºä»¶è¡çºã
èç±æª¢æ¥ææ³è³æåæ 便±ºå®æ¯å¦å 許æ¾ç½®ï¼æ¯æå¸¸è¦ç使³ãdataTransfer ç©ä»¶çtypeså±¬æ§æ¯ä¸åææ³è³æåæ çå表ï¼å ¶ä¸é åºæç §è³æè¢«å å ¥ä¹å 徿åºã
function doDragOver(event) {
var isLink = event.dataTransfer.types.contains("text/uri-list");
if (isLink) event.preventDefault();
}
ä¸é¢æåå¼å« contains æ¹æ³æª¢å¯ text/uri-list æ¯å¦å卿æ³è³æåæ çå表ä¹å §ï¼æç話æåæ¶é è¨è¡çºãå許æ¾ç½®ä½æ¥ï¼å¦åï¼ä¸åæ¶é è¨è¡çºãä¸å許æ¾ç½®ä½æ¥ã
æª¢æ¥ææ³è³æåæ å¾ï¼æåä¹å¯ä»¥ä¾æ¤æ´å effectAllowed å dropEffect 屬æ§ï¼åªä¸éï¼å¦ææ²æåæ¶é è¨è¡çºï¼æ´å䏦䏿æç麼影é¿ã
Updates to DataTransfer.types
Note that the latest spec now dictates that DataTransfer.types should return a frozen array of DOMStrings rather than a DOMStringList (this is supported in Firefox 52 and above).
As a result, the contains method no longer works on the property; the includes method should be used instead to check if a specific type of data is provided, using code like the following:
if ([...event.dataTransfer.types].includes("text/html")) {
// Do something
}
You could always use some feature detection to determine which method is supported on types, and run code as appropriate.
æ¾ç½®åé¥
æå¥½å¹¾ç¨®æ¹æ³åé¥ä½¿ç¨è ï¼å訴使ç¨è ç麼å ç´ å¯ä»¥æ¥åæ¾ç½®ä½æ¥ï¼æç°¡å®çæ¯æ»é¼ æææ¨æèªåè®ææ¨£å¼(è¦å¹³å°èå®)ã
æ»é¼ ææ¨æç¤ºéç¶å¤ ç¨äºï¼ä¸éæææåéæ¯ææ³åå ¶ä» UI ä¸ç樣å¼è®åã-moz-drag-over ç CSS pseudo-class 便å¯ä»¥æç¨å¨ææ³ç®æ¨å ç´ ä¸ã
.droparea:-moz-drag-over {
border: 1px solid black;
}
ç¶ç®æ¨å ç´ ç dragenter é è¨äºä»¶æè¢«åæ¶æï¼éå pseudo-class å°±æååï¼ç®æ¨ UI æå¥ç¨ 1px çé»è² borderï¼è«æ³¨æ dragover ä¸¦ä¸ææª¢æ¥éé è¨å®ã
å ¶ä»æ¯å¦èªªæå ¥åççï¼å¨ dragenter äºä»¶å §å·è¡æ´å¤æ´è¤éçæ¨£å¼è®å乿¯å¯ä»¥çã
åè¥æ³è¦ååºåçæ´èæ»é¼ å¨ææ³ç®æ¨åä¸é¢ç§»åçææï¼é£éº¼å¯ä»¥å¨ dragover äºä»¶å §ä¾åå¾çclientXåclientYçæ»é¼ åº§æ¨è³è¨ã
æå¾ï¼æè©²è¦å¨ dragleave äºä»¶å §å¾©åä¹åæå樣å¼è®æ´ï¼dragleave äºä»¶ä¸éè¦åæ¶é è¨äºä»¶è¡çºãæ°¸é é½æè§¸ç¼ï¼å³ä½¿ææ³è¢«åæ¶äºï¼è³æ¼ä½¿ç¨-moz-drag-over ç CSS æ¹æ³çè©±ï¼æ¨£å¼å¾©åæèªåå·è¡ï¼ä¸ç¨æå¿ã
å·è¡æ¾ç½®ä½æ¥
ç¶ä½¿ç¨è 卿æ³ç®æ¨å䏿¾éæ»é¼ æï¼drop äºä»¶å°±æè§¸ç¼ãç¶ drop äºä»¶ç¼çï¼æåéè¦ååºè¢«ä¸å ¥çè³æï¼ç¶å¾èçä¹ã
è¦ååºè¢«ä¸å ¥çè³æï¼é£å°±è¦å¼å« dataTransfer ç©ä»¶çgetDataæ¹æ³ãgetData æ¹æ³æ¥åè³æåæ ç忏ï¼å®æåå³setDataæåå ¥çå°æè³æåæ çè³æï¼åè¥æ²æå°æåæ è³æï¼é£ç©ºå串就æè¢«åå³ã
function onDrop(event) {
var data = event.dataTransfer.getData("text/plain");
event.target.textContent = data;
event.preventDefault();
}
ä¸é¢çç¯ä¾æååºæåè³æï¼åè¨ææ³ç®æ¨åæ¯æåååï¼ä¾å¦ p æ div å ç´ ï¼é£éº¼è³æå°±æè¢«ç¶ä½æåå §å®¹ï¼æå ¥ç®æ¨å ç´ ä¹ä¸ã
ç¶²é ä¹ä¸ï¼å¦ææåå·²ç¶èçéæ¾ç½®è³æï¼é£æè©²è¦å¼å«{preventDefault}æ¹æ³é²æ¢ç覽å¨å次èçè³æï¼æ¯å¦èªªï¼Firefox é è¨æ¯æéåæå ¥çé£çµï¼ä½æåå¯ä»¥åæ¶éé é è¨è¡çºä¾é¿å éåé£çµã
ç¶ç¶ä¹å¯ä»¥åå¾å ¶ä»ç¨®é¡è³æä¾ä½¿ç¨ï¼æ¯å¦èªªé£çµè³æï¼text/uri-listã
function doDrop(event)
{
var links = event.dataTransfer.getData("text/uri-list").split("\n");
for each (var link in links) {
if (link.indexOf("#") == 0)
continue;
var newlink = document.createElement("a");
newlink.href = link;
newlink.textContent = link;
event.target.appendChild(newlink);
}
event.preventDefault();
}
ä¸é¢çç¯ä¾åå¾é£çµè³æï¼ç¶å¾çæé£çµå ç´ ãå å ¥é é¢ãå¾ text/uri-list åé¢ä¸ä¸é£çåºéç¨®è³ææ¯ä¸è¡è¡ç URLï¼æä»¥æåå¼å« split æ¹æ³æéä¸è¡è¡ç URLï¼åå° URL ä¸åä¸åå å ¥é é¢ãè«æ³¨ææåæé¿ééé çºã#ãåå ç註解ã
æ´ç°¡å®ç使³æ¯æ¡ç¨ç¹å¥ URL åæ ãURL åæ æ¯ä¸åç¹æ®ç°¡å¯«ç¨éå½¢æ ï¼å®ä¸æåºç¾å¨{types}屬æ§ä¸ï¼ä½å®å¯ä»¥æ¹ä¾¿çåå¾ç¬¬ä¸åé£çµï¼å¦ä¸:
var link = event.dataTransfer.getData("URL");
éå使³è½å¤ ç廿ª¢æ¥è¨»è§£åä¸åä¸åæé URLï¼ä½åªæå¾å°ç¬¬ä¸å URLã
ä¸é¢çä¾åæå¾å¤åæ¯æ´çè³æåæ ä¸ï¼æ¾åºæ¯æ´çè³æã
function doDrop(event)
{
var types = event.dataTransfer.types;
var supportedTypes = ["application/x-moz-file", "text/uri-list", "text/plain"];
types = supportedTypes.filter(function (value) types.contains(value));
if (types.length)
var data = event.dataTransfer.getData(types[0]);
event.preventDefault();
}
å®æææ³
ææ³ä½æ¥å®æå¾ï¼ä¸è«æåæåæ¶æ¼å¦ï¼è¢«ææ³å
ç´ çdragendäºä»¶é½æè§¸ç¼ï¼å¦ææ³è¦å¤å¥ä½æ¥æ¯å¦å®æï¼å¯ä»¥æª¢æ¥ dropEffect 屬æ§ï¼è¥æ¯ dropEffect çº noneï¼ä»£è¡¨ææ³ä½æ¥è¢«åæ¶ï¼å¦å dropEffect çå¼ä»£è¡¨æå®æç使¥é¡åã
æä¸å Gecko å°å±¬çmozUserCancelled屬æ§ï¼ç¶ä½¿ç¨è æ ESC éµåæ¶ææ³å¾ï¼éåå±¬æ§æçº trueï¼ä½è¥æ¯å å ¶ä»çç±è¢«åæ¶ææåï¼åçº false
ææ³ä½æ¥çæ¾ç½®å¯ä»¥ç¼çå¨åä¸åè¦çªæå ¶ä»æç¨ç¨å¼ï¼èä¸ dragend äºä»¶éæ¯æè§¸ç¼ï¼ä¸éäºä»¶ä¸çscreenXèscreenYå±¬æ§ææ¯æ¾ç½®ç¼çé»çè³è¨ã
ç¶ dragend äºä»¶çµæå³éå¾ï¼ææ³ä½æ¥ä¹å®æäºã
[1] å¨ Geckoï¼å¦æè¢«ææ³å ç´ å¨ææ³ä½æ¥éå¨é²è¡ä¸ç§»åæåªé¤ï¼é£éº¼ dragend äºä»¶å°±ä¸æè§¸ç¼ãbug 460801