看看这个小提琴:https://jsfiddle.net/zanpx9mw/1/
代码:
const draggable_element = document.getElementById("draggable_element");
draggable_element.addEventListener("dragstart", (e) => {
const rect = e.srcElement.getBoundingClientRect();
const dt = e.dataTransfer;
dt.setData("dx", `${Math.round(e.clientX - rect.x)}`);
dt.setData("dy", `${Math.round(e.clientY - rect.y)}`);
[...dt.items].forEach(it => {
console.log(`dragstart ${it.type}: ${dt.getData(it.type)}`);
});
});
draggable_element.addEventListener("dragover", (e) => {
const dt = e.dataTransfer;
[...dt.items].forEach(it => {
console.log(`dragover ${it.type}: ${dt.getData(it.type)}`);
});
});
在Firefox上,我可以将数据存储在dragstart
事件中的事件dataTransfer
对象中,然后在dragover
事件中读取它。
在铬/铬然而,我可以存储数据并在dragstart
事件内成功读取它,但不再在dragover
事件。奇怪的是,具有预期名称的项仍然存在,但数据似乎为空。
有一个有趣的解决方案:我可以只是保存数据内的项目类型,但这似乎是错误的..
这是已知的行为吗?我做错了什么吗?
看起来Chrome只在drop
事件上支持getData()
出于安全原因(取自这个非常相似的问题)。
规避这些"安全"度量您必须将数据写入如下类型:
const draggable_element = document.getElementById("draggable_element");
function int_list(dt, name) {
for(const it of dt.items) {
if (it.type.startsWith(`${name}`)) {
return it.type.split("_").slice(1).map(x=>parseInt(x));
}
}
}
draggable_element.addEventListener("dragstart", (e) => {
const rect = e.srcElement.getBoundingClientRect();
e.dataTransfer.setData(`pos_${Math.round(e.clientX - rect.x)}_${Math.round(e.clientY - rect.y)}`, '');
});
draggable_element.addEventListener("dragover", (e) => {
const pos = int_list(e.dataTransfer, "pos");
e.srcElement.style.left = `${e.x - pos[0]}px`;
e.srcElement.style.top = `${e.y - pos[1]}px`;
});
参见工作示例https://jsfiddle.net/g7608m1j/