Web简易图片浏览器

news/2024/10/17 10:32:28/

实现功能:旋转、拖拽、鼠标滚轮放大缩小

样式

        .img-viewer {overflow: hidden;height: 0;padding-bottom: 75%;;}.iv-btn-area {display: flex;flex-direction: row;justify-content: center;}.iv-btn-area button {width: 3rem;height: 3rem;font-size: 1.2rem;margin: 0.5rem;}.iv-image-area {display: flex;flex-direction: row;justify-content: center;align-items: center;overflow: hidden;}

Javascript

function ImageView(selector, setting) {const scale_rate = 0.2 //滚动鼠标的缩放速率/*** 绘制图片浏览器*/const image_view = document.getElementById(selector);const iv_btn_area = document.createElement('div')const iv_image_area = document.createElement('div')iv_btn_area.className = 'iv-btn-area'iv_image_area.className = 'iv-image-area'const iv_amplify = document.createElement('button')const iv_shrink = document.createElement('button')const iv_turn_clockwise = document.createElement('button')const iv_turn_counterclockwise = document.createElement('button')iv_amplify.className = 'iv-amplify'iv_shrink.className = 'iv-shrink'iv_turn_clockwise.className = 'iv-turn-clockwise'iv_turn_counterclockwise.className = 'iv-turn-counterclockwise'iv_amplify.innerText = '+'iv_shrink.innerText = '-'iv_turn_clockwise.innerText = '↻'iv_turn_counterclockwise.innerText = '↺'iv_btn_area.appendChild(iv_amplify)iv_btn_area.appendChild(iv_shrink)iv_btn_area.appendChild(iv_turn_clockwise)iv_btn_area.appendChild(iv_turn_counterclockwise)image_view.appendChild(iv_btn_area)image_view.appendChild(iv_image_area)/*** 绑定按键事件*/iv_turn_counterclockwise.onclick = () => {image_pool.getCurrentImage().rotate(-90)}iv_turn_clockwise.onclick = () => {image_pool.getCurrentImage().rotate(90)}iv_amplify.onclick = () => {image_pool.getCurrentImage().scale(0.2)}iv_shrink.onclick = () => {image_pool.getCurrentImage().scale(-0.2)}/*** 滚动放大缩小*/iv_image_area.addEventListener('mousewheel', (evt) => {evt.preventDefault()if (evt.deltaY < 0) {image_pool.getCurrentImage().scale(scale_rate)} else {image_pool.getCurrentImage().scale(-scale_rate)image_pool.getCurrentImage().reset(5)}})/*** 创建图片缓存池单例*/const image_pool = (function ImagePool() {/*** 根据url加载图片* @param url* @returns {Promise<unknown>}*/function loadImage(url) {return new Promise((resolve, reject) => {let img = new Image()img.src = urlimg.style.cursor = "pointer"img.onload = () => {resolve(img)}});}/*** 用于存放网络图片,同时提供图片变形工具* @param url* @returns {Promise<*>}* @constructor*/async function ImageContainer(url) {/*** 根据图片初始化*/let image = await loadImage(url).then((e) => {return e;})let angle = 0let scale = 1let original_width = image.widthlet original_height = image.heightlet wh_proportion = original_width / original_height/*** 图片变形器单例,用于生成css transform*/let transformer = (function Transformer() {let rotate = 0;let scale = 1;let currentX = 0;let currentY = 0;let offsetX = 0let offsetY = 0return {getCurrentX: () => {return currentX},getCurrentY: () => {return currentY},setRotate(angle) {rotate = anglereturn this},setScale(size) {scale = sizereturn this},/*** 临时位移变形方法,用于拖拽图片时显示位置* @param offset_1* @param offset_2* @returns {transformer}*/trySetTranslateOffset(offset_1, offset_2) {offset_1 /= scaleoffset_2 /= scaleif (angle === 0) {offsetX = offset_1offsetY = offset_2} else if (angle === 90) {offsetX = offset_2offsetY = -offset_1} else if (angle === 180) {offsetX = -offset_1offsetY = -offset_2} else {offsetX = -offset_2offsetY = offset_1}return this},/*** 更具偏移量所相对位移变形* @param offset_1* @param offset_2* @returns {transformer}*/setTranslateOffset(offset_1, offset_2) {offset_1 /= scaleoffset_2 /= scaleoffsetX = 0offsetY = 0if (angle === 0) {currentX += offset_1currentY += offset_2} else if (angle === 90) {currentX += offset_2currentY -= offset_1} else if (angle === 180) {currentX -= offset_1currentY -= offset_2} else {currentX -= offset_2currentY += offset_1}return this},/*** 根据与原点的偏移值进行位移变形* @param offset_1* @param offset_2* @returns {transformer}*/setTranslate(offset_1, offset_2) {offsetX = 0offsetY = 0if (angle === 0) {currentX = offset_1currentY = offset_2} else if (angle === 90) {currentX = offset_2currentY = offset_1} else if (angle === 180) {currentX = offset_1currentY = offset_2} else {currentX = offset_2currentY = offset_1}return this},/*** 生成css* @returns {string}*/toString() {return "rotate(" + angle + "deg) " + "scale(" + scale + "," + scale + ") " + "translate(" + (currentX + offsetX) + "px," + (currentY + offsetY) + "px)"},/*** 初始化变形器* @returns {transformer}*/init() {rotate = 0;scale = 1;currentX = 0;currentY = 0;offsetX = 0offsetY = 0return this;}}})()/*** 初始化图片容器*/function init() {angle = 0scale = 1wh_proportion = original_width / original_heightimage.style.transform = transformer.init()}/*** 按照原始图像长宽比例,更具长计算宽* @param height* @returns {number}*/function computeWidthOfProportion(height) {if (angle / 90 % 2 === 0) {return height * wh_proportion} else {return height / wh_proportion}}/*** 按照原始图像长宽比例,更具宽计算长* @param width* @returns {number}*/function computeHeightOfProportion(width) {if (angle / 90 % 2 === 0) {return width / wh_proportion} else {return width * wh_proportion;}}/*** 设置变形(旋转后)后图片的宽度* @param width*/function setWidth(width) {if (angle / 90 % 2 === 0) {image.style.width = width + "px"} else {image.style.height = width + "px"}}/*** 获取变形(旋转)后图片的宽度* @returns {number}*/function getWidth() {if (angle / 90 % 2 === 0) {return parseInt(image.style.width)} else {return parseInt(image.style.height)}}/*** 设置变形(旋转后)后图片的高度* @param height*/function setHeight(height) {if (angle / 90 % 2 === 0) {image.style.height = height + "px"} else {image.style.width = height + "px"}}/*** 获取变形(旋转)后图片的高度* @returns {number}*/function getHeight() {if (angle / 90 % 2 === 0) {return parseInt(image.style.height)} else {return parseInt(image.style.width)}}/*** 调整变形后图片的长度和宽度适配容器尺寸*/function adaptParent() {if (getWidth() > getHeight()) {setWidth(iv_image_area.offsetWidth)setHeight(computeHeightOfProportion(getWidth()))} else {setHeight(iv_image_area.offsetHeight)setWidth(computeWidthOfProportion(getHeight()))}}/*** 更具缩放倍率缩放图片* @param magnification*/function scaleImage(magnification) {scale = scale + magnification < 1 ? 1 : scale + magnificationimage.style.transform = transformer.setScale(scale)}/*** 拖拽实现*/let ScreenX = 0let ScreenY = 0image.addEventListener("dragstart", (evt) => {ScreenX = evt.screenXScreenY = evt.screenY})image.addEventListener("drag", (evt) => {image.style.transform = transformer.trySetTranslateOffset(evt.screenX - ScreenX, evt.screenY - ScreenY)})image.addEventListener("dragend", (evt) => {image.style.transform = transformer.setTranslateOffset(evt.screenX - ScreenX, evt.screenY - ScreenY)})return {rotate(degree) {angle = (degree + angle + 360) % 360image.style.transform = transformer.setRotate(angle)adaptParent()},scale: scaleImage, getImage() {init()adaptParent()return image}, reset(speed) {if (scale === 1 && (transformer.getCurrentX() !== 0 || transformer.getCurrentY() !== 0)) {image.style.transform = transformer.setTranslate(Math.trunc(transformer.getCurrentX() / speed), Math.trunc(transformer.getCurrentY() / speed))}}}}let size = 0;let index = 0;let pool = []let url_dict = {}return {/*** 向图片浏览器添加图片* @param url* @returns {Promise<number>}*/async addImage(url) {pool.push(await ImageContainer(url))url_dict[url] = sizesize++return size - 1},/*** 设置当前图片,若图片不在缓存池内则加载图片* @param url* @returns {Promise<void>}*/async setCurrentImage(url) {if (url_dict[url] !== undefined) {index = url_dict[url]} else {index = await this.addImage(url)}},/*** 获取当前图片容器* @returns {*}*/getCurrentImage() {return pool[index]}}})()/*** 容器变换时重绘窗口* @type {ResizeObserver}*/let observer = new ResizeObserver((evt) => {iv_image_area.innerHTML = ""iv_image_area.style.height = image_view.offsetHeight - iv_btn_area.offsetHeight + "px"let img = image_pool.getCurrentImage()?.getImage()if (img) {iv_image_area.appendChild(img)}});observer.observe(image_view);return {async setImage(url) {await image_pool.setCurrentImage(url)}}}

用法

<div id="image_view" class="img-viewer"></div>
<script>let iv = new ImageView("image_view")iv..setImage("https://img.io/example.jpg")
</script>

http://www.ppmy.cn/news/150222.html

相关文章

选择浏览图片

我们先看到前端 放置图片的地方写上x:Name 名作为后端需要时可以找到该位置 浏览路径的文本一样 还需要浏览按钮&#xff0c;清空要不要都行 那么接下来的就是后端的操作 对了还有下面的这个初始化&#xff0c;写在在外头 List<byte[]> lstBytes new List<byte[]&…

使用浏览器插件,下载网页中的图片

1.360浏览器。 在扩展中搜索图片下载&#xff0c;点击安装此插件 提取网页图片时&#xff0c;只需点击浏览器右上角的图标 2.谷歌浏览器 下载 Image downloader Chrome插件 http://www.cnplugins.com/photos/imageye-image-downloader/ 安装方法 https://jingyan.baidu.c…

(HoneyView)轻便好用的免费图片浏览器

需求 windows 10 自带的图片浏览器加载图片总是很慢&#xff0c;这在整理照片的时候就显得特别不方便。因此&#xff0c;想找一个免费的、轻巧的、快速的图片浏览器&#xff0c;来替代掉 windows 10自带的图片浏览器。 解决方案&#xff1a;HoneyView 下载地址 Bandisoft - H…

Chrome浏览器保存整个网页为图片的方法

Chrome浏览器保存整个网页为图片的方法 方法举例说明 方法 打开需要保存为图片的网页 然后按F12&#xff0c;接着按CtrlShiftP 在红框内输入full 举例说明 以这个网址的网站为里&#xff0c;vitesse产品的各种型号&#xff1a; https://www.microsemi.com/product-directory…

android图片浏览器(一)

主要实现的功能就是浏览图片。 用到的控件&#xff1a;ImageSwitcher和Gallery。 这种简单的图片浏览器google一下有很多&#xff0c;我也是参考别人上写的。在搜索的过程中&#xff0c;我发现了一个比较有意思的事情&#xff0c;就是很多博客里面的代码基本上都是相同的&…

基于RecyclerView的图片浏览器

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、作业要求二、具体实现1.布局代码2.程序代码 总结 前言 基于RecyclerView的图片浏览器 一、作业要求 使用RecyclerView实现一个图片列表&#xff0c;如图…

Android图片浏览器

当手机开机、插拔USB连接时&#xff0c;Android系统会启动MediaScanner&#xff0c;扫描SD卡和内存里面的文件&#xff0c;扫描的结果保存在data/data/com.android.providers.media/databases/external.db下。通过DDMS可以找到&#xff0c;数据库中包含了图片、视频、音乐等文件…

网页图片浏览

基本功能&#xff1a;输入图片的url然后点击按钮加载出来图片 activity_main.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android" xmlns:tools"http://s…