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

yizhihongxing

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

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

一、实现效果

屏幕录制2023-02-18 下午8.21.50.gif

二、代码实现

代码不多,先看一下 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="">
</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:

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

image.png

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

image.png

这样跨域问题就解决了。

本文转载于:

https://juejin.cn/post/7201437314693906491

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

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

原文链接:https://www.cnblogs.com/smileZAZ/p/17337784.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:记录-JS简单实现购物车图片局部放大预览效果 - Python技术站

(0)
上一篇 2023年4月22日
下一篇 2023年4月24日

相关文章

  • jquery判断复选框选中状态以及区分attr和prop

    当我们在开发网站时,经常需要使用jQuery来操作复选框的选中状态。但是,由于jQuery的版本和浏览器的不同,有时候我们会遇到一些坑。本次攻略就来详细讲解如何使用jQuery判断复选框的选中状态,并探讨attr和prop两种方法之间的区别与使用场景。 一、使用prop方法判断复选框选中状态 jQuery的prop方法可以获取和设置HTML元素的属性值。对于…

    JavaScript 2023年6月11日
    00
  • php正则表达式基本知识与应用详解【经典教程】

    “PHP正则表达式基本知识与应用详解【经典教程】”是一篇关于PHP正则表达式的详细讲解文章,包含了从正则表达式基础知识到应用实例的全面介绍。 一、正则表达式基础知识 文章首先详细介绍了正则表达式的基础知识,包括元字符、定界符、字符集、量词等内容。针对每个知识点,作者都进行了详细的讲解并给出了示例说明。 例如,对于元字符一节,作者列出了常见的元字符,并给出了它…

    JavaScript 2023年6月10日
    00
  • JS实现表单验证功能(验证手机号是否存在,验证码倒计时)

    请看下面的攻略。 JS实现表单验证功能(验证手机号是否存在,验证码倒计时) 概述 表单验证是Web开发中非常常见的操作,通常的表单验证方式是利用前后端的交互获取数据进行验证,但是这种方式需要进行网络请求,不仅影响用户体验,也增加了服务器的负担。而JS实现表单验证则可以在不进行网络请求的情况下,对用户输入的数据进行实时验证,从而提高用户体验以及减轻服务器压力。…

    JavaScript 2023年6月10日
    00
  • 5种处理js跨域问题方法汇总

    以下是“5种处理js跨域问题方法汇总”的完整攻略: 1. 什么是跨域问题 跨域问题是指在浏览器端,当脚本试图访问来自不同源(域名、端口、协议)的资源时,会出现安全限制,这就是跨域问题。跨域问题对前端开发影响较大,如果不处理的话,可能会出现一些非常棘手的问题。 2. 为什么会出现跨域问题 跨域问题的产生是因为浏览器出于安全考虑而限制了客户端脚本中发起的跨域HT…

    JavaScript 2023年6月11日
    00
  • JS对字符串编码的几种方式使用指南

    JS对字符串编码的几种方式使用指南 在前端开发中,我们经常需要处理字符串编码的相关问题,如将字符串进行编码、解码等。本文将介绍JS中对于字符串编码的几种方式以及它们的使用方法,同时提供相应的示例。 Unicode编码 Unicode编码是一种用于表示各种字符的标准,它规定了字符集、编码方式、具体字符的表示方法等,是目前最常用的字符编码标准之一。在JS中,我们…

    JavaScript 2023年5月20日
    00
  • JavaScript实现H5接金币功能(实例代码)

    JavaScript实现H5接金币功能(实例代码)攻略 1. 理解接金币功能 接金币是一种在H5小游戏中常见的功能,玩家只需要点击页面上的金币图片,即可让自己的金币数量增加。在实现接金币功能时,我们需要实现以下几个步骤: 在页面中添加金币图片 实现点击金币图片后,金币数量增加的功能 将金币数量保存到本地,以便下次打开游戏时可以恢复之前的金币数量 2. 实现接…

    JavaScript 2023年6月11日
    00
  • JavaScript Date 知识浅析

    JavaScript Date 知识浅析 什么是 JavaScript Date? JavaScript Date 是 JavaScript 提供的内置对象之一,用于处理日期和时间的相关操作。它允许您创建和格式化日期、获取和设置不同的日期和时间值,以及执行其他日期和时间操作。 如何创建 Date 对象? 要创建一个新的 Date 对象,可以使用以下语法: n…

    JavaScript 2023年5月27日
    00
  • 创建与框架无关的JavaScript插件

    创建与框架无关的JavaScript插件,需要考虑以下关键要点: 1. 避免与全局命名空间冲突 在创建插件时,应尽可能避免使用全局命名空间中已存在的变量和函数。可以通过创建一个伪命名空间,将插件中的所有变量和函数保存在其中,并确保不会与其他脚本发生冲突。 var MyPlugin = (function() { // 插件的代码放在这里… })(); 2…

    JavaScript 2023年6月11日
    00
合作推广
合作推广
分享本页
返回顶部