Плавная прокрутка плитки изображения на большой сетке? - программирование
Подтвердить что ты не робот

Плавная прокрутка плитки изображения на большой сетке?

Длительный слушатель, первый раз вызывающий абонент.

Хорошо, я приношу свои извинения за длину этого сообщения, но я хочу быть предельно ясным в том, что я пытаюсь сделать, и о том, что я пытался, надеюсь, руководствовать ваши ответы.

Цель: Я пытаюсь создать сетку из плиток (изображений) 100 х 100, и я буду отображать только часть сетки за раз, потому что изображения 240 х 120. Нажимая кнопки (обратите внимание: нет необходимости в прокрутке мыши, масштабировании и т.д..), пользователь будет перемещаться по горизонтали и по вертикали.

В качестве аналогии возьмите шашку, которая настроена для игры, и вы смотрите на нее. Было бы довольно просто отобразить, требуя всего лишь нескольких базовых изображений и помещая их в сетку. Теперь подумайте, что вы только хотели показать нижнюю 1/3 платы. Затем, когда пользователь нажимает на них, они перемещают свой вид на середину, а другой щелчок берет их на верхнюю 1/3 панели. Это простой пример того, что я пытаюсь выполнить, за исключением гораздо большей сетки с меньшим представлением/перемещением.

Что я пробовал:

  • Сначала я написал код в PHP, чтобы нарисовать полную сетку 100x100, и все выглядело великолепно.
  • Затем я изменил код, чтобы на самом деле писать файлы для каждого квадрата, сохраняя их как X-Y.png
  • Я втянулся в мир инструментов карты и инструментов типа масштабирования.
  • У меня был некоторый частичный успех при написании собственного решения.

Инструменты карты/Масштабирование сбоя:

После получения полной карты и фрагментов я попытался выяснить, как черт прокручивать часть этого окна. Лампочка погасла: "как насчет того, как карты Google делают что-то!" Это, когда начались неприятности, и я засасывал кроличью нору, изучая все эти картографические инструменты, которые действительно меня не достали, потому что просто они кажутся только для отображения географических карт.

Однако, в какой-то момент я получил Zoomify, и я подумал, что это действительно вариант. Первая проблема заключалась в том, что я не мог заставить ее забрать свои собственные плитки без одного снимка полного изображения, поэтому я попробовал каждую программу захвата экрана под солнцем, чтобы попытаться получить полный снимок моего браузера с полной сеткой, чтобы позволить zoomize сделать их. Скажем так, это не сработало, но я попытался уменьшить размер. Это сработало, но потеряло много качества, и я понял, что zoomize даже не выполняет действительно то, что мне нужно, потому что 1. свиток не так гладен; и 2. эти изображения в конечном итоге содержат некоторые ссылки, связанные с их координатами X-Y, что означает, что мне нужно контролировать, сколько прокручивается каждый раз, когда будут нажаты стрелки вверх, вниз, влево, вправо.

Моя неудачная попытка сделать это не сама.

Хорошо, тогда я вернулся к основам, и я выбросил сетку в DIV с переполнением: скрытый в CSS. Отлично, теперь у меня было окно. Я не хотел загружать все эти изображения одновременно, поэтому я рисовал только часть сетки в абсолютно позиционированных DIV с уникальным идентификатором (например, Tile_1_1). Все это выглядело отлично, но теперь мне нужно было убедиться, что вы прокручиваете сетку при нажатии на кнопки со стрелками, поэтому я бросил ее на функцию javascript для этого. У меня был javascript, который вычисляет новый X и новый Y и заменяет источник изображения всех фрагментов, так как все они названы после их координат X/Y в сетке. Фактически, это полностью сработало, и теперь карта прокручивается. Проблема в том, что это немного изменчиво, чтобы просто изменить источники изображения. Нет иллюзий, что мы перемещаемся по этой сетке так же сильно, как только контент мгновенно меняется. И ЭТО мои друзья - это то, где мне нужна наша помощь.

Где я ошибся? Был ли я на правильном пути с этой последней попыткой? Должен ли я полностью переосмыслить это или есть какое-то простое исправление для перемещения плиток немного элегантнее, чем замена источника?

Пожалуйста, имейте в виду, что я неплохо справился с php, css и т.д., но я никогда не вкладывал много времени в javascript, поэтому вам может понадобиться немного больше объяснить в этой области.

P.S. это была самая близкая вещь, которую я мог найти на этих досках, но на самом деле она не получила четкого ответа: Прокрутка/предварительная загрузка плитки (стиль Google Maps) слоев HTML с помощью Ajax

Обновление: используемое решение

Мне понравились и ответы Cobby, и псевдопоты. Решение Pseudosavant было действительно правильным моим союзником, позволяя CSS выполнять большую часть тяжелой работы, однако я пошел с решением Cobby. Я думал, что это даст мне немного больше контроля, и потому, что я на самом деле использую бриллиантовую сетку, я мог бы обернуть вокруг себя голову (не говоря, что другой тоже не обязательно будет работать).

Вот что я сделал. Я знаю, что код немного груб и нуждается в некоторой очистке, но, возможно, он может помочь кому-то.

Сначала мне нужно было найти связь между моей осью X и Y, поэтому я сделал небольшую диаграмму.

enter image description here

Я быстро заметил, что больше 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 вокруг этого с переполнением: спрячьте и дайте ему идентификатор (мой - #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 для добавления на страницу. Например, часть может выглядеть так (но установить переменные в зависимости от перемещения, затем пройти через цикл):

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;
    }
}

то просто используйте echo $newTiles для использования script.

Удалить похоже, просто выставляя в xml идентификатор DIV для удаления, потому что я не мог заставить каждый() работать иначе.

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>"; 
}

Надеюсь, это поможет кому-то. Спасибо всем за идеи и поддержку!

4b9b3361

Ответ 1

Я думаю, вам нужно вернуться к подходу всей сетки, вложенной в DIV с помощью overflow:hidden, но использовать JavaScript, чтобы определить, какие изображения должны быть видимыми, и загружать только эти изображения по мере необходимости, а затем загружать в дополнительные соответствующие изображения, когда пользователь прокручивает эту область.

Прокрутка, конечно, должна просто манипулировать свойствами CSS left и top для вашей сетки, чтобы переместить ее в содержащем overflow: hidden DIV. В вашем случае было бы проще всего просто изменить свойства CSS позиционирования с шагом вашего размера плитки (так что у вас никогда не будет показов фрагментов).

С точки зрения программирования это немного больно, но похоже, что у вас уже есть метод для расчета того, какие из них должны/должны отображаться?

С помощью этого метода он будет иметь первоначальный сбой при загрузке изображений в первый раз, но последующее перемещение сетки не придется перезагружать одни и те же изображения. После того, как вы это сделаете, вы можете использовать jQuery или аналогично анимации свойств left и top, чтобы обеспечить плавный эффект прокрутки.

Затем, если вы хотите, вы можете использовать это дальше и разрешить частичную прокрутку фрагментов и прокрутку по клику и перетаскиванию, такую ​​как Google Maps. Кроме того, если вы хотите работать с производительностью, я рекомендую настроить сервер nginx, который прослушивает несколько поддоменов вашего сайта, чтобы воспроизводить изображения с фрагментами.

РЕДАКТИРОВАТЬ: Я рекомендую анимировать scrollLeft и scrollTop в контейнере div (который имеет overflow: hidden), даст гораздо лучшую производительность/плавную прокрутку.


Существует чистая программа под названием TileMill, в то время как OP не использует ее, она может быть применима для других людей.

Ответ 2

Вот решение, которое я использовал раньше.

  • Плитки должны быть <div>, которые должны быть inline-block с <img> внутри него. Управляйте шириной и высотой заголовка с помощью <div>. * Важно, чтобы между элементами <div> не было белого пространства, иначе плитки не будут закрыты рядом друг с другом.
  • Плитки должны быть в #container <div>, который имеет line-height 0. Контейнер должен быть установлен в несколько кратных размерах плитки, так как плитки автоматически завернут линию. Таким образом, 20 плиток могут быть 4x5 или 5x4 в зависимости от размера контейнера.
  • #container должен находиться в другом <div> с overflow: hidden, который я вызываю в окне просмотра. Вы можете прокручивать #viewport с помощью jQuery и .scrollLeft .scrollTop.

Вот пример jsfiddle: http://jsfiddle.net/pseudosavant/b4hSV/

Ответ 3

Вы можете дать ровную анимацию, если ваша анимация основана на времени, а не на позиции/фрейме. Я бы начал с рассмотрения requestAnimationFrame (или правильных полиномиальных по времени для него) и разработал вычисления анимации/позиционирования, исходя из. Вопрос:

заданное время t, что должны делать прокрутки x и y смещения моей карты?

Затем подумайте о том, чтобы использовать иллюзию наличия видового экрана в массивном наборе плиток, вместо того, чтобы на самом деле иметь массивный набор плиток, который использует overflow: hidden для просмотра маленького окна просмотра. Вы не хотите исчерпывать DOM со слишком большим количеством фрагментов.

Предположим, что ваш viewport позволяет просматривать 4 x 4 плитки, которые составляют максимум 5 x 5 фрагментов с учетом частично отображаемых фрагментов, когда смещение плитки не привязывается к вашему окну просмотра (что будет в большинстве случаев времени). 5 x 5 плиток будут все, что вам когда-либо понадобится, независимо от того, сколько плиток на вашей карте действительно есть. Здесь эскиз:

http://jsfiddle.net/6uRHD/

Задача:

  • Рассчитать ускорение/скорость/позицию на основе действий пользователя (прокрутка, подталкивание с демпфированием), а затем вычислить положение в момент времени t анимации.
  • Рассчитайте, какие плитки попадают в набор 5 x 5, основанный на позиции, а также вычисляют смещение видового экрана для этих фрагментов.