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

原生js实现图片预览控件,支持丝滑拖拽,滚轮放缩,放缩聚焦

手撸源代码如下:注释应该很详细了,拿去直用

可以放到在线编辑器测试,记得修改图片路径

菜鸟教程在线编辑器

<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>#img_box {position: relative;width: 800px;height: 800px;border: 1px solid #000000;overflow: hidden;cursor: grab;}#img_c {width: 100%;height: 100%;position: absolute;object-fit: contain;user-select: none;-webkit-user-drag: none;user-select: none;-moz-user-select: none;-webkit-user-select: none;-ms-user-select: none;/* transition: all 0.1s ease-in-out; */}</style>
</head><body><div id="img_box"><img id="img_c" title="没有" src="./1719194464803.jpg"></div><script>initImageScaleElement();function initImageScaleElement() {//定义参数const max = 20;//放缩原图倍数const scale = 0.05;//滚轮一下缩放的变化比例 越大放缩越快//获取对象const box = document.getElementById("img_box");const img = document.getElementById("img_c");/*** 图片已加载完毕后,对图片居中* 图片一开始其实默认是居中的,只不过是img的object-fit: contain属性进行了居中,并且产生了一些边缘填充空白* 这些填充的空白会影响后续图片拖拽的计算,因此需要将img修改成图片展示的真实大小,但对用户视觉不发生改变。*/img.onload = function () {const imgRatio = img.naturalWidth / img.naturalHeight; //图片横纵比const boxRatio = box.clientWidth / box.clientHeight;   //容器横纵比/*** 因为拿到的图片真实大小,不是显示大小,需要手动放缩,适配到容器中* 当图片横纵比大于容器横纵比,图片保持比例的情况下填充容器,此时只能对图片的横向放缩填充全部容器 * 当图片横纵比小于容器横纵比,图片保持比例的情况下填充容器,此时只能对图片的纵向放缩填充全部容器 * 这个规律可以自己画图试验一下*/if (imgRatio > boxRatio) { const scale = box.clientWidth / img.naturalWidth;img.style.width = box.clientWidth; //长度填充img.style.height = img.naturalHeight * scale; //高度自适应img.style.top = Math.ceil((box.clientHeight - img.clientHeight) / 2) + "px" ;//位置居中} else {const scale = box.clientHeight / img.naturalHeight;img.style.height = box.clientHeight;//高度填充img.style.width = img.naturalWidth * scale;//长度自适应img.style.left = Math.ceil((box.clientWidth - img.clientWidth) / 2) + "px";//位置居中}};//用于元素拖拽时边界的参数限制,入参:{ 实际值,左区间,右区间 }const getRange = (actual, limita, limitb) => {if (actual < -limita) {return -limita;} else if (actual > limitb) {return limitb;}return actual;}/*** 缩放操作* */box.onwheel = (event) => {event.preventDefault(); //关闭默认事件const center_x = event.clientX;const center_y = event.clientY;const wheelDelta = event.deltaY;const top_d = center_y - img.offsetTop;const left_d = center_x - img.offsetLeft;if (wheelDelta > 0) {//缩小 往后推滚轮  【滚轮值和缩放关系不是固定的,你也可以反过来】let modifyHeight = img.clientHeight * (1 - scale);let modifyWidth = img.clientWidth * (1 - scale);if (modifyHeight * max > img.naturalHeight) { //只在比例范围内,放缩img.style.height = modifyHeight;img.style.width = modifyWidth;img.style.top = center_y - top_d * (1 - scale);img.style.left = center_x - left_d * (1 - scale);} else {console.log("缩小超出" + max * 100 + "%比例无法缩小");}} else {//放大  往前推滚轮let modifyHeight = img.clientHeight * (1 + scale);let modifyWidth = img.clientWidth * (1 + scale);if (modifyHeight < img.naturalHeight * max) { //只在比例范围内,放缩img.style.height = modifyHeight;img.style.width = modifyWidth;img.style.top = center_y - top_d * (1 + scale);img.style.left = center_x - left_d * (1 + scale);} else {console.log("放大超出" + max * 100 + "%比例无法放大");}}}/*** 拖拽操作*///拖拽需要的全局变量const drag = {status: false,lastX: null,lastY: null}box.onmousedown = (event) => {if (event.button === 0) {//鼠标会移出元素,甚至移出到浏览器外部,使用document监听移动就可以不受影响。document.onmousemove = (event) => {if (drag.status) {let mx = event.clientX - drag.lastXlet my = event.clientY - drag.lastYdrag.lastX = event.clientXdrag.lastY = event.clientYlet top = img.offsetTop + mylet left = img.offsetLeft + mx//拖拽超出容器外部无意义,可能找不回,因此图片位置不能任意拖拽至少有一个角或一个边在容器内部,这里减10就是预留出的宽度img.style.left = getRange(left, img.clientWidth - 10, box.clientWidth - 10) + 'px';img.style.top = getRange(top, img.clientHeight - 10, box.clientHeight - 10) + "px";//如果你不想让图片跑出容器,那就调整这里就好了,控制两个相邻边就能控制整个图片,如// img.style.left = getRange(left,0, box.clientWidth - img.clientWidth) + 'px';// img.style.top = getRange(top,0, box.clientHeight - img.clientHeight) + "px";}}//鼠标松开,初始化操作,如果鼠标在元素外部松开,元素的松开监听是获取不到的,因此需要用document监听document.onmouseup = (event) => {if (event.button === 0) {drag.status = falsedocument.onmousemove = nulldocument.onmouseup = null}}drag.status = truedrag.lastX = event.clientXdrag.lastY = event.clientY}}}</script></body></html>

相关文章:

原生js实现图片预览控件,支持丝滑拖拽,滚轮放缩,放缩聚焦

手撸源代码如下&#xff1a;注释应该很详细了&#xff0c;拿去直用 可以放到在线编辑器测试&#xff0c;记得修改图片路径 菜鸟教程在线编辑器 <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" conten…...

C语言入门课程学习笔记9:指针

C语言入门课程学习笔记9 第41课 - 指针&#xff1a;一种特殊的变量实验-指针的使用小结 第42课 - 深入理解指针与地址实验-指针的类型实验实验小结 第43课 - 指针与数组&#xff08;上&#xff09;实验小结 第44课 - 指针与数组&#xff08;下&#xff09;实验实验小结 第45课 …...

借助 Cloudflare D1 和 Drizzle 在 Astro 上实现全栈

使用 Cloudflare D1 和 Drizzle ORM 将后端添加到 Astro 项目的分步指南 文章目录 安装 Astro添加 Cloudflare 适配器部署到 Pages安装 wrangler 并登录创建 D1 数据库创建 wrangler.toml 文件将 .wrangler 添加到 .gitignore更新 astro.config.ts安装 Drizzle 依赖项创建 driz…...

SUSE linux 15的网络管理

1 手工配置网络 wicked提供了一种新的网络配置框架。自SUSE 12起&#xff0c;SUSE使用了新的网络管理工具wicked&#xff0c;这个是区别与其他常见发行版的。常见的发行版目前大多使用的是NetworkManager服务进行网络管理。 1.1 wicked网络配置 传统网络接口管理面临的挑战之…...

海康威视-下载的录像视频浏览器播放问题

目录 1、播放异常比对 2、视频编码检查 2.1、正常视频解析 2.2、海康视频解析 2.3、比对工具 3、转码 3.1、maven依赖 3.2、实现代码 4、验证 在前面的文章&#xff08;海康威视-按时间下载录像文件_海康威视 sdk 下载录像 大小0-CSDN博客&#xff09;中&#xff0c;通…...

养殖自动化管理系统:开启智慧养殖新篇章

在现代农业的快速演进中&#xff0c;养殖业正经历一场前所未有的技术革命。养殖自动化管理系统&#xff0c;作为这场变革的前沿科技&#xff0c;正逐步成为推动行业高效、环保、可持续发展的关键力量。本文将深入探讨自动化养殖系统如何通过精准管理、智能监控、数据驱动决策&a…...

SmartEDA革新来袭:融合Multisim与Proteus精髓,引领电子设计新纪元!

在电子设计领域&#xff0c;每一次技术的革新都如同春风化雨&#xff0c;滋润着设计师们的心田。今天&#xff0c;我们迎来了一个划时代的电子设计自动化&#xff08;EDA&#xff09;工具——SmartEDA&#xff0c;它不仅融合了业界知名的Multisim和Proteus的精华&#xff0c;更…...

【FFmpeg】AVFormatContext结构体

【FFmpeg】AVFormatContext结构体 1.AVFormatContext结构体1.2 const struct AVInputFormat *iformat1.3 const struct AVOutputFormat *oformat 参考&#xff1a; FFMPEG结构体分析&#xff1a;AVFormatContext 示例工程&#xff1a; 【FFmpeg】调用ffmpeg库实现264软编 【FF…...

【SpringSecurity】认证与鉴权框架SpringSecurity——授权

目录 权限系统的必要性常见的权限管理框架SpringSecurity授权基本流程准备脚本限制访问资源所需权限菜单实体类和Mapper封装权限信息封装认证/鉴权失败处理认证失败封装鉴权失败封装配置SpringSecurity 过滤器跨域处理接口添加鉴权hasAuthority/hasAnyAuthorityhasRole/​ hasA…...

深入解析FTP:原理、架构与搭建方式

在当今互联网世界中&#xff0c;文件传输是日常工作和生活中不可或缺的一部分。FTP&#xff08;File Transfer Protocol&#xff0c;文件传输协议&#xff09;作为一种老而弥坚的协议&#xff0c;一直在文件传输领域发挥着重要作用。本文将从技术人的角度&#xff0c;详细分析F…...

Springboot与RestTemplate

RestTemplate是Spring提供的用于访问Rest服务的客户端&#xff0c;RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。 一、使用Get进行访问 1、获取json格式 使用 getForEntity() API 发起 GET 请求&#xff1a; RestTemplate restTemplate…...

端口发布与暴露

端口发布与暴露 目录 发布端口发布到临时端口发布所有端口试一试 使用 Docker CLI使用 Docker Compose 如果你一直在跟随本指南&#xff0c;你应该理解容器为应用程序的每个组件提供了隔离的进程。每个组件 - 如 React 前端、Python API 和 Postgres 数据库 - 都运行在自己的…...

Unity:使用Texture2D动态创建的图像无法正常显示 / 修改图像后未生效

开发中遇到需要动态绘制图像的需求&#xff0c;前后文代码如下所示&#xff1a; Texture2D newImageTexture new Texture2D(width, height); Color32[] newImagePixels new Color32[height * width];for (int y 0; y < height ; y) {for (int x 0; x < width; x){if…...

【LinuxC语言】详解TCP/IP

文章目录 前言TCP与UDP协议的介绍TCP协议流式传输TCP的三次握手连接TCP的四次挥手连接断开总结前言 在我们的日常生活中,无论是浏览网页,还是发送电子邮件,甚至是在线视频聊天,都离不开网络通信。而在网络通信中,TCP和UDP协议起着至关重要的作用。本文将以通俗易懂的语言…...

数字化转型下的企业人力资源信息系统研究

随着数字化转型的加速&#xff0c;企业人力资源管理面临着全新的挑战和机遇。传统的人力资源信息系统&#xff08;HRIS&#xff09;在新时代的要求下必须进行深刻的革新和升级&#xff0c;以更好地支持企业的发展战略和员工的需求。 数据驱动的决策支持 在当今这个信息化迅猛发…...

docker camunda 8.5 部署步骤

Camunda Platform 8 环境准备 Docker 版本要求 Docker 20.10.16 is required; docker compose version 1.27.0.;github 开源地址:https://github.com/camunda/camunda-platformcamunda7 文档地址:https://docs.camunda.org/manual/7.21/user-guide/process-engine/社区地址: …...

学懂C#编程:常用高级技术——委托(Delegate)应用场景——委托与Lambda表达式的结合使用详解

在C#中&#xff0c;委托与Lambda表达式的结合使用是现代编程实践中的一个重要且强大的特性&#xff0c;它极大地提高了代码的简洁性和可读性。下面将详细讲解这两个概念如何协同工作&#xff0c;以及如何在实际编程中有效利用它们。 委托基础 委托是C#中的一种引用类型&#x…...

05-java基础——循环习题

循环的选择&#xff1a;知道循环的次数或者知道循环的范围就使用for循环&#xff0c;其次再使用while循环 猜数字 程序自动生成一个1-100之间的随机数&#xff0c;在代码中使用键盘录入去猜出这个数字是多少&#xff1f; 要求&#xff1a;使用循环猜&#xff0c;一直猜中为止…...

网络安全等级保护测评

网络安全等级保护 《GB17859 计算机信息系统安全保护等级划分准则》 规定计算机信息系统安全保护等级共分五级 《中华人民共和国网络安全法》 “国家实行网络安全等级保护制度。 等级测评 测评机构依据国家网络安全等级保护制度规定&#xff0c;按照有关 管理规范和…...

真有被这套零售数据分析方案惊艳到

在数字化时代&#xff0c;零售行业的竞争愈发激烈&#xff0c;如何精准把握市场动态、优化业务流程、提升市场竞争力成为了每一家零售企业都面临的挑战。奥威BI零售数据分析方案&#xff0c;一款具备全面、高效、智能的数据分析能力的BI方案出现地恰到好处。 奥威BI零售数据分…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用

文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么&#xff1f;1.1.2 感知机的工作原理 1.2 感知机的简单应用&#xff1a;基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测

uniapp 中配置 配置manifest 文档&#xff1a;manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号&#xff1a;4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...