Подтвердить что ты не робот

Увеличить изображение до разрыва курсора при перемещении мыши

Это вопрос о следующем вопросе Как увеличить указатель мыши при использовании моего собственного гладкого скругления колесика мыши?

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

С помощью Bali Balo в моем предыдущем вопросе мне удалось получить 90% пути.

Теперь вы можете масштабировать изображение до указателя мыши, сохраняя при этом гладкую прокрутку, как показано в следующем примере JSFiddle:

http://jsfiddle.net/qGGwx/7/

Однако функциональность прерывается при перемещении указателя мыши.

Чтобы еще раз пояснить, если я увеличиваю изображение на одной колесике на колесико мыши, изображение будет приближено к правильному положению. Такое поведение продолжается для каждой отметки, которую я увеличиваю на колесико мыши, полностью, как предполагалось. Если, однако, после изменения масштаба, я перемещаю мышь в другую позицию, функциональность ломается, и я должен полностью уменьшить масштаб, чтобы изменить положение зума.

Предполагаемое поведение заключается в том, чтобы любые изменения положения мыши в процессе масштабирования были правильно отражены в увеличенном изображении.

Две основные функции, которые управляют текущим поведением, следующие:

self.container.on('mousewheel', function (e, delta) {
        var offset = self.image.offset();

        self.mouseLocation.x = (e.pageX - offset.left) / self.currentscale;
        self.mouseLocation.y = (e.pageY - offset.top) / self.currentscale;

        if (!self.running) {
            self.running = true;
            self.animateLoop();
        }
        self.delta = delta
        self.smoothWheel(delta);
        return false;
    });

Эта функция собирает текущую позицию мыши в текущем масштабе масштабированного изображения.

Затем он запускает мой гладкий алгоритм прокрутки, который приводит к следующей функции, вызываемой для каждой интерполяции:

zoom: function (scale) {

    var self = this;
    self.currentLocation.x += ((self.mouseLocation.x - self.currentLocation.x) / self.currentscale);
    self.currentLocation.y += ((self.mouseLocation.y - self.currentLocation.y) / self.currentscale);

    var compat = ['-moz-', '-webkit-', '-o-', '-ms-', ''];
    var newCss = {};
    for (var i = compat.length - 1; i; i--) {
        newCss[compat[i] + 'transform'] = 'scale(' + scale + ')';
        newCss[compat[i] + 'transform-origin'] = self.currentLocation.x + 'px ' + self.currentLocation.y + 'px';
    }
    self.image.css(newCss);


    self.currentscale = scale;
},

Эта функция принимает значение шкалы (1-10) и применяет преобразования css, перемещая изображение с использованием источника преобразования.

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

Огромное спасибо заранее всем, кто может помочь.

4b9b3361

Ответ 1

Прежде чем вы проверите эту скрипту; Я должен упомянуть:

Прежде всего, в вашем методе .zoom(); вы не должны делиться на currentscale:

self.currentLocation.x += ((self.mouseLocation.x - self.currentLocation.x) / self.currentscale);
self.currentLocation.y += ((self.mouseLocation.y - self.currentLocation.y) / self.currentscale);

потому; вы уже используете этот коэффициент при вычислении mouseLocation внутри метода initmousewheel() следующим образом:

self.mouseLocation.x = (e.pageX - offset.left) / self.currentscale;
self.mouseLocation.y = (e.pageY - offset.top) / self.currentscale;

Итак, вместо этого; (в методе .zoom()), вы должны:

self.currentLocation.x += (self.mouseLocation.x - self.currentLocation.x);
self.currentLocation.y += (self.mouseLocation.y - self.currentLocation.y);

Но (например) a += b - a всегда будет выдавать b, поэтому приведенный выше код равен:

self.currentLocation.x = self.mouseLocation.x;
self.currentLocation.y = self.mouseLocation.y;

:

self.currentLocation = self.mouseLocation;

Тогда, кажется, вам даже не нужно self.currentLocation. (2 переменные для одного и того же значения). Итак, почему бы не использовать переменную mouseLocation в строке, где вы установили transform-origin вместо этого и избавиться от переменной currentLocation?

newCss[compat[i] + 'transform-origin'] = self.mouseLocation.x + 'px ' + self.mouseLocation.y + 'px';

Во-вторых,, вы должны включить прослушиватель событий mousemove в метод initmousewheel() (как и другие разработчики здесь), но он должен постоянно обновлять преобразование, а не только когда пользовательские колеса. В противном случае кончик указателя никогда не догонит, пока вы увеличиваете "любую" случайную точку.

self.container.on('mousemove', function (e) {
    var offset = self.image.offset();
    self.mouseLocation.x = (e.pageX - offset.left) / self.currentscale;
    self.mouseLocation.y = (e.pageY - offset.top) / self.currentscale;
    self.zoom(self.currentscale);
});

