mirror of https://github.com/ElemeFE/element
Image: fix ssr and object-fit compatibility. (#15346)
* fix: Image is not defined during ssr Delay loadImage to mounted hook and add $isServer check * fix(image): simulate object-fit behavior to compatible with IE11 and other browsers which not suppor fix #15278 * fix: image inline-flex with overflow will still extend its parent elementpull/15178/head
parent
06dfe16ef6
commit
340da2ff61
|
@ -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 {};
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -7,11 +7,21 @@
|
|||
}
|
||||
|
||||
@include b(image) {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
|
||||
@include e(inner) {
|
||||
@extend %size;
|
||||
vertical-align: top;
|
||||
|
||||
@include m(center) {
|
||||
position: relative;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@include e(placeholder) {
|
||||
|
|
Loading…
Reference in New Issue