[英]HTML5 - canvas and dragging/dropping or placing an image where user clicks
[英]HTML5 DnD - Why is ghost image only working as expected AFTER dragging & dropping an element?
我試圖讓一個帶有嵌套img
的p
元素在拖動時顯示為重影圖像。
我不確定如何調試它,但我注意到一旦圖像被緩存或被拖放到頁面上的某個位置,它就會按預期工作。 我在這里做了一個 MWE:
笑臉在頁面首次加載時被拖動並顯示錯誤行為 - 表情符號在拖動過程中不顯示。 悲傷的臉被拖動,釋放,然后重新拖動,這導致了預期的行為 - 表情符號確實顯示為幽靈圖像的一部分。 所有圖像都是如此。
我試過的:我認為這可能是頁面元素加載方式的問題,所以我將 javascript 移動到正文的底部(試圖確保在腳本運行之前加載所有元素)。 這並不能解決問題。
MWE 代碼:我從這里得到了表情符號,但我想你機器上的任何 png 都可以重現這個。
索引.php:
<html>
<head>
<link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>
<body>
<h2>Order these items</h2>
<div id="main_wrapper">
<?php
$json = json_decode(file_get_contents("image_set.json"), true);
echo '<div id="home_container" ondrop="drop(event, this)" ondragover="allowDrop(event)">';
$i = 0;
foreach($json as $k => $v) {
echo '<p class="drag_item" draggable="true" ondragstart="drag(event)" id="drag'.$i.'"><img draggable="false" src="/images/'.$v['fn'].'" width=200 height=200>'.$v['text'].'</p>';
$i++;
}
echo '</div>';
?>
<div id="buffer" style="min-height:100px; width:100%;"></div>
<div id="dropzone_wrapper">
<?php
for($i = 0; $i < count($json); $i++) {
echo '<div class="dropzone" id="dropzone'.$i.'" ondrop="drop(event, this)" ondragover="allowDrop(event)"></div>';
if($i < count($json)-1){echo '<';}
}
?>
</div>
<div id="msg"></div>
</div>
<script>
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
var dataList = ev.dataTransfer.items;
dataList.add(ev.target.id, "text/plain");
}
function drop(ev, el) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
var element_to_drop = document.getElementById(data);
let droppable = true;
// If the dropzone already contains something (not text due to
// spaces in markup being counted as text), don't allow
// another drop to occur.
if (el.childNodes.length > 0) {
el.childNodes.forEach(function(obj) {
if(obj.nodeName != '#text') {
droppable = false;
}
});
}
if(droppable)
el.appendChild(document.getElementById(data));
}
function reset() {
// Put all drag items back into the home container
let home = document.getElementById('home_container');
let cards = document.querySelectorAll('.drag_item');
for(var i = 0; i < cards.length; i++) {
home.appendChild(cards[i]);
}
}
</script>
</body>
</html>
image_set.json:
{
"happy": {
"fn":"happy.png",
"text":"A happy face"
},
"sad": {
"fn":"sad.png",
"text":"A sad face"
},
"angry": {
"fn":"angry.png",
"text":"An angry face"
},
"confused": {
"fn":"confused.png",
"text":"A confused face"
},
"sleepy": {
"fn":"sleepy.png",
"text":"A sleepy face"
}
}
樣式表.css:
* {
box-sizing:border-box;
padding:0px;
margin:0px;
font-family:sans-serif;
font-weight:100;
}
body {
padding:20px;
}
h2 {
padding:20px 0;
font-size:4em;
}
p.drag_item {
text-align:center;
transition:0.5s;
width:200px;
height:200px;
}
.drag_item:hover {
cursor:move;
}
#home_container, #dropzone_wrapper {
min-height:200px;
width:100%;
display:flex;
flex-direction:row;
justify-content:space-around;
margin:20px 0;
align-items:center;
}
#dropzone_wrapper {
font-size:3em;
}
#dropzone_wrapper p {
font-size:initial;
}
#home_container {
border:1px solid black;
border-radius:8px;
background-color:#e5e5e5;
}
#home_container p {
width:200px;
font-size:16px;
}
#msg {
display:block;
font-size:2.5em;
}
.dropzone {
min-height:200px;
width:200px;
border:1px dashed black;
background-color:#00a8bd;
}
我做了一些研究來找到問題所在。 這對我來說有點難,因為 Firefox 是唯一一個在第一次加載頁面和第一次拖動時沒有顯示重影圖像的瀏覽器。 我打開Network
選項卡,發現僅在第一次拖動時才請求圖像(我不太明白,因為圖像已完全加載)。
無論如何,我終於設法讓這個工作,通過將可拖動元素更改為圖像而不是段落。
索引.php:
<div id="main_wrapper">
<?php
$json = json_decode(file_get_contents("image_set.json"), true);
echo '<div id="home_container" ondrop="drop(event, this)" ondragover="allowDrop(event)">';
$i = 0;
foreach($json as $k => $v) {
echo '<p class="drag_item"><img ondragstart="drag(event)" id="drag'.$i.'" draggable="true" src="images/'.$v['fn'].'" width=200 height=200>'.$v['text'].'</p>';
$i++;
}
echo '</div>';
?>
<div id="buffer" style="min-height:100px; width:100%;"></div>
<div id="dropzone_wrapper">
<?php
for($i = 0; $i < count($json); $i++) {
echo '<div class="dropzone" id="dropzone'.$i.'" ondrop="drop(event, this)" ondragover="allowDrop(event)"></div>';
if($i < count($json)-1){echo '<';}
}
?>
</div>
<div id="msg"></div>
</div>
JS:
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
// get the cursor position relative to the element
var x = (ev.pageX - ev.target.offsetLeft) + document.body.scrollLeft;
var y = (ev.pageY - ev.target.offsetTop) + document.body.scrollTop;
ev.dataTransfer.setData("text", ev.target.id);
// set the parent element (the paragraph) as the custom ghost image and set the position of the ghost image (x, y)
ev.dataTransfer.setDragImage(ev.target.parentElement, x, y);
}
function drop(ev, el) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
var element_to_drop = document.getElementById(data);
let droppable = true;
if (el.childNodes.length > 0) {
el.childNodes.forEach(function(obj) {
if(obj.nodeName != '#text') {
droppable = false;
}
});
}
if(droppable)
el.appendChild(document.getElementById(data).parentElement);
}
function reset() {
let home = document.getElementById('home_container');
let cards = document.querySelectorAll('.drag_item');
for(var i = 0; i < cards.length; i++) {
home.appendChild(cards[i]);
}
}
這適用於:Chrome、Edge、IE 11
注意:這僅在 Firefox 中完美運行(段落文本僅出現在此瀏覽器中)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.