前情提要:搜索后发现没有移动端和PC兼容的符合我要求的现成组件于是想自己写一个图片预览的功能,写着写着发现里面门道有点子多导致越写越乱😂于是我!
找到了这篇文章⬇️
https://zhuanlan.zhihu.com/p/579668318
参考了这篇代码⬇️
https://code.juejin.cn/pen/7158337368355766285
大佬用了原生JS,我是放在VUE3项目中的,可以作一siusiu优化🤏而且我想在这个基础上新增一些卡边界的功能,然后我不自量力地改呀加呀努力地写呀。。
只是想分享一段代码的优化过程。我真的。。人家一次能写好的东西,我改一百次出来都不一定是最优雅的😭虽然我会努力,可是我想死😖😭
第一次尝试⬇️
if (scale.value < 1) {
const scale1TranslateDif = imgRef.value.offsetHeight - container.height
resetImage({
y: scale1TranslateDif > 0 ? y : Math.abs(scale1TranslateDif / 2)
})
} else if (scale.value > 2) {
const { top: translateY } = getBoundaryOffset({originO: newOrigin, newScale: 2})
// 放大后非长图居中
// console.log(imgRef.value.offsetHeight*2 - container.height)
const scale2isLongPic = imgRef.value.offsetHeight*2 - container.height
resetImage({
x,
y: scale2isLongPic > 0 ? y : translateY + Math.abs(scale2isLongPic/2),
newScale: 2,
newOrigin,
})
}
这次写完发现功能还不全呢,这个时候就应该意识到用if else来区分scale值有点不对劲了,虽然scale<1或>2需要重置,可是不管scale多大,y值长图都保持不变,非长图都得给它居中。但我脑子那会儿有点儿木于是在意识到不对劲的情况下硬是在不对劲的代码基础上做了第二次尝试⬇️
let newTranslateY: number = getBoundaryOffset({ originO: newOrigin }).top
if (scale.value < 1) {
const scale1YDif = imgRef.value.offsetHeight - container.height
newTranslateY = scale1YDif > 0 ? y : Math.abs(scale1YDif / 2)
} else if (scale.value > 2) {
const scale2YDif = imgRef.value.offsetHeight * 2 - container.height
newTranslateY =
scale2YDif > 0
? y
: getBoundaryOffset({ originO: newOrigin, newScale: 2 }).top + Math.abs(scale2YDif / 2)
} else {
newTranslateY =
isLongPic.value > 0
? y
: getBoundaryOffset({ originO: newOrigin }).top + Math.abs(isLongPic.value / 2)
}
resetImage({
x: scale.value < 1 ? 0 : x,
y: newTranslateY,
newScale: (scale.value < 1 && 1) || (scale.value > 2 && 2) || scale.value,
newOrigin: scale.value < 1 ? centerOrigin : newOrigin
})
这次写完倒是达到了我的目的,可是看着这些。。这么多。。。明显一样的代码只是换了个参数值我就脑壳疼😣于是又给它整合了一下子⬇️
const currentIsLongPic = (scale.value < 1 && imgRef.value.offsetHeight - container.height) || (scale.value > 2 && imgRef.value.offsetHeight*2 - container.height) || isLongPic.value
const currentCenterY = getBoundaryOffset({originO: scale.value < 1 ? centerOrigin : newOrigin, newScale: (scale.value < 1 && 1) || (scale.value > 2 && 2) || scale.value}).top + Math.abs(currentIsLongPic/2)
resetImage({
x: scale.value < 1 ? 0 : x,
y: currentIsLongPic > 0 ? y : currentCenterY,
newScale: (scale.value < 1 && 1) || (scale.value > 2 && 2) || scale.value,
newOrigin: scale.value < 1 ? centerOrigin : newOrigin
})
看着最后这次的代码,我依然不知道这是不是它们最好的呈现方式,但对于目前的我来说,它真的顺眼多了。
其实应该一开始别着急上手,先想清楚,reset的目的是什么。
首先,y值计算。图片为非长图时设置y值给它垂直居中,长图时保持值不变;
其次,x轴的偏移量和newScale的计算。只有scale<1或>2时才给它固定,其它时候都是scale值本身;
第三,scale基准点的传值。只有scale<1时需要才回到center位置。
想明白这三点再下手敲。。应该就不会像我这次这么痛苦了吧😂
网友评论