当前位置: 首页 > news >正文

vue2图片预览插件

学习:vue插件开发实例-图片预览插件
vue2-pre-img-plugin的gitee代码

准备工作

准备图片与基础的样式

  • 将iconfont下载的字体图标资源放在src/assets/iconfont目录下
  • 将准备预览的图片放到src/static/images目录下

PrevImg.vue

在plugins/PrevImg目录下,创建PrevImg.vue。

直接引入静态图片资源,然后作为vue组件实例的data

<template><div class="prev-container"><div class="mask"></div><div class="indicator"><i class="iconfont icon-jiahao1"></i><i class="iconfont icon-jian"></i><i class="iconfont icon-reset"></i><i class="iconfont icon-close"></i></div><div class="img-wrapper"><img :src="imgPath"></div></div>
</template><script>
import img1 from '@/static/images/1.jpg'
import img2 from '@/static/images/2.jpg'
import img3 from '@/static/images/3.jpg'
import img4 from '@/static/images/4.png'
import img5 from '@/static/images/5.png'console.log('PrevImg->img1',img1); // PrevImg->img1 /img/1.1a1b49d1.jpgexport default {name: 'PrevImg2',data() {return {imgPath: img1}},
}
</script><style lang="scss">.prev-container {position: fixed;top:0;left: 0;width: 100%;height: 100%;.mask {position: absolute;background-color: rgba(0,0,0,.3);width: 100%;height: 100%;z-index: -1;}.indicator {display: flex;justify-content: flex-end;padding: 20px;z-index: 100;i {padding: 10px;background-color: rgba(255,255,255,.3);border-radius: 50%;margin: 0 5px;cursor: pointer;}}.img-wrapper {position: absolute;top: 0;width: 100%;height: 100%;z-index: -1;display: flex;align-items: center;justify-content: center;img {max-height: 100%;max-width: 80%;transition: all 0.5s;}}}
</style>

App.vue

App.vue中使用改组件

<template><div id="app"><prev-img/></div>
</template><script>import PrevImg from '@/plugins/prevImg/PrevImg'export default {name: 'App',components: {PrevImg}
}
</script><style>
* {margin: 0;
}body {display: flex;flex-direction: column;
}.btn-box {text-align: center;margin-top: 20px;
}
</style>

静态效果

在这里插入图片描述

封装插件

修改PrevImg.vue

为按钮绑定相关的方法,图片的路径,将由外部传递过来

<template><div class="prev-container" v-show="isShow"><div class="mask"></div><div class="indicator"><i @click="operate('zoomIn')" class="iconfont icon-jiahao1"></i><i @click="operate('zoomOut')" class="iconfont icon-jian"></i><i @click="operate('rotate')" class="iconfont icon-reset"></i><i @click="close" class="iconfont icon-close"></i></div><div class="img-wrapper"><img :src="imgPath" :style="imgStyle" alt=""></div></div>
</template><script>export default {name: 'PrevImg',components: {},data() {return {isShow: false,imgPath: '',transform: {rotate: 0,scale: 1}}},computed:{imgStyle() {let {rotate, scale} = this.transformreturn {transform: `scale(${scale}) rotate(${rotate}deg)`}}},methods: {open({url}) {this.isShow = truethis.imgPath = url},close() {console.log('object');this.isShow = false},operate(command) {if(command == 'zoomIn') {this.transform.scale += 0.04} else if(command == 'zoomOut') {this.transform.scale -= 0.04} else if(command == 'rotate') {this.transform.rotate += 90} }}
}
</script><style lang="scss">.prev-container {position: fixed;top:0;left: 0;width: 100%;height: 100%;.mask {position: absolute;background-color: rgba(0,0,0,.3);width: 100%;height: 100%;z-index: -1;}.indicator {display: flex;justify-content: flex-end;padding: 20px;z-index: 100;i {padding: 10px;background-color: rgba(255,255,255,.3);border-radius: 50%;margin: 0 5px;cursor: pointer;}}.img-wrapper {position: absolute;top: 0;width: 100%;height: 100%;z-index: -1;display: flex;align-items: center;justify-content: center;img {max-height: 100%;max-width: 80%;transition: all 0.5s;}}}
</style>

定义插件逻辑

