[英]HTML5 drag and drop DOM manipulation with javascript
我正在嘗試使用本機拖放事件重新排序 DOM SVG 元素。 下面的代碼在 Firefox 中似乎可以工作(帶有一些奇怪的圖像效果),在 Chrome 中工作的次數有限(2 或 3 次拖放重新排序工作,然后它似乎掛起),在 IE 中根本不是很好。 我最好的猜測是,有問題的事件有一些我沒有正確考慮的事情,某種類型的重置。 或者可能以這種方式使用沒有 dataTransfer 的拖動事件是不正確的。 我的目標是在沒有庫的情況下理解這種類型的函數,但在最基本的層面上對 DOM 函數、JavaScript、HTML 和 CSS 有一個更清晰的理解。 我很容易在該列表中的任何地方出錯。
<!DOCTYPE html>
<html>
<head>
<title>Drag and Drop Experiments</title>
<style>svg { border-width:3px} </style>
</head>
<body>
<div id="main">
<svg id="s1" draggable="yes" width="100" height="100">
<circle cx="50" cy="50" r="30" fill="blue"></circle>
</svg>
<svg id="s2" draggable="yes" width="100" height="100">
<circle cx="50" cy="50" r="30" fill="red"></circle>
</svg>
<svg id="s3" draggable="yes" width="100" height="100">
<circle cx="50" cy="50" r="30" fill="yellow"></circle>
</svg>
</div>
<script type="text/javascript">
var dragSourceElement = null;
var dragTargetElement = null;
function doDragStart(e){
this.style.opacity = "0.4";
this.style.border = "solid";
dragSourceElement = this;
}
function doDragEnter(e){
if(dragSourceElement != this){
this.style.border = "dashed";
}
}
function doDragLeave(e){
if(dragSourceElement != this){
this.style.border = "";
}
}
function doDragOver(e){
if(dragSourceElement != this){
dragTargetElement = this;
e.preventDefault();//to allow a drop?
}
}
function doDragEnd(e){
this.style.border = "";
this.style.opacity = "1.0";
}
function doDragDrop(e){
if(dragSourceElement != dragTargetElement){
dnd_svg(dragSourceElement,dragTargetElement);
}
dragSourceElement.style.border = "";
dragTargetElement.style.border = "";
dragSourceElement.style.opacity = "";
dragSourceElement = null;
dragTargetElement = null;
}
//called after a drag and drop
//to insert svg element c1 before c2 in the DOM
//subtree of the parent of c2, assuming c1 is
//dropped onto c2
function dnd_svg(c1,c2){
var parent_c2 = c2.parentElement;
parent_c2.insertBefore(c1,c2);
}
function addL(n){
n.addEventListener('dragstart',doDragStart,false);
n.addEventListener('dragenter',doDragEnter,false);
n.addEventListener('dragleave',doDragLeave,false);
n.addEventListener('dragover',doDragOver,false);
n.addEventListener('drop',doDragDrop,false);
}
addL(document.getElementById("s1"));
addL(document.getElementById("s2"));
addL(document.getElementById("s3"));
</script>
</body>
</html>
請參閱此 JSFiddle 。 FF 中的 SVG 上的拖放事件存在問題,因此一種解決方案是向 SVG 添加包裝器元素。 有了這個,您可以使用 dataTransfer 方法,然后將節點附加到放置位置。
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
#div1,#div2 {
width:350px;
height:70px;
padding:10px;
border:1px solid #aaaaaa;
}
</style>
<script>
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
var id = ev.target ? ev.target.id : ev.srcElement.id;
if (id === "circle") {
id = ev.target.parentNode.parentNode.id;
}
ev.dataTransfer.setData("Text", id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(data));
}
</script>
</head>
<body>
<div id="div1" ondrop="drop(event)"
ondragover="allowDrop(event)"></div>
<div id="div2" ondrop="drop(event)"
ondragover="allowDrop(event)"></div>
<br>
<div id="wrapper" draggable="yes" ondragstart="drag(event)" style="width:100px; height:100px;">
<svg id="svg" width="100" height="100" draggable="yes" ondragstart="drag(event)" >
<circle id="circle" cx="50" cy="50" r="30" fill="yellow"></circle>
</svg>
</div>
</body>
</html>
這適用於我在 FF 18 和 IE 9 中。令人討厭的部分是 FF 和 IE 都為這些事件提供不同的目標,IE 返回 SVG 作為拖動事件的目標,而 FF 返回圓圈。 很煩人。
更新:我在 Chrome 24 中嘗試了這個 JSFiddle,它可以工作。
本教程非常適合理解原生拖放,並附有大量示例。
但是,可能存在與 SVG 相關的特殊問題。 例如,請參閱此Mozilla 錯誤:“dragstart 事件未在 svg 元素上觸發”。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.