记录-JS简单实现购物车图片局部放大预览效果
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
一、实现效果
二、代码实现
代码不多,先看一下 HTML 里面结构很简单,初始化 MagnifyingGlass 对象来关联一个 IMG 标签来实现放大。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <! DOCTYPE html> < html > < head > < meta charset="utf-8"> </ head > < style type="text/css"> *{ padding: 0; margin: 0; } .clothes { width: auto; height: auto; } </ style > < body > < div > < img id="clothes" class="clothes" src="./clothes.jpg" alt=""> </ div > </ body > < script src="./magnifyingGlass.js"></ script > < script > //针对某个标签进行图片放大处理 let magnifyingGlass = new MagnifyingGlass(document.getElementById('clothes')) </ script > </ html > |
再看一下 MagnifyingGlass
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | class MagnifyingGlass { // 需要放大的图片 imgEl // 放大预览视图 magnifyingGlassView // 区域小图 smallCanvas // 保存原图的像素值 originalPiexls = [] // 截流定时器 interceptionTimer = null constructor(el){ if(el.tagName == 'IMG'){ this.imgEl = el this.listenerImgLoadSucceeded() } } // 监听图片加载完成 async listenerImgLoadSucceeded(){ if(!this.imgEl.complete){ await new Promise((resolve)=>{ this.imgEl.onload = resolve }) } // 添加鼠标事件 this.addMouseEvent() // 创建一个放大预览视图 this.createMagnifyingGlassView() } // 创建一个放大预览视图 createMagnifyingGlassView(){ if(this.magnifyingGlassView){ this.magnifyingGlassView.remove() } this.magnifyingGlassView = document.createElement('canvas') this.magnifyingGlassView.style.cssText = 'position: fixed;background:aliceblue;left:0;top:0;pointer-events:none;display:none' this.magnifyingGlassView.setAttribute('width',`${200}px`) this.magnifyingGlassView.setAttribute('height',`${200}px`) let body = document.getElementsByTagName('body')[0] body.appendChild(this.magnifyingGlassView) } // 添加鼠标事件 addMouseEvent(){ // 添加鼠标滑过事件 this.addMouseMoveToImageEl() // 鼠标滑出事件 this.addMouseLeaveToImageEl() } // 添加鼠标滑过事件 addMouseMoveToImageEl(){ this.imgEl.onmousemove = (event)=>{ let x = event.clientX + this.getElementPosition(this.imgEl).left + 20 let y = event.clientY + this.getElementPosition(this.imgEl).top + 20 let position = { x, y } // 截流 this.interceptionFunc(()=>{ // 修改放大视图位置 this.changeMagnifyingGlassViewPosition(position) // 获取需要放大的像素 this.getNeedMasgnifyingGlassPiexl({clientX: (event.clientX - this.getElementPosition(this.imgEl).left),clientY: (event.clientY - this.getElementPosition(this.imgEl).top)}) }) } } //截流 interceptionFunc(cb){ if(this.interceptionTimer){ return } this.interceptionTimer = setTimeout(() => { cb() this.interceptionTimer = null }, 20); } // 鼠标滑出事件 addMouseLeaveToImageEl(){ this.imgEl.onmouseleave = ()=>{ // 移除放大框 this.magnifyingGlassView.style.display = 'none' } } // 修改放大视图位置 changeMagnifyingGlassViewPosition(position){ this.magnifyingGlassView.style.left = position.x + 'px' this.magnifyingGlassView.style.top = position.y + 'px' this.magnifyingGlassView.style.display = 'block' } // 获取元素在屏幕的位置 getElementPosition(element){ var top = element.offsetTop var left = element.offsetLeft var currentParent = element.offsetParent; while (currentParent !== null) { top += currentParent.offsetTop left += currentParent.offsetLeft currentParent = currentParent.offsetParent } return {top,left} } // 保存原像素(操作像素点时候用) async getOriginalPiexls(){ if(this.originalPiexls.length == 0){ var image = new Image(); image.src = this.imgEl.src; // 等待IMG标签加载完成后保存像素值 await new Promise((resolve)=>{ image.onload = resolve }) let width = image.width let height = image.height let canvas = document.createElement('canvas') canvas.setAttribute('width',`${width}px`) canvas.setAttribute('height',`${height}px`) var ctx = canvas.getContext("2d") ctx.fillStyle = ctx.createPattern(image, 'no-repeat'); ctx.fillRect(0, 0, width, height); try { //保存像素 this.originalPiexls = ctx.getImageData(0,0,width,height) } catch (error) { console.log(error) } } } // 获取需要放大的像素 async getNeedMasgnifyingGlassPiexl(event){ //获取原始像素 this.getOriginalPiexls() //如果像素为空,不进行操作 if(this.originalPiexls.length == 0){ return } //获取待放大IMG的宽度,用来计算像素 let imageWidth = this.imgEl.offsetWidth //获取当前鼠标点的范围 let diffusionLength = 100 //鼠标触点 let mouseX = event.clientX let mouseY = event.clientY //规定区域的上下、左右宽度 let sepX = parseInt(diffusionLength) let sepY = parseInt(diffusionLength) // 需要开始的点 let startPoint = {x:(mouseX - parseInt(sepX / 2.0)),y:(mouseY - parseInt(sepY / 2.0))} // 需要结束的点 let endPoint = {x:(mouseX + parseInt(sepX / 2.0)),y:(mouseY + parseInt(sepY / 2.0))} // 最终要展示的像素集合(乘以4是单一像素值宽度) let finallyOriginalPiexls = new Uint8ClampedArray(sepX * sepY * 4) let currentIndex = 0 //操作像素 for(let i = startPoint.y;i < endPoint.y ;i++){ for(let j = startPoint.x; j < endPoint.x;j++){ for(let k = 0;k < 4;k++){ let index = (i * imageWidth + j) * 4 + k if(index > 0 && index < this.originalPiexls.data.length ){ // 超过宽度部分需要进行其他色值填充 if(j < imageWidth){ finallyOriginalPiexls[currentIndex] = this.originalPiexls.data[index] } else { finallyOriginalPiexls[currentIndex] = 199 } } else { finallyOriginalPiexls[currentIndex] = 199 } currentIndex += 1 } } } //先绘制一个100*100单位长的小图 if(!this.smallCanvas){ this.smallCanvas = document.createElement('canvas') this.smallCanvas.setAttribute('width',`${diffusionLength}px`) this.smallCanvas.setAttribute('height',`${diffusionLength}px`) } let smallCtx = this.smallCanvas.getContext("2d") //初始化ImageData let finallyImageData = new ImageData(finallyOriginalPiexls,sepX,sepY) // 当前范围内需要放大的像素 smallCtx.putImageData(finallyImageData,0,0,0,0,diffusionLength,diffusionLength) let url = this.smallCanvas.toDataURL('image/jpeg',1) //将小图绘制到200*200的预览图上 var image = new Image(); image.src = url; await new Promise((resolve)=>{ image.onload = resolve }) var magnifyingGlassCtx = this.magnifyingGlassView.getContext("2d") magnifyingGlassCtx.drawImage(image, 0,0,200,200); } } |
上面的就是全部逻辑,实现方法肯定不是最优的,但是其中可以联想到通过像素点的操作实现任意效果。
三、获取像素信息跨域问题怎么解决?
可以启动一个 node 本地服务,首先见一个包含 index.js 和 package.json 的入口文件的文件夹。
package.json 内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | { "name": "youname", "version": "1.0.0", "description": "description", "main": "index.js", "scripts": { "test": "node ./index.js" }, "author": "wsl", "license": "ISC", "dependencies": { "express": "^4.17.3", "express-static": "^1.2.6", "http": "^0.0.1-security" } } |
index.js 内容如下:
1 2 3 4 5 6 7 8 9 | var express = require('express') var app = express() var http = require('http').Server(app) //公共页面访问设置 app.use(express.static('www')) //开启服务 http.listen(3000,function(){ console.log('开始了') }) |
终端执行 npm install 后再执行启动服务命令 node ./index.js:
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 【.NET】调用本地 Deepseek 模型
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)