记录-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="">
</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.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
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

记录-JS简单实现购物车图片局部放大预览效果的更多相关文章
- js实现FileUpload选择图片后预览功能
当asp.net的FileUpload选择一个图片后不需要上传就能显示出图片的预览功能, 代码: <%@ Page Language="C#" AutoEventWireup ...
- JavaScript实现图片裁剪预览效果~(第一个小玩具)
感觉开始学习的前一个月真的太不珍惜慕课网的资源了 上面蛮多小玩意真的蛮适合我这样刚入门JavaScript的同学加深使用理解 大概收藏了百来门或大或小的课程 有一个感觉就是学这个真的比光是看书看概 ...
- css+jquery 实现图片局部放大预览
今天有时间开始动手,使用css+jquery实现了图片局部放大的组件,首先看看效果图: 界面设计思路如下: 1.两个div,左边放图片的缩略图 2.在左边缩略图鼠标移动的时候,区域(效果图中的网格) ...
- 微信小程序实现图片放大预览效果
可以直接用微信程序自己的api很方便的实现 核心方法 wx.previewImage: 直接上代码, wxml: <!--pages/prewpicture/prew.wxml--> &l ...
- Jquery 下实现 图片大图预览效果
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...
- JS兼容各个浏览器的本地图片上传即时预览效果
JS兼容各个浏览器的本地图片上传即时预览效果 很早以前 在工作曾经碰到这么一个需求,当时也是纠结了很久,也是google了很久,没有碰到合适的demo,今天特意研究了下这方面的的问题,所以也就做了个简 ...
- JS兼容各个浏览器的本地图片上传即时预览效果\、
在firefox\chrome\ie10等浏览器中可以使用HTML5中的内容实现图片即时预览效果,在IE10以下浏览器中使用滤镜来解决图片显示问题. HTML5中的FileReader对象主要是把文件 ...
- javascript和HTML5上传图片之前实现预览效果
一:FileList对象与file对象 FileList对象表示用户选择的文件列表,在HTML4中,file控件内只允许放置一个文件,但是到了HTML5中,通过添加multiple属性,file控件内 ...
- js矩阵菜单或3D立体预览图片效果
js矩阵菜单或3D立体预览图片效果 下载地址: http://files.cnblogs.com/elves/js%E7%9F%A9%E9%98%B5%E8%8F%9C%E5%8D%95%E6%88% ...
- node.js平台下,cropper.js实现图片裁剪预览并转换为base64发送至服务端。
一 .准备工作 1.首先需要先下载cropper,常规使用npm,进入项目路径后执行以下命令: npm install cropper 2. cropper基于jquery,在此不要忘记引入jq,同时 ...
随机推荐
- Python树与树算法
Python树与树算法 树的概念 树(英语:tree)是一种抽象数据类型(ADT)或是实作这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合.它是由n(n>=1)个有限节点组成一个具 ...
- NC16527 [NOIP2013]货车运输
题目链接 题目 题目描述 A 国有 n 座城市,编号从 1 到 n ,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆 ...
- Codeforces Round #821 (Div. 2) A-E
比赛链接 A 题解 知识点:贪心. 下标模 \(k\) 相同分为一组,共有 \(k\) 组,组间不能互换,组内任意互换. 题目要求连续 \(k\) 个数字,一定能包括所有的 \(k\) 组,现在只要在 ...
- VS2019 添加三方文件夹遇到的坑
在开发新项目时需要用到一些三方 API,这些三方 API 没有生成 lib,所以我们在 VS 编译器中添加这些三方文件夹的头文件路径后 会出现 ERROR LNK2019 的错误提示,这些提示通常都是 ...
- [2023本地存储方案](https://www.cnblogs.com/fangchaoduan/p/17608006.html)
2023本地存储方案 本地存储方案 cookie 本地存储:有期限的限制,可以自己设置过期期限.在期限内,不论页面刷新还是关闭,存储的信息都还会存在. localStorage 本地持久化存储:页面刷 ...
- 【ACM专项练习#02】输入整行字符串、输入值到vector、取输入整数的每一位
输入整行字符串 平均绩点 题目描述 每门课的成绩分为A.B.C.D.F五个等级,为了计算平均绩点,规定A.B.C.D.F分别代表4分.3分.2分.1分.0分. 输入 有多组测试样例.每组输入数据占一行 ...
- 【算法day1】复杂度和简单排序算法(1)
复杂度和简单排序算法 时间复杂度 以一个排序(选择排序)操作举例 假设我有一个数组,我要找出其中的最小值放到0的位置上 那么 第一次我会遍历数组中N个数(在0位置处),找出最小的数交换到0位置[看了( ...
- 用宝塔设立分发Directory.Build.props及其Import文件的网站
新建站点 服务器名称我们约定是dev.amihome.cn 创建的默认站点有下面4个文件 把本地的文件,用宝塔上传 上图我们是把本地的Directory.Build.props文件上传到了网站的根目录 ...
- 【Azure Compute Gallery】使用 Python 代码从 Azure Compute Gallery 复制 Image-Version
问题描述 Azure Compute Gallery 可以帮助围绕 Azure 资源(例如映像和应用程序)生成结构和组织,并且支持全局复制. 如果想通过Python代码实现 Image-Version ...
- 解决celery与django结合后,分别启动celery和django的进程同时调用定时任务的问题
django中引入celery后发现在代码中写如下这样的定时任务,启动celery和django的工程后,他们都会调用这个定时任务导致,任务有的时候会冲突出现奇怪的问题.如何解决请继续看. sched ...
