当前位置: 首页 > news >正文

实现图片拖拽和缩小放大功能。

1. 前言

        不知道各位前端小伙伴蓝湖使用的多不多,反正我是经常在用,ui将原型图设计好后上传至蓝湖,前端开发人员就可以开始静态页面的的编写了。对于页面细节看的不是很清楚可以使用滚轮缩放后再拖拽查看,还是很方便的。于是就花了点时间研究了一下。今天分享给大家。

2. 实现

HTML

 <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>

js

拖拽查看图片逻辑

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();}

滚轮缩放逻辑

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();}

js全部代码

<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>

相关文章:

实现图片拖拽和缩小放大功能。

1. 前言 不知道各位前端小伙伴蓝湖使用的多不多&#xff0c;反正我是经常在用&#xff0c;ui将原型图设计好后上传至蓝湖&#xff0c;前端开发人员就可以开始静态页面的的编写了。对于页面细节看的不是很清楚可以使用滚轮缩放后再拖拽查看&#xff0c;还是很方便的。于是就花了…...

昇思25天学习打卡营第18天|munger85

DCGAN生成漫画头像 首先肯定是下载训练数据&#xff0c;而这些训练数据就是一些卡通头像。后来我们会看到这个具体的头像 就像其他的数据集目录一样&#xff0c;它是由一些目录和这个目录下面的文件组成的数据集。 有相当多的图片。所以可以训练出来比较好的效果。 图片的处理…...

nginx配置文件说明

Nginx的配置文件说明 Nginx配置文件的主要配置块可以分为三个部分&#xff1a;全局配置块&#xff08;events和http块&#xff09;&#xff0c;events块和http块。这三个部分共同定义了Nginx服务器的整体行为和处理HTTP请求的方式。 全局配置块&#xff1a; 包含了影响Nginx服…...

用不同的url头利用Python访问一个网站,把返回的东西保存为txt文件

这个需要调用requests模块&#xff08;相当于c的头文件&#xff09; import requests 还需要一个User-Agent头&#xff08;这个意思就是告诉python用的什么系统和浏览器&#xff09; Google Chrome&#xff08;Windows&#xff09;: Mozilla/5.0 (Windows NT 10.0; Win64; x64…...

一文掌握Prometheus实现页面登录认证并集成grafana

一、接入方式 以保护Web站点的访问控制&#xff0c;如HTTP 服务器配置中实现安全的加密通信和身份验证&#xff0c;保护 Web 应用程序和用户数据的安全性。 1.1 加密密码 通过httpd-tools工具包来进行Web站点加密 yum install -y httpd-tools方式一&#xff1a;通过htpasswd生…...

欢迎来到 Mint Expedition:Web3 和 NFT 的新时代开始

7 月 15 日&#xff0c;Mint Expedition 正式开启&#xff0c;作为 Mint 生态系统的旗舰项目&#xff0c;将彻底变革 Web3 和 NFT 去中心化应用&#xff01; Mint Expedition 是 Mint 的最新航程&#xff0c;延续了 Mint Forest 的成功。Mint Forest 吸引了超过 41.4 万独立用…...

针对环境构图的全局一致性扫描点云数据对齐(Graph SLAM)

本算法是一个经典的&#xff0c;针对SLAM&#xff08;simultaneous localization and mapping 即时定位与地图构建&#xff09;问题而提出的算法。该算法的提出者是Feng Lu和Evangelos Milios&#xff0c;他们在本算法中开创了通过全局优化方程组以减少约束引入的误差来进一步优…...

Matlab学习笔记01 - 基本数据类型

Matlab学习笔记01 - 基本数据类型 1、数据类型转换2、矩阵2.1 访问单个矩阵元素2.2 访问多个矩阵元素2.3 矩阵转置 3、字符与字符串4、数值与字符串5、元胞数组 1、数据类型转换 十进制转十六进制字符串‘FF’ >> hex2dec(3ff)ans 1023十进制转十六进制字符串 >>…...

基于重要抽样的主动学习不平衡分类方法ALIS

这篇论文讨论了数据分布不平衡对分类器性能造成的影响,并提出了一种新的有效解决方案 - 主动学习框架ALIS。 1、数据分布不平衡会影响分类器的学习性能。现有的方法主要集中在过采样少数类或欠采样多数类,但往往只采用单一的采样技术,无法有效解决严重的类别不平衡问题。 2、论…...

Python爬虫(基本流程)

1. 确定目标和范围 明确需求&#xff1a;确定你需要从哪些网站抓取哪些数据。合法性&#xff1a;检查目标网站的robots.txt文件&#xff0c;了解哪些内容可以被抓取。数据范围&#xff1a;确定爬取数据的起始和结束点&#xff0c;比如时间范围、页面数量等。 2. 选择合适的工…...

primeflex教学笔记20240720, FastAPI+Vue3+PrimeVue前后端分离开发

