当前位置: 首页 > 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...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

ESP32读取DHT11温湿度数据

芯片&#xff1a;ESP32 环境&#xff1a;Arduino 一、安装DHT11传感器库 红框的库&#xff0c;别安装错了 二、代码 注意&#xff0c;DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...