Итак, вам больше не нужно будет вычислять это в обработчике событий mousewheel, поэтому ваш метод initmousewheel() будет выглядеть следующим образом:

initmousewheel: function () {
    var self = this;

    self.container.on('mousewheel', function (e, delta) {
        if (!self.running) {
            self.running = true;
            self.animateLoop();
        }
        self.delta = delta;
        self.smoothWheel(delta);
        return false;
    });

    self.container.on('mousemove', function (e) {
        var offset = self.image.offset();
        self.mouseLocation.x = (e.pageX - offset.left) / self.currentscale;
        self.mouseLocation.y = (e.pageY - offset.top) / self.currentscale;
        self.zoom(self.currentscale); // <--- update transform origin dynamically
    });
}

Один выпуск:

Это решение работает так, как ожидалось, но с небольшой проблемой. Когда пользователь перемещает мышь на обычной или быстрой скорости; событие mousemove, похоже, пропустит окончательную позицию (проверено в Chrome). Таким образом, масштабирование будет немного ниже местоположения указателя. В противном случае, когда вы двигаете мышь медленно, она получает точную точку. Это должно быть легко обойти это, хотя.

Другие примечания и предложения:

  • У вас есть свойство duplicate (prevscale).
  • Я предлагаю вам всегда использовать JSLint или JSHint (который доступен на jsFiddle тоже), чтобы проверить ваш код.
  • Я настоятельно рекомендую вам использовать закрытие (часто называемое Expression Expression Function Expression (IIFE)), чтобы избежать возможности глобального охвата; и скрыть ваши внутренние/частные свойства и методы.

Ответ 2

Собственно, не слишком сложно. Вам просто нужно отделить логику обновления местоположения мыши от логики обновления масштабирования. Посмотрите мою скрипку: http://jsfiddle.net/qGGwx/41/

Все, что я сделал здесь, это добавить слушателя 'mousemove' в контейнер и поместить там логику обновления self.mouseLocation. Поскольку он больше не требуется, я также извлек логику обновления mouseLocation из обработчика "mousewheel". Код анимации остается прежним, как и решение о начале/остановке цикла анимации.

здесь код:

    self.container.on('mousewheel', function (e, delta) {
        if (!self.running) {
            self.running = true;
            self.animateLoop();
        }
        self.delta = delta
        self.smoothWheel(delta);
        return false;
    });

    self.container.on('mousemove', function (e) {
        var offset = self.image.offset();

        self.mouseLocation.x = (e.pageX - offset.left) / self.currentscale;
        self.mouseLocation.y = (e.pageY - offset.top) / self.currentscale;
    });

Ответ 3

Добавьте метод mousemover и вызовите его в методе init:

mousemover: function() {
    var self = this;
    self.container.on('mousemove', function (e) {

        var offset = self.image.offset();

        self.mouseLocation.x = (e.pageX - offset.left) / self.currentscale;
        self.mouseLocation.y = (e.pageY - offset.top) / self.currentscale;

        self.zoom(self.currentscale);
    });
},

Fiddle: http://jsfiddle.net/powtac/qGGwx/34/

Ответ 4

Точка масштабирования не совсем правильная из-за масштабирования изображения (0.9 в ratio). Фактически мышь указывает в частности точку в container, но мы масштабируем image. См. Этот скрипт http://jsfiddle.net/qGGwx/99/ Я добавляю marker с позицией, равной transform-origin. Поскольку вы видите, что размер изображения равен размеру контейнера, проблем нет. Вам нужно это масштабирование? Может быть, вы можете добавить второй контейнер? В скрипке я также добавил условие в mousemove

if(self.running && self.currentscale>1 && self.currentscale != self.lastscale) return;

Это предотвращает перемещение изображения во время масштабирования, а также создает проблему. Вы не можете изменить точку масштабирования, если zoom все еще работает.

Ответ 5

Расширение ответа @jordancpaul Я добавил константу mouse_coord_weight, которая умножается на дельту координат мыши. Это направлено на то, чтобы преобразование трансфокации было менее восприимчивым к изменению координат мыши. Проверьте http://jsfiddle.net/7dWrw/

Я переписал обработчик событий onmousemove как:

    self.container.on('mousemove', function (e) {
        var offset = self.image.offset();
        console.log(offset);

        var x = (e.pageX - offset.left) / self.currentscale,
            y = (e.pageY - offset.top) / self.currentscale;

        if(self.running) {
            self.mouseLocation.x += (x - self.mouseLocation.x) * self.mouse_coord_weight;
            self.mouseLocation.y += (y - self.mouseLocation.y) * self.mouse_coord_weight;
        } else {
            self.mouseLocation.x = x;
            self.mouseLocation.y = y;
        }

    });