移动鼠标时,将图像缩放到光标中断

gor*_*dyr 22 javascript image zoom css-transforms

这是如何在使用我自己的鼠标滚轮smoothscroll时缩放到鼠标指针的后续问题

我正在使用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;
    });
Run Code Online (Sandbox Code Playgroud)

此功能收集鼠标在缩放图像的当前比例下的当前位置.

然后它开始我的平滑滚动算法,导致为每个插值调用下一个函数:

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;
},
Run Code Online (Sandbox Code Playgroud)

此函数采用比例量(1-10)并应用css变换,使用transform-origin重新定位图像.

虽然这对于在图像完全缩小时选择的静止鼠标位置非常有效; 如上所述,在部分缩放后移动鼠标光标时会中断.

非常感谢任何可以提供帮助的人.

jor*_*aul 8

其实,不是太复杂.您只需将鼠标位置更新逻辑与缩放更新逻辑分开即可.看看我的小提琴:http: //jsfiddle.net/qGGwx/41/

我在这里所做的只是在容器上添加一个'mousemove'监听器,并将self.mouseLocation更新逻辑放在那里.由于不再需要,我还从'mousewheel'处理程序中取出了mouseLocation更新逻辑.动画代码保持不变,决定何时开始/停止动画循环.

这是代码:

    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;
    });
Run Code Online (Sandbox Code Playgroud)


Onu*_*rım 5

在你检查这个小提琴之前; 我应该提一下:

首先,在你的.zoom()方法中; 你不应该除以currentscale:

self.currentLocation.x += ((self.mouseLocation.x - self.currentLocation.x) / self.currentscale);
self.currentLocation.y += ((self.mouseLocation.y - self.currentLocation.y) / self.currentscale);
Run Code Online (Sandbox Code Playgroud)

因为; 在计算方法mouseLocation内部时你已经使用了这个因子,initmousewheel()如下所示:

self.mouseLocation.x = (e.pageX - offset.left) / self.currentscale;
self.mouseLocation.y = (e.pageY - offset.top) / self.currentscale;
Run Code Online (Sandbox Code Playgroud)

所以与其; (在.zoom()方法中),你应该:

self.currentLocation.x += (self.mouseLocation.x - self.currentLocation.x);
self.currentLocation.y += (self.mouseLocation.y - self.currentLocation.y);
Run Code Online (Sandbox Code Playgroud)

但是(例如)a += b - a将始终生成b所以上面的代码等于:

self.currentLocation.x = self.mouseLocation.x;
self.currentLocation.y = self.mouseLocation.y;
Run Code Online (Sandbox Code Playgroud)

简而言之:

self.currentLocation = self.mouseLocation;
Run Code Online (Sandbox Code Playgroud)

然后,你似乎甚至不需要self.currentLocation.(2个变量为相同的值).那么为什么不在mouseLocation你设置的行中使用变量transform-origin并去除currentLocation变量呢?

newCss[compat[i] + 'transform-origin'] = self.mouseLocation.x + 'px ' + self.mouseLocation.y + 'px';
Run Code Online (Sandbox Code Playgroud)

其次,你应该mousemoveinitmousewheel()方法中包含一个事件监听器(就像这里建议的其他开发者一样),但它应该连续更新转换,而不仅仅是当用户轮换时.否则当你缩小"任意"随机点时,指针的尖端永远不会赶上.

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);
});
Run Code Online (Sandbox Code Playgroud)

所以; 你不需要在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
    });
}
Run Code Online (Sandbox Code Playgroud)

一个问题:

此解决方案按预期工作但有一个小问题.当用户以常规或快速移动鼠标时; 该mousemove事件似乎错过了最终位置(在Chrome中测试过).因此缩放将略微偏离指针位置.否则,当您慢慢移动鼠标时,它会获得准确的点.尽管如此,应该很容易解决这个问题.

其他注意事项和建议:

  • 你有一个重复的属性(prevscale).
  • 我建议你总是使用的JSLintJSHint(这可以用的jsfiddle太)来验证你的代码.
  • 我强烈建议您使用闭包(通常称为立即调用函数表达式(IIFE))以尽可能避免全局范围; 并隐藏您的内部/私有属性和方法.