长时间听众,第一次来电。
好的,我为这篇文章的篇幅道歉,但我想非常清楚我想要做什么,以及我曾试图指导你的答案。
目标: 我正在尝试创建一个100 x 100的瓷砖(图像)网格,我将一次仅显示网格的一部分,因为图像是240 x 120.通过单击按钮(注意:不需要鼠标滚动,缩放等。),用户将水平和垂直滚动。
作为一个类比,拿一个设置为玩的跳棋板,你正在低头看它。显示起来非常简单,只需要几个基本图像并将它们放在网格上。现在,考虑一下你只想显示底板的1/3。然后,当用户点击时,他们将视图移动到中间,然后再次单击将他们移到板的前1/3处。这是我尝试完成的一个简单示例,除了在视野/移动较小的大得多的网格上。
我尝试过的事情:
地图工具/缩放失败:
获得完整的地图和瓷砖后,我试图弄清楚如何只滚动这个窗口的一部分。一个灯泡熄灭了:"谷歌地图如何处理事情呢!"当麻烦开始的时候,我被兔子洞吸了一下,研究了所有这些真正让我无处可寻的地图工具,因为很简单,它们似乎只是用于显示地理地图。
然而,我确实在某个时刻被引导到了Zoomify,我认为这可能是一个选择。第一个问题是我似乎无法在没有完整图像的情况下拍摄自己的瓷砖,所以我尝试了在阳光下的每个屏幕捕获程序,尝试用完整的网格获取我的浏览器的完整镜头让zoomify让他们。我们只是说,这不起作用,但我尝试减小尺寸。它有点工作,但失去了很多质量,我意识到zoomify甚至没有真正完成我需要的东西,因为1.滚动不是那么顺利; 2.这些图像最终将包含一些与其X-Y坐标连接的链接,这意味着我需要控制每次点击向上,向下,向左,向右箭头时滚动多少。我自己没有尝试过这样做
好的,然后我回到了基础知识,我把网格扔进了一个溢出的DIV:隐藏在CSS上。太好了,现在我有了一个窗口。我不想一次加载所有这些图像,所以我只在绝对定位的DIV中绘制了具有唯一ID的网格的一部分(例如Tile_1_1)。这看起来很棒,但现在我需要让你看到你在点击箭头按钮时滚动网格,所以我把它扔到了一个javascript函数。我有javascript计算新X和新Y并交换所有图块的图像源,因为它们都是在网格上的X / Y坐标后命名的。实际上,这完全有效,现在地图滚动。问题是,只是改变图像源有点不稳定。毫无疑问,我们正在这个网格中移动,因为内容只是瞬间改变。而我的朋友就是我需要我们帮助的地方。
我哪里出错了?这次最新尝试是否在正确的轨道上?我是否需要完全重新考虑这个问题,或者是否有一些简单的方法可以更好地移动瓷砖而不是交换光源?
请记住,我在php,css等方面表现得相当不错,但我从来没有在javascript上投入太多时间,所以你可能需要在该领域做更多的解释。
P.S。这是我能在这些板上找到的最接近的东西,但它从来没有得到明确的答案:Tile scrolling / preloading (Google Maps style) of HTML layers with Ajax
更新:使用解决方案
我喜欢Cobby和pseudosavant的答案。 Pseudosavant的解决方案非常适合我的盟友,让CSS完成大部分艰苦的工作,但是我选择了Cobby的解决方案。我认为它会给我一点控制权,因为我实际上使用了一个菱形网格,我可以更好地包裹它(不要说另一个也不一定也能用)。
这就是我所做的。我知道代码有点粗糙,需要一些清理,但也许它可以帮助别人。
首先我需要找到我的X和Y轴之间的关系,所以我画了一个小图。
我很快注意到更多的X意味着在更远的左侧和更高处开始钻石以在视图的中心(用户定义的开始)获得正确的坐标,然后通过Y坐标偏移以取消一些负的左边和降低起点。
然后,绘制网格的PHP看起来像这样($ xcoord和$ ycoord来自一个表单):
//draw the grid
//Offset leftStart and topStart by Xcoord
$leftStart = 360 - ($xcoord * 120);
$topStart = 360 - ($xcoord * 60);
//Offset leftStart and topStart by Ycoord
$leftStart += ($ycoord * 120);
$topStart -= ($ycoord * 60);
for($y = 1; $y <= 99; $y++) { //y min to y max
$left = $leftStart;
$top = $topStart;
for($x = 1; $x <= 99; $x++) { //x min to x max
//I only want to draw part of the square
if(($x < ($xcoord + 6) && $x > ($xcoord - 6)) && ($y < ($ycoord + 6) && $y > ($ycoord - 6))) {
//Put out the image - this is how i needed mine formated
echo "\t<div class=\"move\" id=\"T" . $x . "_" . $y . "\" style='position:absolute; left:" . $left . "px; top:" . $top . "px;'>\n";
echo "\t\t<img src=\"./<path to your image>" . $x . "-" . $y . ".gif\">\n";
echo "\t</div>\n";
}
$left = $left + 120;
$top = $top + 60;
}
$leftStart = $leftStart - 120;
$topStart = $topStart + 60;
}
用溢出的方式抛出一个DIV:隐藏并给它一个ID(我的是#tileView)。好的,现在你的视图中有一个菱形网格,现在我们需要开始移动它!
这就是我的jquery看起来的样子。对不起,如果它需要改进,我昨天刚学会了Jquery和Ajax。
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#top").click(function(){
var y = document.getElementById('ycoord').value;
var x = document.getElementById('xcoord').value;
$(".move").animate({"left": "-=120px", "top": "+=60px"}, 500);
changeImg(x, y, 'up');
$("#ycoord").val(parseInt( y ) - 1);
});
$("#bottom").click(function(){
var y = document.getElementById('ycoord').value;
var x = document.getElementById('xcoord').value;
$(".move").animate({"left": "+=120px", "top": "-=60px"}, 500);
changeImg(x, y, 'down');
$("#ycoord").val(parseInt( y ) + 1);
});
$("#left").click(function(){
var y = document.getElementById('ycoord').value;
var x = document.getElementById('xcoord').value;
$(".move").animate({"left": "+=120px", "top": "+=60px"}, 500);
changeImg(x, y, 'left');
$("#xcoord").val(parseInt( x ) - 1);
});
$("#right").click(function(){
var y = document.getElementById('ycoord').value;
var x = document.getElementById('xcoord').value;
$(".move").animate({"left": "-=120px", "top": "-=60px"}, 500);
changeImg(x, y, 'right');
$("#xcoord").val(parseInt( x ) + 1);
});
function changeImg(x, y, move){
$.ajax({
type: "POST",
url: "addImage.php",
data: 'x=' + x + '&y=' + y + '&move=' + move,
cache: false,
success: function(html){
$(html).appendTo($("#tileView"));
}
});
$.ajax({
type: "POST",
url: "removeImage.php",
data: 'x=' + x + '&y=' + y + '&move=' + move,
cache: false,
success: function(xml){
$("removeTile",xml).each(function(id) {
removeTile = $("removeTile",xml).get(id);
removeID = $("tileID",removeTile).text();
$("#" + removeID).remove();
});
}
});
}
});
</script>
ajax调用addImage.php在正确的位置添加一个新行,而deleteImage.php则删除现在不在视图中的行(我发现没有删除事情开始运行的那些行很慢)。
在添加图片中,您只需找出要在页面中添加的html的新位置和输出。例如,part可能看起来像这样(但是根据move设置变量然后遍历循环):
if($_REQUEST["move"] == "up") {
$xmin = $x - 5;
$xmax = $x + 5;
$y = $y - 6;
$left = 360;
$top = -360;
for($i = $xmin; $i <= $xmax; $i++) {
$id = "T" . $i . "_" . $y;
$newTiles .= "<div class='move' style='position:absolute; left:" . $left . "px; top:" . $top . "px;' id='$id'><img src='./Map/TileGroup1/1-$i-$y.gif'></div>\n";
$left += 120;
$top += 60;
}
}
然后只需回显$ newTiles就可以使用。
删除类似,只需在xml中输入要删除的DIV ID,因为我无法使每个()无法正常工作。
if($_REQUEST["move"] == "up") {
$xmin = $x - 5;
$xmax = $x + 5;
$y = $y + 5;
echo "<?xml version=\"1.0\"?>\n";
echo "<response>\n";
for($i = $xmin; $i <= $xmax; $i++) {
echo "\t<removeTile>\n";
echo "\t\t<tileID>T" . $i . "_" . $y . "</tileID>\n";
echo "\t</removeTile>\n";
}
echo "</response>";
}
希望这有助于某人。谢谢大家的想法和支持!
答案 0 :(得分:2)
这是我之前使用的解决方案。
<div>
,其中inline-block
设置为<img>
。通过<div>
控制标题的宽度和高度。 *重要的是<div>
元素之间没有空白区域,否则瓷砖不会彼此相邻。#container
<div>
line-height
0。容器应设置为图块大小的倍数,因为图块会自动换行。所以20个瓷砖可以是4x5或5x4,具体取决于容器的大小。#container
应该在我称之为视口的<div>
overflow: hidden
。您可以使用jQuery和#viewport
.scrollLeft
滚动.scrollTop
。这是一个jsfiddle示例:http://jsfiddle.net/pseudosavant/b4hSV/
答案 1 :(得分:1)
我认为您需要回到使用overflow:hidden
嵌套在DIV中的整个网格的方法,但是使用JavaScript来确定哪些图像应该是可见的,并且只根据需要加载这些图像,然后加载当用户滚动到该区域时,在其他相关图像中。
滚动当然应该操纵网格的left
和top
CSS属性,以便在包含overflow: hidden
DIV中移动它。在您的情况下,最简单的方法就是以图块大小的增量更改定位CSS属性(因此您永远不会显示部分图块)。
从编程的角度来看,这有点痛苦,但听起来你已经有了计算哪些/应该显示的方法?
使用此方法,首次加载图像时会出现初始毛刺,但随后移动网格将不必重新加载相同的图像。一旦你有了这个工作,你可以使用jQuery或类似的方法来动画left
和top
属性,以提供平滑的滚动效果。
然后,如果您愿意,可以进一步构建,并允许部分滚动图块并点击并拖动滚动,如Google地图。此外,如果你想要提高性能,我建议你设置一个nginx服务器来监听你网站的几个子域,以提供平铺图像。
编辑:我建议在容器scrollLeft
(具有scrollTop
)上设置div
和overflow: hidden
的动画,但会提供更好的效果/更顺畅的滚动。
有一个名为TileMill的简洁程序,而OP不会使用它,它可能适用于其他人。
答案 2 :(得分:1)
如果您的动画是基于时间的,而不是基于位置/帧数,则您只能提供流畅的动画体验。我首先看一下requestAnimationFrame
(或适当的,基于时间的polyfill)并设计你的动画/定位计算是基于时间的。问题是:
给定时间
t
我的地图的x
和y
滚动偏移应该是什么?
然后考虑使用错觉将视口放入一个巨大的图块集,而不是实际上有一个使用overflow: hidden
来查看小视口的大量图块集。你不想用太多的瓷砖耗尽DOM。
假设您的视口允许查看4 x 4个图块,当图块偏移不会与您的视口对齐时,考虑到部分显示的图块,最多可以显示5 x 5个图块(大多数情况下都会如此)时间)。无论你的地图实际拥有多少个瓷砖,5 x 5瓷砖都将是你所需要的。这是一个草图:
任务将是: