Javascript (jQuery) масштабирует изображение до его центральной точки контейнера - PullRequest
9 голосов
/ 30 декабря 2011

Кажется, это должно быть довольно просто, но по какой-то причине я не могу обернуть это вокруг себя. У меня есть изображение внутри div "viewport", свойство overflow которого скрыто.

Я реализовал простое масштабирование и панорамирование с помощью пользовательского интерфейса jQuery, однако у меня возникают проблемы с отображением увеличения в центре области просмотра. Я сделал небольшой скринкаст из фотошопа о том эффекте, который пытаюсь воспроизвести: http://dl.dropbox.com/u/107346/share/reference-point-zoom.mov

В PS вы можете настроить масштабную контрольную точку, чтобы объект масштабировался от этой точки. Очевидно, что это невозможно с HTML / CSS / JS, поэтому я пытаюсь найти соответствующие левые и верхние значения CSS, чтобы имитировать эффект.

Вот код, о котором идет речь, с удалением нескольких ненужных битов:

HTML

<div id="viewport">
    <img id="map" src="http://dl.dropbox.com/u/107346/share/fake-map.png" alt="" />
</div>

<div id="zoom-control"></div>

Javascript

$('#zoom-control').slider({
    min: 300,
    max: 1020,
    value: 300,
    step: 24,
    slide: function(event, ui) {
        var old_width = $('#map').width();
        var new_width = ui.value;
        var width_change = new_width - old_width;
        $('#map').css({
            width: new_width,

            // this is where I'm stuck...
            // dividing by 2 makes the map zoom
            // from the center, but if I've panned
            // the map to a different location I'd
            // like that reference point to change.
            // So instead of zooming relative to
            // the map image center point, it would
            // appear to zoom relative to the center
            // of the viewport. 
            left: "-=" + (width_change / 2),
            top: "-=" + (width_change / 2)
        });
    }
});

Вот проект на JSFiddle: http://jsfiddle.net/christiannaths/W4seR/

Ответы [ 3 ]

5 голосов
/ 30 декабря 2011

Вот рабочее решение. Я объясню логику при следующем редактировании.

Функциональная логика:

  • Резюме: Запомните центральное положение изображения, относительно .
    Расчеты для ширины и высоты аналогичны, я объясню только вычисление height
    Подробное объяснение является лишь примером функциональной логики. Реальный код с разными именами переменных можно найти внизу ответа.

    1. Рассчитать центр (x, y) #map относительно #viewport. Это можно сделать с помощью методов offset(), height() и width().

      // Absolute difference between the top border of #map and #viewport
      var differenceY = viewport.offset().top - map.offset().top;
      // We want to get the center position, so add it.
      var centerPosition = differenceY + viewport.height() * 0.5;
      // Don't forget about the border (3px per CSS)
      centerPosition += 3;
      // Calculate the relative center position of #map
      var relativeCenterY = centerPosition / map.height();
      // RESULT: A relative offset. When initialized, the center of #map is at
      //  the center of #viewport, so 50% (= 0.5)
      // Same method for relativeCenterX
      
    2. Рассчитать новое верхнее и левое смещения:

      // Calculate the effect of zooming (example: zoom 1->2 = 2)
      var relativeChange = new_width / old_width;
      // Calculate the new height
      var new_height = relativeChange * old_height;
      // Calculate the `top` and `left` CSS properties.
      // These must be negative if the upperleft corner is outside he viewport
      // Add 50% of the #viewport's height to correctly position #map
      //   (otherwise, the center will be at the upperleft corner)
      var newTopCss = -relativeCenterY * new_height + 0.5 * viewport.height();
      
    3. Изменить свойство CSS

      map.css("top", newTopCss);
      

Демо: http://jsfiddle.net/W4seR/12/

var map = $('#map');
var viewport = $('#viewport');
// Cache the size of the viewport (300x300)
var viewport_size = {
    x: viewport.width(),
    y: viewport.height()
};

map.draggable();

$('#zoom-control').slider({
    min: 300,
    max: 1020,
    value: 300,
    step: 24,
    create: function() {
        map.css({
            'width': 300,
            'left': 0,
            'top': 0
        });
    },
    slide: function(event, ui) {
        var old_width = map.width();
        var old_height = map.height();
        var viewport_offset = viewport.offset();
        var offset = map.offset();
        offset = {
            top: viewport_offset.top - offset.top + .5*viewport_size.y +3,
            left: viewport_offset.left - offset.left + .5*viewport_size.x +3
        };
        // Relative offsets, relative to the center!
        offset.top = offset.top / old_height;
        offset.left = offset.left / old_width;

        var new_width = ui.value;
        var relative = new_width / old_width;
        var new_height = relative * old_height;

        offset = {
            top: -offset.top * new_height + .5*viewport_size.y,
            left: -offset.left * new_width + .5*viewport_size.x
        };

        var css_properties = {
            width: new_width,
            left: offset.left,
            top: offset.top
        };

        map.css(css_properties);

        trace((map.position().left));
    }
});
1 голос
/ 30 декабря 2011

Я всегда полагался на доброту незнакомцев .Соответствующие изменения:

// Calculate the offset as a percentage, accounting for the height of the window
var x_offset = ((map.position().left-150))/(old_width/2);
var y_offset = ((map.position().top-150))/(old_width/2);

var css_properties = {
    width: new_width,
    // Set the offset based on the existing percentage rather than 1/2
    // then readjust for the height of the window
    left: (new_width * x_offset /2 ) + 150 + "px", 
    top: (new_width * y_offset /2 ) + 150 + "px"
};

Замените жестко закодированный 150 переменной, установленной при создании экземпляра области просмотра при необходимости.

0 голосов
/ 30 декабря 2011

Вот быстрая рабочая версия: http://jsfiddle.net/flabbyrabbit/chLkZ/

Возможно, это не самое удачное решение, но, похоже, оно работает хорошо, надеюсь, оно поможет.

Обновление: извините, это работает только при увеличении 0когда карта перемещена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...