import PrevImg from '@/plugins/prevImg/PrevImg'export default {install(Vue, options) {let PrevImgConstructor = Vue.extend(PrevImg)let instance = new PrevImgConstructor()/* 这里会打印dom */console.log('instance', instance.$mount().$el);// instance <div class="prev-container" style="display: none;">...</div>/* 把组件转换成了dom,插入到了body中  */document.body.appendChild(instance.$mount().$el) let opts = {open(url) {// 调用组件实例上定义的方法instance.open({url})},close() {instance.close()}}// 挂载到vue组件实例上Vue.prototype.$prevImg = opts}
}

main.js中应用此插件

import Vue from 'vue'
import App from './App.vue'import '@/assets/iconfont/iconfont.css'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';import prevImg from './plugins/prevImg';Vue.config.productionTip = falseVue.use(ElementUI)
Vue.use(prevImg)new Vue({render: h => h(App),
}).$mount('#app')

App.vue中使用此插件

<template><div id="app"><div class="btn-box"><el-button @click="preview">打开预览</el-button></div></div>
</template><script>
import img1 from '@/static/images/1.jpg'
import img2 from '@/static/images/2.jpg'
import img3 from '@/static/images/3.jpg'
import img4 from '@/static/images/4.png'
import img5 from '@/static/images/5.png'export default {name: 'App',components: {},methods: {preview() {// 原本测试的是把PrevImg.vue组件给引进来, 直接调用子组件的方法使用, 但// 是没想到插件还能这么玩的, 感觉那种方式会更好// this.$refs.prevImgRef.open()this.$prevImg.open(img4)}}
}
</script><style>
* {margin: 0;
}body {display: flex;flex-direction: column;
}.btn-box {text-align: center;margin-top: 20px;
}
</style>

在这里插入图片描述

图片预览列表

在这里插入图片描述

修改App.vue

<template><div id="app"><div class="btn-box"><el-button @click="preview">打开预览</el-button></div></div>
</template><script>
import img1 from '@/static/images/1.jpg'
import img2 from '@/static/images/2.jpg'
import img3 from '@/static/images/3.jpg'
import img4 from '@/static/images/4.png'export default {name: 'App',components: {},methods: {preview() {// this.$refs.prevImgRef.open()this.$prevImg.open(0,[img1,img2,img3,img4])}}
}
</script><style>
* {margin: 0;
}body {display: flex;flex-direction: column;
}.btn-box {text-align: center;margin-top: 20px;
}
</style>

修改插件逻辑

import PrevImg from '@/plugins/prevImg/PrevImg'
export default {install(Vue, options) {let PrevImgConstructor = Vue.extend(PrevImg)let instance = new PrevImgConstructor()/* 这里会打印dom */console.log('instance', instance.$mount().$el);// instance <div class="prev-container" style="display: none;">...</div>/* 把组件转换成了dom,插入到了body中  */document.body.appendChild(instance.$mount().$el) let opts = {open(imgIdx,imgPaths) {instance.open({imgIdx,imgPaths})},close() {instance.close()}}Vue.prototype.$prevImg = opts}
}

修改PrevImg.vue

<template><div class="prev-container" v-show="isShow"><div class="mask"></div><div class="indicator"><i @click="operate('zoomIn')" class="iconfont icon-jiahao1"></i><i @click="operate('zoomOut')" class="iconfont icon-jian"></i><i @click="operate('rotate')" class="iconfont icon-reset"></i><i @click="close" class="iconfont icon-close"></i></div><div :class="['prev-next', 'left', { 'pointer-allowd': isPrev }]" @click="operate('left')"><i class="iconfont icon-houtuishangyige"></i></div><div :class="['prev-next', 'right', { 'pointer-allowd': isNext }]" @click="operate('right')"><i class="iconfont icon-qianjinxiayige"></i></div><div ref="imgWrapper" :class="['img-wrapper']"><img :src="imgPaths[imgIdx]" :style="imgStyle" alt=""></div></div>
</template><script>export default {name: 'PrevImg',components: {},data() {return {isShow: false,imgIdx: 0,imgPaths: [],transform: {rotate: 0,scale: 1},enterAniClass: '',}},computed: {imgStyle() {let { rotate, scale } = this.transformreturn {transform: `scale(${scale}) rotate(${rotate}deg)`}},isNext() {return this.imgIdx != this.imgPaths.length - 1},isPrev() {return this.imgIdx != 0},},mounted() {this.$refs['imgWrapper'].addEventListener('webkitAnimationEnd', (e) => {console.log('动画停止了');this.enterAniClass = ''})},methods: {open({ imgIdx, imgPaths }) {this.isShow = truethis.imgIdx = imgIdxthis.imgPaths = imgPaths},close() {console.log('object');this.isShow = falsethis.transform = {rotate: 0,scale: 1}},operate(command) {if (command == 'zoomIn') {this.transform.scale += 0.04} else if (command == 'zoomOut') {this.transform.scale -= 0.04} else if (command == 'rotate') {this.transform.rotate += 90} else {this.transform = {rotate: 0,scale: 1}if (command == 'left') {if (this.imgIdx == 0) {return}this.imgIdx = this.imgIdx - 1} else if (command == 'right') {if (this.imgIdx == this.imgPaths.length - 1) {return}this.imgIdx = this.imgIdx + 1}}}}
}
</script><style lang="scss">
.prev-container {position: fixed;top: 0;left: 0;width: 100%;height: 100%;.mask {position: absolute;background-color: rgba(0, 0, 0, .3);width: 100%;height: 100%;z-index: -1;}.pointer-allowd {cursor: pointer !important;}.prev-next {width: 36px;height: 36px;border-radius: 50%;background-color: rgba(255, 255, 255, .3);text-align: center;line-height: 36px;cursor: not-allowed;position: absolute;top: 0;bottom: 0;margin: auto;z-index: 2000;}.left {left: 30px;}.right {right: 30px;}.indicator {display: flex;justify-content: flex-end;padding: 20px;z-index: 100;i {padding: 10px;background-color: rgba(255, 255, 255, .3);border-radius: 50%;margin: 0 5px;cursor: pointer;}}.img-wrapper {position: absolute;top: 0;width: 100%;height: 100%;z-index: -1;display: flex;align-items: center;justify-content: center;img {max-height: 100%;max-width: 80%;transition: all 0.5s;}}
}</style>

相关文章:

vue2图片预览插件

学习&#xff1a;vue插件开发实例-图片预览插件 vue2-pre-img-plugin的gitee代码 准备工作 准备图片与基础的样式 将iconfont下载的字体图标资源放在src/assets/iconfont目录下将准备预览的图片放到src/static/images目录下 PrevImg.vue 在plugins/PrevImg目录下&#xff…...

手写Promise源码的实现思路

Promise的使用&#xff1a; let promise new Promise((resolve, reject) > {resolve("OK");// reject("Error"); });console.log(promise);promise.then(value > {console.log("success"); }, error > {console.log("fail"…...

【数据结构】-关于树的概念和性质你了解多少??

作者&#xff1a;小树苗渴望变成参天大树 作者宣言&#xff1a;认真写好每一篇博客 作者gitee:gitee 如 果 你 喜 欢 作 者 的 文 章 &#xff0c;就 给 作 者 点 点 关 注 吧&#xff01; 树前言一、树概念及结构1.1树的概念1.2 树的相关概念1.3 树的表示1.4树在实际中的运用…...

【前端之旅】NPM必知必会

一名软件工程专业学生的前端之旅,记录自己对三件套(HTML、CSS、JavaScript)、Jquery、Ajax、Axios、Bootstrap、Node.js、Vue、小程序开发(UniApp)以及各种UI组件库、前端框架的学习。 【前端之旅】Web基础与开发工具 【前端之旅】手把手教你安装VS Code并附上超实用插件…...

Android SQLite使用事务来确保所有语句都以原子方式执行及保证数据完整性一次执行多条语句示例

execSQL 不支持用分号分隔一次执行多个 SQL 语句&#xff0c;虽然理论上可以实现。但是&#xff0c;并不建议这样做&#xff0c;因为这可能会导致潜在的 SQL 注入漏洞。相反&#xff0c;建议使用 execSQL 或 rawQuery 分别执行每个语句。 在下面的代码块中&#xff0c;我们正在…...

nodejs+vue校园超市小卖部零食在线购物商城系统

21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#xff0c;科学化的管理&#xff0c;使信息存储达到…...

Karl Guttag:论相机对焦技术在AR/VR中的沿用

近期&#xff0c;AR/VR光学专家Karl Guttag介绍了两家在CES 2023展出光学传感技术的公司&#xff1a;poLight和CML&#xff08;剑桥机电一体化&#xff09;。​同时介绍两家公司的原因&#xff0c;是因为他们提供了实现AR/VR“光学微动”&#xff08;Optics Micromovement&…...

ECL@SS学习笔记(3)-概念数据模型

ECLSS 是产品&#xff0c;服务的分类和描述系统。本文介绍其内部的数据模型。ECLSS的作用ECLSS 标准的目标是为了实现工业界数据交换的标准化。这个标准主要作用是产品的分类和描述。分类为了有效地物料管理&#xff0c;供应链管理和电子商务&#xff0c;需要对物料进行分类和编…...

206. 反转链表

给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 示例 2&#xff1a; 输入&#xff1a;head [1,2] 输出&#xff1a;[2,1] 示例 3&#xff1a; 输…...

文心一言 vs GPT-4 —— 全面横向比较

文心一言 vs GPT-4 —— 全面横向比较 3月15日凌晨&#xff0c;OpenAI发布“迄今为止功能最强大的模型”——GPT-4。我第一时间为大家奉上了体验报告《OpenAI 发布GPT-4——全网抢先体验》。 时隔一日&#xff0c;3月16日下午百度发布大语言模型——文心一言。发布会上&#…...

rancher2.6进阶之kubectl安装

rancher2.6进阶之kubectl安装 1.安装kubectl客户端 1.1.1.使用命令行下载安装包: curl -LO https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl Note: 可指定下载版本, 将 ( c u r l − L − s h t t p s : / / d l . k …...

图像基本变换

缩放与裁剪裁剪图像的裁剪&#xff0c;是指将图像的某个区域切割出来。一些常见的应用场景包括&#xff1a;* 感兴趣区域提取* 去除无用信息* 图像增强* 纠偏&#xff1a;去除不规则部分&#xff0c;将图像变得更加整齐事实上&#xff0c;图像裁剪的裁剪通常就是一个numpy矩阵切…...

基于文心一言的底层视觉理解,百度网盘把「猫」换成了「黄色的猫」

随着移动互联网的一路狂飙&#xff0c;手机已经成为人们的新器官。出门不带钥匙可以&#xff0c;不带手机却是万万不可以的。而手机上&#xff0c;小小的摄像头也越来越成为各位「vlogger」的口袋魔方。每天有超过数亿的照片和视频被上传到百度网盘中&#xff0c;这些照片和视频…...

安卓开发的环境配置教程

文章目录事先准备&#xff1a;下载 JDK、Gradle下载安装 Android Studio下载安装 Android SDK下载安装 ADB笔者的环境&#xff1a; Java 17.0.1 Gradle 8.0.1 Android Studio Electric Eel | 2022.1.1 Patch 1 Windows 10 教育版 64位 事先准备&#xff1a;下载 JDK、Gradl…...

【Spring Cloud Alibaba】Spring Cloud Alibaba 搭建教程

文章目录教程适用版本一、简介主要功能组件开源地址二、开始搭建1.项目搭建与依赖管理2.服务注册与发现&#xff08;Nacos安装&#xff09;3.创建服务提供者4.创建服务消费者5.创建服务消费者(Feign)6.添加熔断机制&#xff08;Sentinel&#xff09;7.Sentinel熔断器仪表盘监控…...

关于自动机器学习flaml训练时的一些报错

一、版本背景flaml 1.1.3sciket-learn 0.23.0二、一路报错2.1、SyntaxError: future feature annotations is not definedTraceback (most recent call last):File "C:/Users/dell/Desktop/AI/run.py", line 151, in <module>model.autoMlArgs(queryDf,targe…...

【计算机视觉】消融实验(Ablation Study)是什么?

文章目录一、前言二、定义三、来历四、举例说明一、前言 我第一次见到消融实验&#xff08;Ablation Study&#xff09;这个概念是在论文《Faster R-CNN》中。 消融实验类似于我们熟悉的“控制变量法”。 假设在某目标检测系统中&#xff0c;使用了A&#xff0c;B&#xff0…...

Java毕业论文参考文献参考例子整理

[1]李庆民.基于java的软件agent开发环境的分析[J].数字技术与应用,2017,01:189.    [2]籍慧文.Web应用开发中JAVA编程语言的应用探讨[J].科技创新与应用,2017,07:90.    [3]卜令瑞.基于Java软件项目开发岗位的企业实践总结报告[J].职业,2016,32:124-125.    [4]肖成金,吕…...

C++ Primer第五版_第六章习题答案(21~30)

文章目录练习6.21练习6.22练习6.23练习6.24练习6.25练习6.26练习6.27练习6.28练习6.29练习6.30练习6.21 编写一个函数&#xff0c;令其接受两个参数&#xff1a;一个是int型的数&#xff0c;另一个是int指针。函数比较int的值和指针所指的值&#xff0c;返回较大的那个。在该函…...

SLAM算法之HectorSLAM,Gmapping,KartoSLAM,CoreSLAM和LagoSLAM

文章将介绍使用的基于机器人操作系统&#xff08;ROS&#xff09;框架工作的SLAM算法。 在ROS中提供的五种基于2D激光的SLAM算法分别是&#xff1a;HectorSLAM&#xff0c;Gmapping&#xff0c;KartoSLAM&#xff0c;CoreSLAM和LagoSLAM。当然最后还有比较经典的google开源的ca…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

深入理解Optional:处理空指针异常

1. 使用Optional处理可能为空的集合 在Java开发中&#xff0c;集合判空是一个常见但容易出错的场景。传统方式虽然可行&#xff0c;但存在一些潜在问题&#xff1a; // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...

HTML前端开发:JavaScript 获取元素方法详解

作为前端开发者&#xff0c;高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法&#xff0c;分为两大系列&#xff1a; 一、getElementBy... 系列 传统方法&#xff0c;直接通过 DOM 接口访问&#xff0c;返回动态集合&#xff08;元素变化会实时更新&#xff09;。…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关

在水泥厂的生产流程中&#xff0c;工业自动化网关起着至关重要的作用&#xff0c;尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关&#xff0c;为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多&#xff0c;其中不少设备采用Devicenet协议。Devicen…...