将可放置div拖动到背景图像上的特定点

时间:2018-09-25 16:27:39

标签: jquery jquery-ui draggable jquery-ui-droppable

我正在尝试创建一个简单的教育游戏,在其中将标志拖放到地图背景图像上的正确位置。因此,我知道如何使标记可拖动和可拖放,但不知道如何在地图上的特定点上使可拖放区域成为可能。

这是我到目前为止所拥有的:

    <!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>temperate journeys</title>

<style>
    #flags{float:left; height:100px;width:35px; padding:2px;margin-right: 10px;}
    #china{height:20px; width:25px; background-color:red; border: 1px solid #B7191C;padding:3px;}
    .china{height:22px; width:27px; background-color:green; border: 1px solid green;}
    #australia {height:20px; width:25px; background-color:blue; border: 1px solid #3324AF;padding:3px;}
    </style>
 <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
  <script>
  $( function() {
    $( "#china" ).draggable();
     $( "#australia" ).draggable(); 
     $( ".china" ).droppable({accept:"#china"});  
  } );
  </script>
</head>

<body>

    <div id="flags">
    <div id="china"> Ch </div>
    <div id="australia">Au</div>    


    </div>
<img src="map.gif" alt="" width="520" height="289" usemap="#Map"/>
<map name="Map"><area class="china" shape="rect" coords="346,118,397,153" href="#" target="_self">

  <area shape="rect" coords="409,209,461,240" class="australia" target="_self">
</map>
</body>

1 个答案:

答案 0 :(得分:0)

尝试在Droppable中使用Image-Map不会很有趣,也不会以您想要的方式解决。

  

<area>标记定义了图像映射内的区域(图像映射是具有可点击区域的图像)。

     

<area>元素始终嵌套在标签内。

     

注意<img>标签中的usemap属性与<map>元素的name属性相关联,并在图像和地图之间建立关系。

对于我们的用户界面,这意味着什么?好吧,这暗示了<area>元素不具有与<img><div>相同的意义。它更多地是用于检查区域是否已单击的坐标参考。它在DOM中,但是其盒模型与与其关联的图像相同。因此$("map .china")将具有与图像相同的宽度和位置。

这并不意味着它没有帮助。每个<area>元素仍然具有定义坐标的属性。因此,$("map .china").attr("coords")将产生"346,118,397,153",我们可以使用此String做一些事情!

目标

  • 允许用户将标记拖放到地图上
  • 在下降时,确定标志是否在坐标内
  • 指示用户是否击中目标
  • (将标志还原到原始位置吗?)

示例

https://jsfiddle.net/Twisty/saufz8tg/

HTML

<div class="drag-area">
  <div id="flags">
    <div id="china" class="flag" title="China">Ch</div>
    <div id="australia" class="flag" title="Autstralia">Au</div>
  </div>
  <img class="map-image" src="https://www.wpclipart.com/dl.php?img=/geography/world_maps/world_map_basic_color.png" alt="" width="520" height="289" usemap="#Map" />
  <map name="Map">
    <area class="china" shape="rect" coords="346,118,397,153" href="#" target="_self">
    <area shape="rect" coords="409,209,461,240" class="australia" target="_self">
  </map>
</div>

这里没有太多变化。 <div>用于帮助包装和容纳东西。还有其他一些类可以帮助组织和分配样式。

CSS

#flags {
  float: left;
  height: 100px;
  width: 35px;
  padding: 2px;
  margin-right: 10px;
}

.flag {
  height: 20px;
  width: 25px;
  margin-bottom: 1px;
  border: 1px solid #B7191C;
  border-radius: 3px;
  padding: 3px;
}

#china {
  background-color: red;
}

#australia {
  background-color: blue;
}

同样,没有重大变化。只需清理并简化组织,减少重复代码。

JavaScript

$(function() {
  function getObjCoords(o) {
    var p = o.position();
    var d = {
      width: o.width(),
      height: o.height()
    };
    var coords = [
      p.left, // X1
      p.top, // Y1
      p.left + d.width, // X2
      p.top + d.height // Y2
    ];
    return coords;
  }

  function getObjCenter(o) {
    var p = o.position();
    var d = {
      width: o.width(),
      height: o.height()
    }
    var c = [
      parseInt(p.left + (d.width / 2)),
      parseInt(p.top + (d.height / 2))
    ];
    return c;
  }

  function hit(o, t, off) {
    var x, y;
    var center = getObjCenter(o);
    var hit = false;
    if (center[0] > (t[0] + off.left) && center[0] < (t[2] + off.left)) {
      x = true
    } else {
      x = false;
    }
    if (center[1] > (t[1] + off.top) && center[1] < (t[3] + off.top)) {
      y = true;
    } else {
      y = false;
    }
    if (x && y) {
      hit = true;
    }
    return hit;
  }

  var $mapArea = $("map[name='Map']");
  var imgOff = $(".map-image").position();
  console.log("Image Position:", imgOff);

  $(".flag").draggable({
    containment: ".drag-area"
  });
  $(".flag").disableSelection();
  $(".map-image").droppable({
    drop: function(e, ui) {
      var itemCenter = getObjCenter(ui.draggable);
      console.log("Drop Center:", itemCenter);
      var t = ui.draggable.attr("id");
      var tPos = $mapArea.find("." + t).attr("coords").split(",");
      $.each(tPos, function(k, v) {
        tPos[k] = parseInt(v);
      });
      console.log("Target Coords:", tPos);
      console.log("Target Offset: [ " + (tPos[0] + imgOff.left) + ", " + (tPos[1] + imgOff.top) + ", " + (tPos[2] + imgOff.left) + ", " + (tPos[3] + imgOff.top) + " ]");
      if (hit(ui.draggable, tPos, imgOff)) {
        console.log("Hit!");
        return true;
      } else {
        console.log("Miss.");
        return false;
      }
    }
  });
});

我这样布置我的JavaScript / jQuery:函数,常量和UI定义/设置。我们具有三个帮助程序功能:getObjCoords()getObjCenter()hit()。我将此脚本比作《战舰》游戏,所以我使用了很多相同的术语。

我怀疑您会有更多的标记和区域来放置它们。这是这些辅助功能发挥作用的地方。我们将把繁重的工作留给他们,而只需在拖放区域中使用我们更基础的对象即可。

getObjCoords(jQuery Object)

接受jQuery对象,并根据对象的位置和尺寸返回[x1, y1, x2, y2]数组。

getObjCenter(jQuery Object)

接受jQuery对象,并返回[x, y]数组,定义对象框的中心。

hit(jQuery对象,数组坐标,数组偏移量)

确定对象中心是否在4个区域坐标内。

注释

  • 由于您没有定义如何处理“命中”或“未命中”,因此我只需在删除标志时将其发送到控制台。现在,可以放下标志,然后再次移动。
  • .split()用于将字符串转换为数组,但它将是字符串数组。 JavaScript通常会接受这一点,但是为了进行适当的比较,我已经将它们转换为Integers。
  • getObjCenter()可以使用数学运算对值进行四舍五入。请记住,将奇数除以将产生一个长整数(3/2 = 1.5),HTML不喜欢半个Pixel。您可以使用Math.round()Math.floor(),但是parseInt()也可以完成这项工作。选择你的毒药。

希望有帮助。另外,这不是唯一的方法,您必须确定这是否对您的脚本有用。