手把手教你写一个图片预览组件
创始人
2024-03-04 14:26:11

一、前言

本篇主要介绍,vue项目手写一个图片预览组件,组件主要包括图片方法、图片缩小、显示原图、下载、复制等功能。

二、实现方式

首先我们需要做一个图片预览组件都有的功能表头,如下图

主要功能包括,放大、缩放比例显示、缩小、原图比例、旋转、复制、下载,如果是多图预览的话,还有上一张、下一张。接下来我们逐个实现各个功能。

1.初始化窗口显示完整图片

我们在一打开图片预览的时候,就是要看到图片的全貌,有时候图片会比我们预览的窗口要大许多,因此我们需要初始化的时候计算图片的大小和窗口大小的对应比例。代码如下


 

以上我们实现了图片的初始化显示

2.实现放大缩小逻辑

咱们这里主要css通过设置图片的缩放比例,利用zoom样式来实现图片的放大缩小。

 // 缩放,ratio为放大或缩小比例
handleZoom (ratio) {const styles = this.stylesconst abs = Math.abs(ratio)const changeScale = styles.ratio * absconst calScale = ratio > 0 ? changeScale : -changeScalelet _scale = styles.ratio + calScaleconst max = Math.min(this.SCALE_LIMIT.MAX, _scale) // 最大比例const min = Math.max(this.SCALE_LIMIT.MIN, _scale) // 最小比例console.log(_scale, max, this.SCALE_LIMIT.MAX)if (_scale > max) {_scale = max} else if (_scale < min) {_scale = min}_scale = parseFloat(_scale)this.setZoomSize(_scale)this.$nextTick(() => {this.setMargin()})
}, 

3.实现原始图片展示及复原

这里其实主要还是图片的缩放控制,代码如下

// 重置缩放比例, historyRatio记录原始大小之前的一次操作比例
handleResetZoom () {this.historyRatio = this.styles.ratiothis.setZoomSize(1)this.$nextTick(() => {this.setMargin()})
},
// 复原缩放比例, historyRatio
handleHistoryZoom () {this.setZoomSize(this.historyRatio)this.historyRatio = 0this.$nextTick(() => {this.setMargin()})
}, 

4.实现图片的翻转

这里主要是通过css的transform来实现的图片翻转,代码如下

// 旋转,配合样式的改变而改变
handleRotate () {this.styles.rotate += 90
}, 

5.实现图片的复制

这里主要用的clipboard剪切板和canvas来实现的图片复制,代码如下

// 复制图片
handleCopy() {var canvas = document.createElement('canvas') // 创建一个画板let image = new Image()image.setAttribute("crossOrigin", 'Anonymous') //可能会有跨越问题image.src = this.currentImgUrlimage.onload = () => {// img加载完成事件canvas.width = image.width//设置画板宽度canvas.height = image.height //设置画板高度canvas.getContext('2d').drawImage(image, 0, 0); //加载img到画板let url = canvas.toDataURL("image/png") // 转换图片为dataURL,格式为pngthis.clipboardImg(url) // 调用复制方法}
},
// 将图片写入到剪切板上
async clipboardImg (url) {try {const data = await fetch(url);const blob = await data.blob();await navigator.clipboard.write([new window.ClipboardItem({[blob.type]: blob})]);alert('复制成功')} catch (err) {alert('复制失败')}
}, 

6.实现图片的下载

这里就不说了,直接上代码吧

// 生成uuid
uuid (len, radix) {const chars = '0123456789abcdefghijklmnopqrstuvwxyz'.split('')const uuid = []let iradix = radix || 16len = len || 8radix = radix || chars.lengthif (len) {// Compact formfor (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]} else {// rfc4122, version 4 formlet r// rfc4122 requires these charactersuuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'uuid[14] = '4'// Fill in random data. At i==19 set the high bits of clock sequence as// per rfc4122, sec. 4.1.5for (i = 0; i < 36; i++) {if (!uuid[i]) {r = 0 | Math.random() * 16uuid[i] = chars[(i === 19) ? (r & 0x3) | 0x8 : r]}}}return uuid.join('')
},
// 下载
handleDownload () {fetch(this.currentImgUrl).then(res => res.blob().then(blob => {const a = document.createElement('a')const url = window.URL.createObjectURL(blob)const filename = this.uuid(8,16)a.href = url;a.download = filename;a.click();window.URL.revokeObjectURL(url);}));
}, 

7.实现ctrl + 滚轮事件缩放以及mac触摸板滚动放大缩小

这里主要通过监听鼠标的滚轮事件,来处理的缩放时间,触摸板同理

// 滚轮事件
handleMousewheel (evt) {this.wheelEvent(evt)
},
// ctrl + 滚轮事件缩放
wheelEvent (e) {if (Math.abs(e.deltaX) !== 0 && Math.abs(e.deltaY) !== 0) returnif (e.ctrlKey) {e.preventDefault()if (e.deltaY > 0) {this.handleZoom(-0.05)} else if (e.deltaY < 0) {this.handleZoom(0.05)}this.$nextTick(() => {this.setMargin()})}
}, 

以上就是逐个功能的实现代码一一说明。这些都是对于图片操作的主要实现方式。

三、后记

1. 全部代码及组件使用说明

图片预览组件的全部代码点击查看,下载代码下来复制直接使用,二次开发也可以。组件位置如图所示

其中index.vue为图片操作的各个封装,PreviewImageDialog.vue文件是做了个弹窗,用于弹窗显示图片预览内容,大家开发项目中肯定也有用到IU框架组件,到时候可以不用这个,直接引入index.vue组件, 放到dialog/modal等弹出窗中也是可以的。

2.关于dragToScroll

这里简单说下这个插件,它是用来将默认的拖拽变换成了scroll事件,在图片预览的时候,拖拽会变成滚动事件,用来查看全图。

最后

整理了75个JS高频面试题,并给出了答案和解析,基本上可以保证你能应付面试官关于JS的提问。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

相关内容

热门资讯

demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...