记录-JS简单实现购物车图片局部放大预览效果

  • 记录-JS简单实现购物车图片局部放大预览效果已关闭评论
  • 95 次浏览
  • A+
所属分类:Web前端
摘要

代码不多,先看一下 HTML 里面结构很简单,初始化 MagnifyingGlass 对象来关联一个 IMG 标签来实现放大。


这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

记录-JS简单实现购物车图片局部放大预览效果

一、实现效果

记录-JS简单实现购物车图片局部放大预览效果

二、代码实现

代码不多,先看一下 HTML 里面结构很简单,初始化 MagnifyingGlass 对象来关联一个 IMG 标签来实现放大。

<!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="记录-JS简单实现购物车图片局部放大预览效果" alt=""> </div> </body>     <script src="./magnifyingGlass.js"></script> <script>     //针对某个标签进行图片放大处理     let magnifyingGlass = new MagnifyingGlass(document.getElementById('clothes')) </script>  </html>

再看一下 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.jspackage.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:

三、获取像素信息跨域问题怎么解决?

记录-JS简单实现购物车图片局部放大预览效果

注意将前端文件放在目录里 www 文件夹下

记录-JS简单实现购物车图片局部放大预览效果

这样跨域问题就解决了。

本文转载于:

https://juejin.cn/post/7201437314693906491

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 记录-JS简单实现购物车图片局部放大预览效果