|
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
一、实现效果
二、代码实现
代码不多,先看一下 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')[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
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。
来源:https://www.cnblogs.com/smileZAZ/p/17337784.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|