目标很简单,使用鼠标滚轮,放大到特定点(鼠标所在的位置)。这意味着在缩放后,鼠标将与图片大致相同的位置。
我不想使用画布,到目前为止,我尝试过这样的事情:
<img src="whatever">
function zoom(e){
var deltaScale = deltaScale || -e.deltaY / 1000;
var newScale = scale + deltaScale;
var newWidth = img.naturalWidth * newScale;
var newHeight = img.naturalHeight * newScale;
var x = e.pageX;
var y = e.pageY;
var newX = x * newWidth / img.width;
var newY = y * newHeight / img.height;
var deltaX = newX - x;
var deltaY = newY - y;
setScale(newScale);
setPosDelta(-deltaX,-deltaY);
}
function setPosDelta(dX, dY) {
var imgPos = getPosition();
setPosition(imgPos.x + dX, imgPos.y + dY);
}
function getPosition() {
var x = parseFloat(img.style.left);
var y = parseFloat(img.style.top);
return {
x: x,
y: y
}
}
function setScale(n) {
scale = n;
img.width = img.naturalWidth * n;
img.height = img.naturalHeight * n;
}
这样做的目的是计算海豚眼睛的 x,y坐标 之前的和之后的,计算这两点之间的距离后,从左,顶位置对其进行减法,以纠正变焦位移,但没有特别成功。
变焦发生自然地将图像向右和向下延伸,因此校正尝试向左拉回到顶部,以便将鼠标保持在那该死的海豚眼上!但它肯定没有。
告诉我,代码/数学有什么问题?考虑到除了画布之外我找不到任何解决方案,我觉得这个问题不是太宽泛。
谢谢!
CSS转换顺序很重要,如果您按照选定的答案,请确保先按顺序排序,然后再按比例排序。 CSS变换向后执行(从右到左),因此首先处理缩放,然后处理翻译。
答案 0 :(得分:6)
这是缩放到某一点的实现。该代码使用CSS 2D transform,并包括在单击和拖动时平移图像。这很容易,因为规模没有变化。
缩放时的技巧是首先使用当前比例标准化偏移量(换句话说:除以当前比例),然后将新比例应用于该标准化偏移。这使光标准确地保持在与刻度无关的位置。
var scale = 1,
panning = false,
xoff = 0,
yoff = 0,
start = {x: 0, y: 0},
doc = document.getElementById("document");
function setTransform() {
doc.style.transform = "translate(" + xoff + "px, " + yoff + "px) scale(" + scale + ")";
}
doc.onmousedown = function(e) {
e.preventDefault();
start = {x: e.clientX - xoff, y: e.clientY - yoff};
panning = true;
}
doc.onmouseup = function(e) {
panning = false;
}
doc.onmousemove = function(e) {
e.preventDefault();
if (!panning) {
return;
}
xoff = (e.clientX - start.x);
yoff = (e.clientY - start.y);
setTransform();
}
doc.onwheel = function(e) {
e.preventDefault();
// take the scale into account with the offset
var xs = (e.clientX - xoff) / scale,
ys = (e.clientY - yoff) / scale,
delta = (e.wheelDelta ? e.wheelDelta : -e.deltaY);
// get scroll direction & set zoom level
(delta > 0) ? (scale *= 1.2) : (scale /= 1.2);
// reverse the offset amount with the new scale
xoff = e.clientX - xs * scale;
yoff = e.clientY - ys * scale;
setTransform();
}
&#13;
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
#document {
width: 100%;
height: 100%;
transform-origin: 0px 0px;
transform: scale(1) translate(0px, 0px);
}
&#13;
<div id="document">
<img style="width: 100%"
src="http://lorempixel.com/output/animals-q-c-1920-1920-9.jpg" />
</div>
&#13;
答案 1 :(得分:3)
这是一个更接近原始想法的实现,使用顶部和左侧偏移并修改图像的宽度属性,而不是在我的其他答案中使用css变换。
var scale = 1.0,
img = document.getElementById("image"),
deltaX = 0,
deltaY = 0;
// set the initial scale once the image is loaded
img.onload = function() {
scale = image.offsetWidth / image.naturalWidth;
}
img.onwheel = function(e) {
e.preventDefault();
// first, remove the scale so we have the native offset
var xoff = (e.clientX - deltaX) / scale,
yoff = (e.clientY - deltaY) / scale,
delta = (e.wheelDelta ? e.wheelDelta : -e.deltaY);
// get scroll direction & set zoom level
(delta > 0) ? (scale *= 1.05) : (scale /= 1.05);
// limit the smallest size so the image does not disappear
if (img.naturalWidth * scale < 16) {
scale = 16 / img.naturalWidth;
}
// apply the new scale to the native offset
deltaX = e.clientX - xoff * scale;
deltaY = e.clientY - yoff * scale;
// now modify the attributes of the image to reflect the changes
img.style.top = deltaY + "px";
img.style.left = deltaX + "px";
img.style.width = (img.naturalWidth * scale) + "px";
}
window.onresize = function(e) {
document.getElementById("wrapper").style.width = window.innerWidth + "px";
document.getElementById("wrapper").style.height = window.innerHeight + "px";
}
window.onload = function(e) {
document.getElementById("wrapper").style.width = window.innerWidth + "px";
document.getElementById("wrapper").style.height = window.innerHeight + "px";
}
&#13;
html,
body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
div {
overflow: hidden;
}
&#13;
<div id="wrapper" style="position:relative;">
<img id="image" style="width:100%;position:absolute;top:0px;left:0px;" src="http://lorempixel.com/output/animals-q-c-1920-1920-9.jpg" alt="">
</div>
&#13;
答案 2 :(得分:0)
我喜欢fmacdee的这两个帖子。我将他创建的代码考虑成可以在任何图像上调用的可重用版本。
只需致电:
var imageScaler = new ImageScaler(document.getElementById("image"));
imageScaler.setup();
并在项目的某处包含此代码:
var ImageScaler = function(img)
{
this.img = img;
this.scale = this.getImageScale();
this.panning = false;
this.start = {x: 0, y: 0};
this.delta = {x: 0, y: 0};
};
ImageScaler.prototype =
{
constructor: ImageScaler,
setup: function()
{
this.setupEvents();
},
setupEvents: function()
{
var img = this.img;
var callBack = this.onScale.bind(this);
var touchDown = this.touchDown.bind(this),
touhcMove = this.touchMove.bind(this),
touchUp = this.touchUp.bind(this);
img.onwheel = callBack;
img.onmousedown = touchDown;
img.onmousemove = touhcMove;
img.onmouseup = touchUp;
},
getImageScale: function()
{
var img = this.img;
return img.offsetWidth / img.naturalWidth;
},
getMouseDirection: function(e)
{
return (e.wheelDelta ? e.wheelDelta : -e.deltaY);
},
getOffset: function(e)
{
var scale = this.scale,
delta = this.delta;
// first, remove the scale so we have the native offset
return {
x: (e.clientX - delta.x) / scale,
y: (e.clientY - delta.y) / scale
};
},
scaleElement: function(x, y, scale)
{
var img = this.img;
img.style.top = y + "px";
img.style.left = x + "px";
img.style.width = (img.naturalWidth * scale) + "px";
},
minScale: 0.2,
updateScale: function(delta)
{
// get scroll direction & set zoom level
var scale = (delta > 0) ? (this.scale *= 1.05) : (this.scale /= 1.05);
// limit the smallest size so the image does not disappear
if (scale <= this.minScale)
{
this.scale = this.minScale;
}
return this.scale;
},
touchDown: function(e)
{
var delta = this.delta;
this.start = {x: e.clientX - delta.x, y: e.clientY - delta.y};
this.panning = true;
},
touchMove: function(e)
{
e.preventDefault();
if (this.panning === false)
{
return;
}
var delta = this.delta,
start = this.start;
delta.x = (e.clientX - start.x);
delta.y = (e.clientY - start.y);
console.log(delta, start)
this.scaleElement(delta.x, delta.y, this.scale);
},
touchUp: function(e)
{
this.panning = false;
},
onScale: function(e)
{
var offset = this.getOffset(e);
e.preventDefault();
// get scroll direction & set zoom level
var delta = this.getMouseDirection(e);
var scale = this.updateScale(delta);
// apply the new scale to the native offset
delta = this.delta;
delta.x = e.clientX - offset.x * scale;
delta.y = e.clientY - offset.y * scale;
this.scaleElement(delta.x, delta.y, scale);
}
};
我做了一个小提琴来查看结果:http://jsfiddle.net/acqo5n8s/12/