要实现富文本内图片点击实现放大器效果,在不改变<img /> 标签且不添加自定义指令的前提下放大图片,找了下没有找到合适的插件,就自己动手写一个图片放大器组件。
设计思路:
富文本里的图片,最终应该是呈现这样的状态:
<div>
<img src="……" />
<div class="content">扁扁的糖是扁的</div>
</div>
给富文本标签添加点击事件;
<div @click="setImgBigger" v-html="" />
点击事件,如果点击的是<img /> 标签,则识别浏览器,获取原生图片的大小和src,传参给图片放大器组件:
data() {
return {
ifShowBigger: false, //图片是否放大
imgSite: {
height: 0,
width: 0,
}, //图片属性
imgSrc:'', //图片路径
}
},
/**
* @description: 图片放大
* @param e
* @return void
*/
setImgBigger(e) {
if (e.target.nodeName === 'IMG') {
this.ifShowBigger = true //图片放大器组件开启
let userAgent = navigator.userAgent //识别浏览器
if (userAgent.indexOf('Chrome') > -1) {
this.imgSrc = e.target.currentSrc //谷歌
} else {
this.imgSrc = e.target.href //其他
}
this.imgSite.height = e.target.offsetHeight //原图片高度
this.imgSite.width = e.target.offsetWidth //原图片宽度
}
},
?引入图片放大器组件,传入展示参数为true则展示全屏图片:
<!-- 图片放大组件 -->
<big-img
:ifImgShow="ifShowBigger"
:imgSrc="imgSrc"
:imgSite="imgSite"
@closeBigImg="ifShowBigger = false"
/>
要注意的是,由于<img />的属性限制,等比例放大组件只要赋值相应的高度或者宽度其一就可以了,所以要想最大限度的放大图片,并且不让放大的图片超出可视区域,需要对容器和图片的宽高比进行计算,取比例小一个进行赋值:
ifImgShow(val) {
if (val) {
const _H = document.body.offsetHeight ?? 0 //容器高度
const _W = document.body.offsetWidth ?? 0 //容器宽度
const V = _H / this.imgSite.height > _W / this.imgSite.width //容器和图片的宽高比,是否高比大于宽比
//取比例小的一个进行赋值
this.H = V ? null : '90vh'
this.W = V ? '90vw' : null
}
},
详细代码:
父组件:
<!-- 需要放大的富文本 -->
<div @click="setImgBigger" v-html="" />
<!-- 图片放大组件 -->
<big-img
:ifImgShow="ifShowBigger"
:imgSrc="imgSrc"
:imgSite="imgSite"
@closeBigImg="ifShowBigger = false"
/>
data() {
return {
ifShowBigger: false, //图片放大器开关
imgSite: {
height: 0,
width: 0,
}, //图片属性
imgSrc: '', //图片地址
}
},
methods: {
/**
* @description: 图片放大
* @param e
* @return void
*/
setImgBigger(e) {
if (e.target.nodeName === 'IMG') {
this.ifShowBigger = true //打开图片放大器开关
let userAgent = navigator.userAgent //获取浏览器属性
if (userAgent.indexOf('Chrome') > -1) { //Google
this.imgSrc = e.target.currentSrc
} else { //其他
this.imgSrc = e.target.href
}
//保存原图片属性
this.imgSite.height = e.target.offsetHeight
this.imgSite.width = e.target.offsetWidth
}
},
},
图片放大器组件:
这里用了 css变量,详情介绍请移步之前的文章?Vue <style>使用变量 css使用变量
<template>
<div class="img-view" @click="getClose" :style="cssVar" v-show="ifImgShow">
<div class="img-layer">
<img :src="imgSrc" alt="图片地址错误" />
</div>
</div>
</template>
<script>
export default {
props: {
ifImgShow: {
type: Boolean,
default: false,
},
imgSrc: {
type: String,
default: '',
},
imgSite: {
type: Object,
default: () => {
return {}
},
},
},
data() {
return {
H: 0,
W: 0,
}
},
computed: {
cssVar({ H, W }) {
const _site = {
'--height': H,
'--width': W,
}
return _site
},
},
watch: {
ifImgShow(val) {
if (val) {
const _H = document.body.offsetHeight ?? 0 //容器高度
const _W = document.body.offsetWidth ?? 0 //容器宽度
const V = _H / this.imgSite.height > _W / this.imgSite.width //容器和图片的宽高比,是否高比大于宽比
this.H = V ? null : '90vh'
this.W = V ? '90vw' : null
}
},
},
methods: {
/**
* @description: 关闭图片放大
* @return void
*/
getClose() {
this.$emit('closeBigImg')
},
},
}
</script>
.img-view {
.img-layer {
width: 100%;
height: 100%;
position: fixed;
z-index: 5; //保证是容器内最大的z-index
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.7);
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
img {
height: var(--height);
width: var(--width);
}
}
}
|