首页 前端知识 html、css、js实现图片放大功能,包括拖拽和滚动焦点缩放

html、css、js实现图片放大功能,包括拖拽和滚动焦点缩放

2024-02-02 09:02:49 前端知识 前端哥 35 767 我要收藏

1. 前言

  • 实现图片点击放大、拖拽、滚轴滚动焦点缩放功能
  • 放了完整,coder可以复制去看效果,不要忘记替换代码中的图片路径

2. 代码

2.1 html+js+css完成代码

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div class="imgBox">
<img style="width: 150px; height: 150px; padding: 10px" src="../../../images/HTTP工作原理.jpg" class="img-responsive" />
<img style="width: 150px; height: 150px; padding: 10px" src="../../../images/HTTP报文结构.jpg" class="img-responsive" />
</div>
<div id="outerdiv" style="
position: fixed;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.7);
z-index: 2;
width: 100%;
height: 100%;
display: none;
">
<img id="bigimg" src="" />
</div>
<script>
/**
* 实现图片点击放大、拖拽、滚轴滚动焦点缩放功能,相关参数、函数声明
*/
let imgWidth, imgHeight; // 图片点击放大初始尺寸参数
let maxZoom = 4; //最大缩放倍数
let minreduce = 0.5; // 最小缩放倍数
let initScale = 1; //滚动缩放初始倍数,并不是图片点击放大的倍数
let isPointerdown = false; //鼠标按下的标识
//记录鼠标按下坐标和按下移动时坐标
let lastPointermove = {
x: 0,
y: 0,
};
//移动过程从上一个坐标到下一个坐标之间的差值
let diff = {
x: 0,
y: 0,
};
//图片放大后左上角的坐标,主要结合diff参数用于鼠标焦点缩放时图片偏移坐标
let x = 0;
let y = 0;
// 记录节点
const allImg = document.querySelectorAll(".imgBox img");
const outerdiv = document.querySelector("#outerdiv");
const image = outerdiv.querySelector("#bigimg");
window.onload = function () {
allImg.forEach((item) => {
item.addEventListener("click", (e) => {
const that = e.target;
image.style.transform = "scale(1)";
//图片放大展示函数调用
imgShow(that);
// 监听鼠标滚动事件
window.addEventListener("wheel", handleStopWheel, {
passive: false,
});
// 拖转事件调用
imgDrag();
});
});
};
function imgShow(that) {
let src = that.getAttribute("src");
image.setAttribute("src", src);
// 设置尺寸和调整比例
let windowW = document.documentElement.clientWidth;
let windowH = document.documentElement.clientHeight;
let realWidth = image.naturalWidth; //获取图片的原始宽度
let realHeight = image.naturalHeight; //获取图片的原始高度
let outsideScale = 0.8;
let belowScale = 1.4;
let realRatio = realWidth / realHeight;
let windowRatio = windowW / windowH;
// 说明:下面是我自己的一些判断逻辑,大致意思就是图片的真实尺寸大于屏幕尺寸则使用屏幕尺寸,如果小于屏幕尺寸就使用自己本身的尺寸;并根据大于或者小于的比例对图片的尺寸进一步调整。coder可以根据自己的要求进行修改。
if (realRatio >= windowRatio) {
if (realWidth > windowW) {
imgWidth = windowH * outsideScale;
imgHeight = (imgWidth / realWidth) * realHeight;
} else {
if (realWidth * belowScale < windowW) {
imgWidth = realWidth * (belowScale - 0.2);
imgHeight = (imgWidth / realWidth) * realHeight;
} else {
imgWidth = realWidth;
imgHeight = realHeight;
}
}
} else {
if (realHeight > windowH) {
imgHeight = windowH * outsideScale;
imgWidth = (imgHeight / realHeight) * realWidth;
} else {
if (realHeight * belowScale < windowW) {
imgHeight = realHeight * (belowScale - 0.2);
imgWidth = (imgHeight / realHeight) * realWidth;
} else {
imgWidth = realWidth;
imgHeight = realHeight;
}
}
}
//设置放大图片的尺寸、偏移量并展示
image.style.width = imgWidth + "px";
image.style.height = imgHeight + "px";
x = (windowW - imgWidth) * 0.5;
y = (windowH - imgHeight) * 0.5;
image.style.transform = `translate3d(${x}px, ${y}px, 0)`;
outerdiv.style.display = "block";
// 点击蒙版及外面区域放大图片关闭
outerdiv.onclick = () => {
outerdiv.style.display = "none";
initScale = 1;
window.removeEventListener("wheel", handleStopWheel);
};
// 阻止事件冒泡
image.onclick = (e) => {
e.stopPropagation();
};
}
function handleStopWheel(e) {
let itemSizeChange = 1.1; //每一次滚动放大的倍数
if (e.target.id == "bigimg") {
// 说明:e.dataY如果大于0则表示鼠标向下滚动,反之则向上滚动,这里设计为向上滚动为缩小,向下滚动为放大
if (e.deltaY < 0) {
itemSizeChange = 1 / 1.1;
}
let _initScale = initScale * itemSizeChange;
// 说明:在超过或低于临界值时,虽然让initScale等于maxZoom或minreduce,但是在后续的判断中放大图片的最终倍数并没有达到maxZoom或minreduce,而是跳过。
if (_initScale > maxZoom) {
initScale = maxZoom;
} else if (_initScale < minreduce) {
initScale = minreduce;
} else {
initScale = _initScale;
}
const origin = {
x: (itemSizeChange - 1) * imgWidth * 0.5,
y: (itemSizeChange - 1) * imgHeight * 0.5,
};
// 计算偏移量
if (_initScale < maxZoom && _initScale > minreduce) {
x -= (itemSizeChange - 1) * (e.clientX - x) - origin.x;
y -= (itemSizeChange - 1) * (e.clientY - y) - origin.y;
e.target.style.transform = `translate3d(${x}px, ${y}px, 0) scale(${initScale})`;
}
}
// 阻止默认事件
e.preventDefault();
}
function imgDrag() {
// 绑定 鼠标按下事件
image.addEventListener("pointerdown", pointerdown);
// 绑定 鼠标移动事件
image.addEventListener("pointermove", pointermove);
image.addEventListener("pointerup", function (e) {
if (isPointerdown) {
isPointerdown = false;
}
});
image.addEventListener("pointercancel", function (e) {
if (isPointerdown) {
isPointerdown = false;
}
});
}
function pointerdown(e) {
isPointerdown = true;
console.log(e.pointerId)
// 说明:Element.setPointerCapture()将特定元素指定为未来指针事件的捕获目标。指针的后续事件将以捕获元素为目标,直到捕获被释放。可以理解为:在窗口不是全屏情况下,我在拖动放大图片时即使鼠标移出可窗口之外,此时事件还是捕获在该放大图片上。
image.setPointerCapture(e.pointerId);
lastPointermove = {
x: e.clientX,
y: e.clientY,
};
}
function pointermove(e) {
if (isPointerdown) {
const current1 = {
x: e.clientX,
y: e.clientY,
};
diff.x = current1.x - lastPointermove.x;
diff.y = current1.y - lastPointermove.y;
lastPointermove = {
x: current1.x,
y: current1.y,
};
x += diff.x;
y += diff.y;
image.style.transform = `translate3d(${x}px, ${y}px, 0) scale(${initScale})`;
}
e.preventDefault();
}
</script>
</body>
</html>
复制

