点击缩略图放大,查看原比例高清大图,是我们做完图片上传功能后经常需要遇到面对的问题,比如图片预览。虽然这个问题zoom.js这个现成插件可以帮我们解决,美中不足的是,zoom.js放大后的图片会受原img本身外层高宽限制,恰恰我们做缩略图往往会限制外层宽高以便多图呈现,并希望放大后的图片不受原img影响,基于这个问题,下面借助layer.js简单封装了一个Vue图片缩放组件。
目录
1.demo页面
kt-zoom-demo.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<link rel="stylesheet" href="kt-zoom.css">
<style>
.wrap {
border: 1px solid;
/* 自身水平垂直居中 */
width: 300px;
height: 300px;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
/* 内部元素水平垂直居中 */
display: flex;
justify-content: center;
align-items: center;
}
.wrap img {
max-width: calc(100% - 12px);
max-height: calc(100% - 12px);
}
.el-card__body {
position: relative;
height: calc(100vh - 100px);
}
.el-icon-view:hover{
color: #f56c6c;
}
</style>
<title>Document</title>
</head>
<body>
<div id="app">
<el-card style="padding: 20px;" v-cloak>
<div slot="header">
KT-ZOOM-DEMO
<kt-zoom custom :src="src">
<el-button style="font-size: 16px;" type="text" size="mini">
<i class="el-icon-view"></i>
</el-button>
</kt-zoom>
</div>
<div class="wrap">
<kt-zoom class="real-img" :src="src"></kt-zoom>
</div>
</el-card>
</div>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="kt-zoom.js"></script>
<script>
const APP = new Vue({
el: '#app',
data() {
return {
src: 'images/tongliya.jpg'
}
}
});
</script>
</body>
</html>
2.组件核心:JS/CSS/辅助页面
kt-zoom.js
document.write("<script src='layer/layer.js'></script>");
Vue.component("kt-zoom", {
template: `
<span v-if="custom" @click="clickMe" v-cloak><slot></slot></span>
<img v-else class="zoom-in" :src="src || 'images/zhanwutupian.png'" alt="This is an image" @click="clickMe" v-cloak>
`,
props: {
src: String,
custom: {
type: Boolean,
default: false
}
},
methods: {
clickMe() {
// const $ev = ev || event;
// let src = $ev.target.getAttribute('src');
let src = this.src || 'images/zhanwutupian.png';
if (src.indexOf('=') !== -1) src = src.replace(/=/g, "%3D");
layer.open({
type: 2,
title: false,
closeBtn: 0,
area: ['60%', '80%'],
skin: 'layui-layer-nobg', //没有背景色
shadeClose: true,
content: `!!kt-zoom-img!!.html?src=${src}`
});
}
}
});
kt-zoom.css
[v-cloak] {
display: none !important;
}
.zoom-in {
transition: width 1s, height 1s;
}
.zoom-in:hover {
cursor: url("images/zoomin.ico"), auto;
}
.zoom-out {
transition: width 1s, height 1s;
}
.zoom-out:hover {
cursor: url("images/zoomout.ico"), auto;
}
.kt-zoom_wrap {
/* 自身水平垂直居中 */
width: 100%;
height: 100%;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
/* 内部元素水平垂直居中 */
display: flex;
justify-content: center;
align-items: center;
}
.kt-zoom_wrap img {
max-width: calc(100% - 12px);
max-height: calc(100% - 12px);
}
!!kt-zoom-img!!.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<link rel="stylesheet" href="kt-zoom.css">
<style>
html, body {
width: 100%;
height: 100%;
}
</style>
<title>Document</title>
</head>
<body>
<div id="app">
<div class="kt-zoom_wrap" v-cloak>
<img class="zoom-out" :src="src" alt="Here is an img" @click="clickMe">
</div>
</div>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script>
const APP = new Vue({
el: '#app',
data() {
return {
src: void 0,
}
},
methods: {
clickMe() {
// 当你在iframe页面关闭自身时
let index = parent.layer.getFrameIndex(window.name); // 先得到当前iframe层的索引
parent.layer.close(index); // 再执行关闭
},
// 获取父页面url传参
getParams(){
const url = location.search;
let params = {};
if (url.indexOf("?") !== -1) {
let str = url.substr(1);
let strs = str.split("&");
for (let i = 0; i < strs.length; i++) {
params[strs[i].split("=")[0]] = unescape(strs[i].split("=")[1]);
}
}
return params;
}
},
created() {
this.src = encodeURI(this.getParams().src) || 'images/zhanwutupian.png';
}
});
</script>
</body>
</html>
3.demo演示
4.实现原理简述
1.通过layer弹出框插件,点击缩略图时,弹出辅助页面并传入src路径。
2.辅助页面放置img原图,设置max-width、max-height百分百并且水平垂直居中即可。
PS:完整demo以图包方式存放,右键 演示demo.gif 存储=》重命名xxx.rar=>解压即可。