“ PK创意闹新春,我正在参加「春节创意投稿大赛」,详情请看:春节创意投稿大赛”
前段时间摸鱼隐约看到有人吐槽沸点专栏图片的放大功能(不过现在好像是改版了哈),年前了也有点时间就想着如果我来实现这个功能的话会怎么做,做出来也方便了我们过年的时候一起扫敬业福不是嘛哈哈。
1.实现方案
正好最近在看vue3.0相关的东西,所以这个插件决定采用vue3.0+typescript来实现。
2.实现思路
本插件主要的功能是:实现点击一个小图片可以全屏展示当前图片的放大版。并且可以拖动,鼠标滚轴也可以控制图片的放大和缩小。
整体UI布局决定基于element-plus的el-dialog来实现,显示遮罩层,背景设置为透明色。
3.实现代码
// html部分
<div class="picview">
<el-dialog
v-model="picture"
:close-on-click-modal="false"
:fullscreen="true"
custom-class="picture"
>
<div v-loading.fullscreen.lock="loading" ref="myPic" class="main" @click="close($event)">
<img
v-show="isPicShow"
:src="src"
:width="picW"
:height="picH"
:style="{ transform: picTransform, top: picTop ,left:picLeft }"
@load="scalePic"
@error="setImgError"
@mousedown.prevent="mousedown($event)"
@mousemove.prevent="mousemove($event)"
@mouseup.prevent="mouseup($event)"
>
</div>
</el-dialog>
</div>
// js部分
import { defineEmit, ref, watch, toRefs } from 'vue'
const props = defineProps({
src: {
type: String,
default: ''
},
width: {
type: String,
default: ''
},
height: {
type: String,
default: ''
},
showPicture: {
type: Boolean,
default: false
}
})
const emit = defineEmit(['update:showPicture'])
const { showPicture } = toRefs(props)
const loading = ref(false)
const picture = ref(false)
const picW = ref(0)
const picH = ref(0)
const isPicShow = ref(false)
const picTransform = ref('')
const picTop = ref('')
const picLeft = ref('')
let scale = 1,
roted = 0,
isMoving = false,
disX = 0,
disY = 0
const myPic: Ref = ref(null)
watch(showPicture, (newVal, oldVal) => {
picture.value = newVal;
})
const scalePic = function() {
loading.value = false;
scale = 1;
roted = 0;
picTransform.value = 'scale(1)';
countImg();
window.onresize = function() {
countImg();
};
document.body.onmousewheel = function(event: any) {
event = event || window.event;
if (picture.value === true) {
if (event.deltaY > 0) {
scale = scale > 0.2 ? scale - 0.1 : scale;
} else {
scale += 0.1;
}
picTransform.value = `scale(${scale}) rotate(${roted}deg)`
}
};
}
const rotePic = function() {
roted = Number(roted) + 90;
picTransform.value = `scale(${scale}) rotate(${roted}deg)`
}
const close = function(e: any) {
if (e.target === myPic.value.childNodes[0]) {
return;
}
//
emit('update:showPicture', false);
// showPicture.value = false
e.stopPropagation();
}
const mousedown = function(e: any) {
let oDiv = myPic.value.childNodes[0];
isMoving = true;
disX = e.clientX - oDiv.offsetLeft;
disY = e.clientY - oDiv.offsetTop;
}
const mousemove = function(e) {
if (
isMoving &&
e.clientY > 0 &&
e.clientY < myPic.value.clientHeight &&
e.clientX > 0 &&
e.clientX < myPic.value.clientWidth
) {
picTop.value = e.clientY - disY + 'px';
picLeft.value = e.clientX - disX + 'px';
}
}
const mouseup = function() {
isMoving = false;
return false;
}
const countImg = function() {
const cpicW = myPic.value.childNodes[0].naturalWidth;
const cpicH = myPic.value.childNodes[0].naturalHeight;
let Width = myPic.value.offsetWidth;
let Height = myPic.value.offsetHeight;
if (Width / Height <= cpicW / cpicH) {
if (Width > cpicW) {
Width = cpicW;
}
picW.value = Width;
picH.value = (Number(cpicH) * Width) / Number(cpicW);
picTop.value = `${(Height - picH.value) / 2}px`;
picLeft.value = `${(myPic.value.offsetWidth - picW.value) / 2}px`;
isPicShow.value = true;
} else {
if (Height > cpicH) {
Height = cpicW;
}
picH.value = Height;
picW.value = (Number(cpicW) * Height) / Number(cpicH);
picLeft.value = `${(Width - picW.value) / 2}px`;
picTop.value = `${(myPic.value.offsetHeight - picH.value) / 2}px`;
isPicShow.value = true;
}
}
const setImgError = function() {
loading.value = false;
}
组件实现之后,我们就可以来把当前组件改造成我们可以供vue3.0项目使用的插件了。
4.封装插件
// imageView.vue写我们的组件
import imageView from './lib/imageView.vue'
// 定义我们的插件
const myPlugin = {
// 该插件有一个install方法
// 方法的第一个参数是传入的Vue,第二个参数可以插件的自定义参数
install (Vue: any) {
// 将其注册为vue的组件,'imageView'是组件名,imageView是我们开发的组件
Vue.component('imageView', imageView)
}
}
// 最后将插件导出,并在main.js中通过Vue.use()即可使用插件
export default myPlugin
插件开发具体过程,这里就不多赘述了,感兴趣的童鞋可以翻之前的文章。
5.使用插件
// main.ts
import imageView from 'lmuy-image-view'
createApp(App).use(imageView).mount('#app')
// 页面中
<lmuy-image-view
:src="src"
:show-picture="item.dialogVisible"
@update:show-picture="closeImage"/>
效果图如下所示,实现了图片的放大功能。并且使用方便,操作简单。沸点的放大完全可以这么来嘛,而且过年的时候我们传上去的那些隐藏在角落里的小敬业福,在我们这个插件的展示下,还不是乖乖被我们扫出来嘛~
当前插件已经被上传到
npm上,感兴趣的童鞋可以搜索lmuy-image-view进行查看。