练习 先实现基本的页面结构&#xff1a; 代码如下&#xff1a; <template><div class"flex p-3 bg-gray-100 gap-3"><div class"w-20rem h-12rem bg-indigo-200 flex justify-content-center align-items-center text-white text-5xl">…...

移动设备安全革命:应对威胁与解决方案

移动设备已成为我们日常工作和家庭生活中不可或缺的工具&#xff0c;然而&#xff0c;对于它们安全性的关注和投资仍然远远不够。本文深入分析了移动设备安全的发展轨迹、目前面临的威胁态势&#xff0c;以及业界对于这些安全漏洞响应迟缓的深层原因。文中还探讨了人们在心理层…...

【C语言】 链表实现学生管理系统(堆区开辟空间)

总体思路都能写出来&#xff0c;问题是感觉稍微比之前的麻烦一些&#xff0c;在刚开始创建结构体的时候&#xff0c;并没有去按照链表的思路去写&#xff0c;导致写成了顺序表&#xff0c;后面就一直纠结空间怎么开辟。 链表是由一个头节点和其它申请出来的小节点连起来的&…...

STM32实战篇:按键(外部输入信号)触发中断

功能要求 将两个按键分别与引脚PA0、PA1相连接&#xff0c;通过按键按下&#xff0c;能够触发中断响应程序&#xff08;不需明确功能&#xff09;。 代码流程如下&#xff1a; 实现代码 #include "stm32f10x.h" // Device headerint main() {//开…...

Android SurfaceView 组件介绍,挖洞原理详解

文章目录 组件介绍基本概念关键特性使用场景 SurfaceHolder介绍主要功能使用示例 SurfaceView 挖洞原理工作机制 使用SurfaceView展示图片示例创建一个自定义的 SurfaceView类在 Activity 中使用 ImageSurfaceView注意事项效果展示 组件介绍 在 Android 开发中&#xff0c;Sur…...

day2加餐 Go 接口型函数的使用场景

文章目录 问题价值使用场景其他语言类似特性 问题 在 动手写分布式缓存 - GeeCache day2 单机并发缓存 这篇文章中&#xff0c;有一个接口型函数的实现&#xff1a; // A Getter loads data for a key. type Getter interface {Get(key string) ([]byte, error) }// A Getter…...

摄像头 RN6752v1 视频采集卡

摄像头 AHD倒车摄像头比较好&#xff0c;AHD英文全名Analog High Definition&#xff0c;即模拟高清&#xff0c;拥有比较好的分辨率与画面质感。 RN6752v1 GQW AKKY2 usb 采集卡 FHD&#xff08;1080p&#xff09;、HD&#xff08;720p&#xff09;和D1&#xff08;480i&am…...

记录vivado自带IP iBert眼图近端回环

记录利用vivado自带IP核工具测试信号质量 ibert是测试眼图的工具&#xff0c;在使用的时候并不用改太多的内容&#xff0c;只需要注意参考时钟及所需要的引脚即可。由于条件的限制&#xff0c;并没有使用光纤和电缆进行连接进行外部回环&#xff0c;仅使用内部回环做测试&…...

js | Core

http://dmitrysoshnikov.com/ecmascript/javascript-the-core/ Object 是什么&#xff1f; 属性[[prototype]]对象。 例如&#xff0c;下面的&#xff0c;son是对象&#xff0c;foo不是对象。打印出来的son&#xff0c;能看到有一个prototype 对象。 prototype vs _proto_ v…...

Log4J reminder

Java JNDI and Log injection https://docs.oracle.com/javase/jndi/tutorial/ See also https://telegra.ph/Log4J-Vulnerability-Explained-07-21...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

在 Spring Boot 中使用 JSP

jsp&#xff1f; 好多年没用了。重新整一下 还费了点时间&#xff0c;记录一下。 项目结构&#xff1a; pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...

Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合

作者&#xff1a;来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布&#xff0c;Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明&#xff0c;Elastic 作为 …...

VisualXML全新升级 | 新增数据库编辑功能

VisualXML是一个功能强大的网络总线设计工具&#xff0c;专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑&#xff08;如DBC、LDF、ARXML、HEX等&#xff09;&#xff0c;并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...

【版本控制】GitHub Desktop 入门教程与开源协作全流程解析

目录 0 引言1 GitHub Desktop 入门教程1.1 安装与基础配置1.2 核心功能使用指南仓库管理日常开发流程分支管理 2 GitHub 开源协作流程详解2.1 Fork & Pull Request 模型2.2 完整协作流程步骤步骤 1: Fork&#xff08;创建个人副本&#xff09;步骤 2: Clone&#xff08;克隆…...

Easy Excel

Easy Excel 一、依赖引入二、基本使用1. 定义实体类&#xff08;导入/导出共用&#xff09;2. 写 Excel3. 读 Excel 三、常用注解说明&#xff08;完整列表&#xff09;四、进阶&#xff1a;自定义转换器&#xff08;Converter&#xff09; 其它自定义转换器没生效 Easy Excel在…...