|
@@ -11,7 +11,8 @@
|
|
|
class="el-image__inner"
|
|
|
:src="src"
|
|
|
:alt="alt"
|
|
|
- :style="{ 'object-fit': fit }">
|
|
|
+ :style="imageStyle"
|
|
|
+ :class="{ 'el-image__inner--center': alignCenter }">
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
@@ -21,6 +22,16 @@
|
|
|
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'
|
|
|
+ };
|
|
|
+
|
|
|
export default {
|
|
|
name: 'ElImage',
|
|
|
|
|
@@ -38,24 +49,42 @@
|
|
|
return {
|
|
|
loading: true,
|
|
|
error: false,
|
|
|
- show: !this.lazy
|
|
|
+ show: !this.lazy,
|
|
|
+ imageWidth: 0,
|
|
|
+ imageHeight: 0
|
|
|
};
|
|
|
},
|
|
|
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
watch: {
|
|
|
- src: {
|
|
|
- handler(val) {
|
|
|
- this.show && this.loadImage(val);
|
|
|
- },
|
|
|
- immediate: true
|
|
|
+ src(val) {
|
|
|
+ this.show && this.loadImage();
|
|
|
},
|
|
|
show(val) {
|
|
|
- val && this.loadImage(this.src);
|
|
|
+ val && this.loadImage();
|
|
|
}
|
|
|
},
|
|
|
|
|
|
mounted() {
|
|
|
- this.lazy && this.addLazyLoadListener();
|
|
|
+ if (this.lazy) {
|
|
|
+ this.addLazyLoadListener();
|
|
|
+ } else {
|
|
|
+ this.loadImage();
|
|
|
+ }
|
|
|
},
|
|
|
|
|
|
beforeDestroy() {
|
|
@@ -63,17 +92,21 @@
|
|
|
},
|
|
|
|
|
|
methods: {
|
|
|
- loadImage(val) {
|
|
|
+ loadImage() {
|
|
|
+ if (this.$isServer) return;
|
|
|
+
|
|
|
// reset status
|
|
|
this.loading = true;
|
|
|
this.error = false;
|
|
|
|
|
|
const img = new Image();
|
|
|
- img.onload = this.handleLoad.bind(this);
|
|
|
+ img.onload = e => this.handleLoad(e, img);
|
|
|
img.onerror = this.handleError.bind(this);
|
|
|
- img.src = val;
|
|
|
+ img.src = this.src;
|
|
|
},
|
|
|
- handleLoad(e) {
|
|
|
+ handleLoad(e, img) {
|
|
|
+ this.imageWidth = img.width;
|
|
|
+ this.imageHeight = img.height;
|
|
|
this.loading = false;
|
|
|
this.$emit('load', e);
|
|
|
},
|
|
@@ -117,6 +150,36 @@
|
|
|
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 {};
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
};
|