Skip to content

Commit 7eeb1e8

Browse files
SimonaliaChenFAKER-A
authored andcommitted
Image: fix ssr and object-fit compatibility. (ElemeFE#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 ElemeFE#15278 * fix: image inline-flex with overflow will still extend its parent element
1 parent 17251fb commit 7eeb1e8

File tree

2 files changed

+86
-13
lines changed

2 files changed

+86
-13
lines changed

packages/image/src/main.vue

Lines changed: 76 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
class="el-image__inner"
1212
:src="src"
1313
:alt="alt"
14-
:style="{ 'object-fit': fit }">
14+
:style="imageStyle"
15+
:class="{ 'el-image__inner--center': alignCenter }">
1516
</div>
1617
</template>
1718

@@ -21,6 +22,16 @@
2122
import { isString, isHtmlElement } from 'element-ui/src/utils/types';
2223
import throttle from 'throttle-debounce/throttle';
2324
25+
const isSupportObjectFit = () => document.documentElement.style.objectFit !== undefined;
26+
27+
const ObjectFit = {
28+
NONE: 'none',
29+
CONTAIN: 'contain',
30+
COVER: 'cover',
31+
FILL: 'fill',
32+
SCALE_DOWN: 'scale-down'
33+
};
34+
2435
export default {
2536
name: 'ElImage',
2637
@@ -38,42 +49,64 @@
3849
return {
3950
loading: true,
4051
error: false,
41-
show: !this.lazy
52+
show: !this.lazy,
53+
imageWidth: 0,
54+
imageHeight: 0
4255
};
4356
},
4457
58+
computed: {
59+
imageStyle() {
60+
const { fit } = this;
61+
if (!this.$isServer && fit) {
62+
return isSupportObjectFit()
63+
? { 'object-fit': fit }
64+
: this.getImageStyle(fit);
65+
}
66+
return {};
67+
},
68+
alignCenter() {
69+
return !this.$isServer && !isSupportObjectFit() && this.fit !== ObjectFit.FILL;
70+
}
71+
},
72+
4573
watch: {
46-
src: {
47-
handler(val) {
48-
this.show && this.loadImage(val);
49-
},
50-
immediate: true
74+
src(val) {
75+
this.show && this.loadImage();
5176
},
5277
show(val) {
53-
val && this.loadImage(this.src);
78+
val && this.loadImage();
5479
}
5580
},
5681
5782
mounted() {
58-
this.lazy && this.addLazyLoadListener();
83+
if (this.lazy) {
84+
this.addLazyLoadListener();
85+
} else {
86+
this.loadImage();
87+
}
5988
},
6089
6190
beforeDestroy() {
6291
this.lazy && this.removeLazyLoadListener();
6392
},
6493
6594
methods: {
66-
loadImage(val) {
95+
loadImage() {
96+
if (this.$isServer) return;
97+
6798
// reset status
6899
this.loading = true;
69100
this.error = false;
70101
71102
const img = new Image();
72-
img.onload = this.handleLoad.bind(this);
103+
img.onload = e => this.handleLoad(e, img);
73104
img.onerror = this.handleError.bind(this);
74-
img.src = val;
105+
img.src = this.src;
75106
},
76-
handleLoad(e) {
107+
handleLoad(e, img) {
108+
this.imageWidth = img.width;
109+
this.imageHeight = img.height;
77110
this.loading = false;
78111
this.$emit('load', e);
79112
},
@@ -117,6 +150,36 @@
117150
off(_scrollContainer, 'scroll', _lazyLoadHandler);
118151
this._scrollContainer = null;
119152
this._lazyLoadHandler = null;
153+
},
154+
/**
155+
* simulate object-fit behavior to compatible with IE11 and other browsers which not support object-fit
156+
*/
157+
getImageStyle(fit) {
158+
const { imageWidth, imageHeight } = this;
159+
const {
160+
clientWidth: containerWidth,
161+
clientHeight: containerHeight
162+
} = this.$el;
163+
164+
if (!imageWidth || !imageHeight || !containerWidth || !containerHeight) return {};
165+
166+
const vertical = imageWidth / imageHeight < 1;
167+
168+
if (fit === ObjectFit.SCALE_DOWN) {
169+
const isSmaller = imageWidth < containerWidth && imageHeight < containerHeight;
170+
fit = isSmaller ? ObjectFit.NONE : ObjectFit.CONTAIN;
171+
}
172+
173+
switch (fit) {
174+
case ObjectFit.NONE:
175+
return { width: 'auto', height: 'auto' };
176+
case ObjectFit.CONTAIN:
177+
return vertical ? { width: 'auto' } : { height: 'auto' };
178+
case ObjectFit.COVER:
179+
return vertical ? { height: 'auto' } : { width: 'auto' };
180+
default:
181+
return {};
182+
}
120183
}
121184
}
122185
};

packages/theme-chalk/src/image.scss

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,21 @@
77
}
88

99
@include b(image) {
10+
position: relative;
1011
display: inline-block;
12+
overflow: hidden;
1113

1214
@include e(inner) {
1315
@extend %size;
1416
vertical-align: top;
17+
18+
@include m(center) {
19+
position: relative;
20+
top: 50%;
21+
left: 50%;
22+
transform: translate(-50%, -50%);
23+
display: block;
24+
}
1525
}
1626

1727
@include e(placeholder) {

0 commit comments

Comments
 (0)