将可放置的 div 拖动到背景图像上的特定点
dragging a droppable div to a specific point on a background image
我正在尝试创建一个简单的教育游戏,其中将旗帜拖放到地图背景图像上的正确位置。所以我知道如何使旗帜可拖动和可放置,但不知道如何在地图上的特定点制作可放置区域。
这是我目前的情况:
<!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>
尝试将 Image-Map 与 Droppable 一起使用不会很有趣,也不会按照您想要的方式进行。
The <area>
tag defines an area inside an image-map (an image-map is an image with clickable areas).
The <area>
element is always nested inside a tag.
Note: The usemap attribute in the <img>
tag is associated with the <map>
element's name attribute, and creates a relationship between the image and the map.
这对我们的 UI 意味着什么?好吧,这有点暗示 <area>
元素不符合与 <img>
或 <div>
相同意义上的元素。它更像是一个坐标参考,用于检查某个区域是否被点击。它在 DOM 中,但它的盒子模型与其关联的图像相同。因此 $("map .china")
将具有与图像相同的宽度和位置。
这并不意味着它没有帮助。每个 <area>
元素仍然具有定义坐标的属性。所以 $("map .china").attr("coords")
将导致 "346,118,397,153"
我们可以用这个字符串做一些事情!
目标
- 允许用户将旗帜拖放到地图上
- 放下后,确定标志是否在坐标范围内
- 指示用户是否击中或未击中目标
- (将标志恢复到原来的位置?)
例子
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对象)
接受 jQuery 对象和 returns 基于对象位置和尺寸的 [x1, y1, x2, y2]
数组。
getObjCenter(jQuery对象)
接受一个 jQuery 对象和 returns 一个定义对象框中心的 [x, y]
数组。
命中(jQuery对象,数组坐标,数组偏移)
确定对象中心是否在 4 个区域坐标内。
备注
- 由于您没有定义如何处理命中或未命中,我只是在放下标志时将其发送到控制台。现在,可以放下旗帜然后再次移动。
.split()
用于将字符串转为数组,但它是一个字符串数组。 JavaScript 通常会接受这一点,但为了进行适当的比较,我已将它们转换为整数。
getObjCenter()
可以用数学四舍五入。请记住,除以一个奇数整数会产生一个 long (3 / 2 = 1.5) 而 HTML 不像半个 Pixel。您可以使用 Math.round()
或 Math.floor()
,但 parseInt()
也可以。选择你的毒药。
希望对您有所帮助。此外,这不是执行此操作的唯一方法,您必须决定这是否对您的脚本有用。
我正在尝试创建一个简单的教育游戏,其中将旗帜拖放到地图背景图像上的正确位置。所以我知道如何使旗帜可拖动和可放置,但不知道如何在地图上的特定点制作可放置区域。
这是我目前的情况:
<!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>
尝试将 Image-Map 与 Droppable 一起使用不会很有趣,也不会按照您想要的方式进行。
The
<area>
tag defines an area inside an image-map (an image-map is an image with clickable areas).The
<area>
element is always nested inside a tag.Note: The usemap attribute in the
<img>
tag is associated with the<map>
element's name attribute, and creates a relationship between the image and the map.
这对我们的 UI 意味着什么?好吧,这有点暗示 <area>
元素不符合与 <img>
或 <div>
相同意义上的元素。它更像是一个坐标参考,用于检查某个区域是否被点击。它在 DOM 中,但它的盒子模型与其关联的图像相同。因此 $("map .china")
将具有与图像相同的宽度和位置。
这并不意味着它没有帮助。每个 <area>
元素仍然具有定义坐标的属性。所以 $("map .china").attr("coords")
将导致 "346,118,397,153"
我们可以用这个字符串做一些事情!
目标
- 允许用户将旗帜拖放到地图上
- 放下后,确定标志是否在坐标范围内
- 指示用户是否击中或未击中目标
- (将标志恢复到原来的位置?)
例子
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对象)
接受 jQuery 对象和 returns 基于对象位置和尺寸的 [x1, y1, x2, y2]
数组。
getObjCenter(jQuery对象)
接受一个 jQuery 对象和 returns 一个定义对象框中心的 [x, y]
数组。
命中(jQuery对象,数组坐标,数组偏移)
确定对象中心是否在 4 个区域坐标内。
备注
- 由于您没有定义如何处理命中或未命中,我只是在放下标志时将其发送到控制台。现在,可以放下旗帜然后再次移动。
.split()
用于将字符串转为数组,但它是一个字符串数组。 JavaScript 通常会接受这一点,但为了进行适当的比较,我已将它们转换为整数。getObjCenter()
可以用数学四舍五入。请记住,除以一个奇数整数会产生一个 long (3 / 2 = 1.5) 而 HTML 不像半个 Pixel。您可以使用Math.round()
或Math.floor()
,但parseInt()
也可以。选择你的毒药。
希望对您有所帮助。此外,这不是执行此操作的唯一方法,您必须决定这是否对您的脚本有用。