1

我试图让p一个嵌套的元素img在拖动时显示为重影图像。

我不确定如何调试它,但我注意到一旦图像被缓存或被拖放到页面上的某个位置,它就会按预期工作。我在这里做了一个 MWE:

gif_of_dragging

笑脸在页面首次加载时被拖动并显示错误行为 - 表情符号在拖动过程中不显示。悲伤的脸被拖动,释放,然后重新拖动,这导致了预期的行为 - 表情符号确实显示为幽灵图像的一部分。所有图像都是如此。

我试过的: 我认为这可能是页面元素加载方式的问题,所以我将 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 '&lt;';}
      }
    ?>
    </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;
}
4

1 回答 1

1

我做了一些研究来找到问题所在。这对我来说有点困难,因为 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 '&lt;';}
            }
        ?>
    </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 中完美运行(段落文本仅出现在此浏览器中)

于 2020-05-26T09:25:19.827 回答