记录-JS简单实现购物车图片局部放大预览效果
来源:博客园 2023-04-21 04:04:01
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
一、实现效果
二、代码实现
代码不多,先看一下HTML里面结构很简单,初始化MagnifyingGlass对象来关联一个IMG标签来实现放大。
<script src="./magnifyingGlass.js"></script><script> //针对某个标签进行图片放大处理 let magnifyingGlass = new MagnifyingGlass(document.getElementById("clothes"))</script>
再看一下MagnifyingGlass
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内容如下:
{ "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内容如下:
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:
三、获取像素信息跨域问题怎么解决?
注意将前端文件放在目录里www文件夹下
这样跨域问题就解决了。
本文转载于:
https://juejin.cn/post/7201437314693906491
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。
关键词:
图片版权归原作者所有,如有侵权请联系我们,我们立刻删除。
新化月报网报料热线:886 2395@qq.com
新化月报网报料热线:886 2395@qq.com
最近更新
- 记录-JS简单实现购物车图片局部放大预览效果2023-04-21
- 特斯拉又降价了!Model 3、Model Y在美售价再降4.7%-6%|世界速读2023-04-21
- 全球观察:南通海安拟发放育儿补贴,三孩每月400元至3岁,入托费全免2023-04-21
- 沙钢股份:公司控股股东、实际控制人已向公司出具了避免同业竞争的承诺,公司已在相关公告中进行了披露-动态焦点2023-04-21
- 央行:要求房价出现趋势性上涨苗头的城市及时退出支持政策 世界视讯2023-04-21
- 你在租房时跳过单吗?法院认定违法,需付中介费及逾期利息_世界快看2023-04-21
- 【独家】2023中国酒都(宿迁)文化旅游节开幕,市委书记向客商推介五个“宿迁之美”2023-04-21
- 无锡惠山经开区牵手乌鲁木齐经开区,打造东西部“共建协同中心” 全球关注2023-04-21
- 无锡首部展示“非遗”活化利用成果的专著出版发行2023-04-21
- 世界最新:2023年国家级铜鼓文化(河池)生态保护实验区宣传活动启动2023-04-21
- 包头市应急管理局发布重要提示 天天速看料2023-04-21
- 共青团改革 | 云南:积分管理为县域共青团基层组织改革赋能|天天看热讯2023-04-21
- 【世界独家】大反转!临沂马上30度!剧烈升温后,直降18度!2023-04-21
- 今日热讯:《今日聚焦》——《寻找大厂崛起的密码》(三)喷薄而出的创新力2023-04-21
- 海王生物(000078):4月20日北向资金减持129.77万股2023-04-21
- 时讯:深天马A(000050):4月20日北向资金增持63.77万股2023-04-21
- 中金岭南(000060):4月20日北向资金增持296.23万股_今日热搜2023-04-21
- 环球微动态丨华锦股份(000059):4月20日北向资金减持12.19万股2023-04-21
- 时讯:德赛电池(000049):4月20日北向资金增持14.61万股2023-04-21
- 每日动态!浙江医院整形外科怎么样2023-04-21
- 院子不方正怎么圈院墙 看热讯2023-04-21
- 最新!4月20日正式开始!_滚动2023-04-21
- 微软DirectStorage加速技术升级1.2:老机械盘打一管鸡血2023-04-21
- 新宏泰(603016)龙虎榜数据(04-07)2023-04-21
- 世界看点:美联储的困境:拿什么“拯救”美国经济衰退2023-04-21
- 李开复:AI2.0时代来临 新一波商业潜能有望在各行各业加速点燃-天天关注2023-04-21
- 每日讯息!马龙力克英格兰一哥,林昀儒退役,澳门锦标赛男单四分之一决赛产生三个席位2023-04-21
- 樊振东国乒搭档官宣喜讯,曾头天获全国冠军,第二天退出国家队 环球即时2023-04-21
- 3-1!3-2!冠军赛3大冷门诞生:国乒3人出局,阻击张本智和失败2023-04-21
- 达科逆转梁靖崑,接发球环节制胜,陈梦克星击败王曼昱克星|天天报资讯2023-04-21