management/front/dkha-web-sz-main/node_modules/element-ui/packages/image/src/main.vue

232 lines
6.1 KiB
Vue

<template>
<div class="el-image">
<slot v-if="loading" name="placeholder">
<div class="el-image__placeholder"></div>
</slot>
<slot v-else-if="error" name="error">
<div class="el-image__error">{{ t('el.image.error') }}</div>
</slot>
<img
v-else
class="el-image__inner"
v-bind="$attrs"
v-on="$listeners"
@click="clickHandler"
:src="src"
:style="imageStyle"
:class="{ 'el-image__inner--center': alignCenter, 'el-image__preview': preview }">
<template v-if="preview">
<image-viewer :z-index="zIndex" :initial-index="imageIndex" v-show="showViewer" :on-close="closeViewer" :url-list="previewSrcList"/>
</template>
</div>
</template>
<script>
import ImageViewer from './image-viewer';
import Locale from 'element-ui/src/mixins/locale';
import { on, off, getScrollContainer, isInContainer } from 'element-ui/src/utils/dom';
import { isString, isHtmlElement } from 'element-ui/src/utils/types';
import throttle from 'throttle-debounce/throttle';
const isSupportObjectFit = () => document.documentElement.style.objectFit !== undefined;
const ObjectFit = {
NONE: 'none',
CONTAIN: 'contain',
COVER: 'cover',
FILL: 'fill',
SCALE_DOWN: 'scale-down'
};
let prevOverflow = '';
export default {
name: 'ElImage',
mixins: [Locale],
inheritAttrs: false,
components: {
ImageViewer
},
props: {
src: String,
fit: String,
lazy: Boolean,
scrollContainer: {},
previewSrcList: {
type: Array,
default: () => []
},
zIndex: {
type: Number,
default: 2000
}
},
data() {
return {
loading: true,
error: false,
show: !this.lazy,
imageWidth: 0,
imageHeight: 0,
showViewer: false
};
},
computed: {
imageStyle() {
const { fit } = this;
if (!this.$isServer && fit) {
return isSupportObjectFit()
? { 'object-fit': fit }
: this.getImageStyle(fit);
}
return {};
},
alignCenter() {
return !this.$isServer && !isSupportObjectFit() && this.fit !== ObjectFit.FILL;
},
preview() {
const { previewSrcList } = this;
return Array.isArray(previewSrcList) && previewSrcList.length > 0;
},
imageIndex() {
return this.previewSrcList.indexOf(this.src);
}
},
watch: {
src(val) {
this.show && this.loadImage();
},
show(val) {
val && this.loadImage();
}
},
mounted() {
if (this.lazy) {
this.addLazyLoadListener();
} else {
this.loadImage();
}
},
beforeDestroy() {
this.lazy && this.removeLazyLoadListener();
},
methods: {
loadImage() {
if (this.$isServer) return;
// reset status
this.loading = true;
this.error = false;
const img = new Image();
img.onload = e => this.handleLoad(e, img);
img.onerror = this.handleError.bind(this);
// bind html attrs
// so it can behave consistently
Object.keys(this.$attrs)
.forEach((key) => {
const value = this.$attrs[key];
img.setAttribute(key, value);
});
img.src = this.src;
},
handleLoad(e, img) {
this.imageWidth = img.width;
this.imageHeight = img.height;
this.loading = false;
},
handleError(e) {
this.loading = false;
this.error = true;
this.$emit('error', e);
},
handleLazyLoad() {
if (isInContainer(this.$el, this._scrollContainer)) {
this.show = true;
this.removeLazyLoadListener();
}
},
addLazyLoadListener() {
if (this.$isServer) return;
const { scrollContainer } = this;
let _scrollContainer = null;
if (isHtmlElement(scrollContainer)) {
_scrollContainer = scrollContainer;
} else if (isString(scrollContainer)) {
_scrollContainer = document.querySelector(scrollContainer);
} else {
_scrollContainer = getScrollContainer(this.$el);
}
if (_scrollContainer) {
this._scrollContainer = _scrollContainer;
this._lazyLoadHandler = throttle(200, this.handleLazyLoad);
on(_scrollContainer, 'scroll', this._lazyLoadHandler);
this.handleLazyLoad();
}
},
removeLazyLoadListener() {
const { _scrollContainer, _lazyLoadHandler } = this;
if (this.$isServer || !_scrollContainer || !_lazyLoadHandler) return;
off(_scrollContainer, 'scroll', _lazyLoadHandler);
this._scrollContainer = null;
this._lazyLoadHandler = null;
},
/**
* simulate object-fit behavior to compatible with IE11 and other browsers which not support object-fit
*/
getImageStyle(fit) {
const { imageWidth, imageHeight } = this;
const {
clientWidth: containerWidth,
clientHeight: containerHeight
} = this.$el;
if (!imageWidth || !imageHeight || !containerWidth || !containerHeight) return {};
const vertical = imageWidth / imageHeight < 1;
if (fit === ObjectFit.SCALE_DOWN) {
const isSmaller = imageWidth < containerWidth && imageHeight < containerHeight;
fit = isSmaller ? ObjectFit.NONE : ObjectFit.CONTAIN;
}
switch (fit) {
case ObjectFit.NONE:
return { width: 'auto', height: 'auto' };
case ObjectFit.CONTAIN:
return vertical ? { width: 'auto' } : { height: 'auto' };
case ObjectFit.COVER:
return vertical ? { height: 'auto' } : { width: 'auto' };
default:
return {};
}
},
clickHandler() {
// prevent body scroll
prevOverflow = document.body.style.overflow;
document.body.style.overflow = 'hidden';
this.showViewer = true;
},
closeViewer() {
document.body.style.overflow = prevOverflow;
this.showViewer = false;
}
}
};
</script>