悦风兰泰 发表于 2023-4-20 18:37:13

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

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



一、实现效果


二、代码实现

代码不多,先看一下 HTML 里面结构很简单,初始化 MagnifyingGlass 对象来关联一个 IMG 标签来实现放大。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>


<body>

    <img id="clothes"src="https://www.cnblogs.com/./clothes.jpg" alt="">

</body>
   


</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')
      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 = this.originalPiexls.data
                  } else {
                        finallyOriginalPiexls = 199
                  }
                  } else {
                        finallyOriginalPiexls = 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

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

 

来源:https://www.cnblogs.com/smileZAZ/p/17337784.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 记录-JS简单实现购物车图片局部放大预览效果