2.2 函数分析

  • imgShow函数:

    • 主要功能:显示放大后的图片,为蒙版添加一个点击隐藏放大图片的事件,给放大图片添加点击阻止冒泡事件;
    • 得到xy的值是放大图片在屏幕中高度宽度留下空白一半的值。
      • 原理:屏幕宽高尺寸减去图片宽高尺寸得到值之后取一半;
      • 可以利用这个值使用transform 属性让图片在屏幕中间。
  • handleStopWheel函数

    • 主要功能:鼠标滚动缩放已经放大的图片,同时得到偏移xy值,实现焦点缩放;
    • e.deltaY大于0则表示鼠标滚轴向下滚动,反之则向上滚动,这里设计为向上滚动为缩小,向下滚动为放大;
    const origin = {
    x: (itemSizeChange - 1) * imgWidth * 0.5,
    y: (itemSizeChange - 1) * imgHeight * 0.5,
    };
    // 计算偏移量
    if (_initScale < maxZoom && _initScale > minreduce) {
    x -= (itemSizeChange - 1) * (e.clientX - x) - origin.x;
    y -= (itemSizeChange - 1) * (e.clientY - y) - origin.y;
    e.target.style.transform = `translate3d(${x}px, ${y}px, 0) scale(${initScale})`;
    }
    复制
    • (itemSizeChange - 1) 有两个值:0.1-0.09090990...也就是放大一次是10%,缩小一次大约9%;
    • origin 对象得到值,为一次缩放时,放大图片在原有的基础之上增加或者减少的值的一半
    • (e.clientX - x)
      • x为第一次缩放时imgShow函数中得到的值;e.clientX为鼠标所在位置的x轴坐标值
      • 得到的结果为:放大图片缩放之前鼠标距离放大图片左侧边缘的间距;
    • 分析稍微有点乱,下面是一个举例:
      • 设屏幕大小为200x200,放大图片width:100px,height:100px,鼠标位于则120x120,做一次放大操作
      • 放大图片打开:x = (200-100)*0.5, y = 50
      • origin = {x: 0.1 * 100 * 0.5, y: 5}
      • (itemSizeChange - 1) * (e.clientX - x) - origin.x = 0.1 * ( 120 - 50 ) - 5 = 2
      • (itemSizeChange - 1) * (e.clientY - y) - origin.y = 2
      • 计算需要的偏移量为x = 50 - 2y = 48 ,从原来的偏移(50,50),变为了(48,48)放大10%
  • imgDrag函数:

    • 主要功能:实现拖拽功能,在鼠标按下时(pointerdown函数)指定为未来指针事件的捕获目标,并且记录最初的鼠标坐标;鼠标移动时(pointermove函数)计算鼠标移动后坐标与上一次鼠标坐标的差值,得到放大图片最终需要偏移的值。

3.效果参考

在这里插入图片描述

4. 参考链接

  • https://juejin.cn/post/7009892447211749406

5. 写在最后

如果有所帮助,希望能够点赞、收藏支持,谢谢喽。

转载请注明出处或者链接地址:https://www.qianduange.cn//article/1097.html
标签
评论
还可以输入200
共0条数据,当前/页
发布的文章

Ajax用法总结

2024-02-14 09:02:07

JQuery之jsTree树形插件

2024-02-14 09:02:01

Why React Doesn‘t Need jQuery?

2024-02-14 09:02:00

jQuery模板字符串

2024-02-14 09:02:58

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!