Skip to content

Commit

Permalink
fix(image): perf fix for safari when scrolling large number of images
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinlee11 committed Dec 8, 2023
1 parent b853e20 commit 4c31136
Showing 1 changed file with 27 additions and 6 deletions.
33 changes: 27 additions & 6 deletions src/components/Image/src/Image.vue
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ export default {
throttledResizeHandler: throttle(this.getImageDimensions, THROTTLE_DELAY),
height: 0,
width: 0,
getImageDimensionsFnAttemptsLeft: 20,
getImageDimensionsTimeout: undefined,
};
},
Expand Down Expand Up @@ -201,11 +203,28 @@ export default {
this.load();
}
this.getImageDimensions();
// Safari seems to really struggle with getImageDimensions, specifically calling
// offsetHeight/offsetWidth which triggers a style recalculation. If you're
// scrolling a list that has images, it just causes the main thread to get frozen.
// Let's try and preload those values before the image is actually loaded.
const timeoutValue = 100;
const getImageDimensionsFn = () => {
this.getImageDimensions();
// Just to ensure we don't have an infinite loop
this.getImageDimensionsFnAttemptsLeft -= 1;
if (this.getImageDimensionsFnAttemptsLeft === 0) {
return;
}
if (!this.height || !this.width) {
this.getImageDimensionsTimeout = setTimeout(getImageDimensionsFn, timeoutValue);
}
};
this.$nextTick(getImageDimensionsFn);
},
beforeDestroy() {
observer?.unwatch(this.$el);
clearTimeout(this.getImageDimensionsTimeout);
},
methods: {
Expand All @@ -214,8 +233,8 @@ export default {
},
getImageDimensions() {
this.height = this.$el?.offsetHeight || '0';
this.width = this.$el?.offsetWidth || '0';
this.height = this.$el?.offsetHeight || 0;
this.width = this.$el?.offsetWidth || 0;
},
afterEnter() {
Expand All @@ -224,9 +243,11 @@ export default {
onLoaded() {
this.loaded = true;
// We can't get the proper height of the image until after the DOM has been updated
// The image will otherwise be hidden, and the offsetHeight will be 0
this.$nextTick(() => this.getImageDimensions());
if (!this.height || !this.width) {
// We can't get the proper height of the image until after the DOM has been updated
// The image will otherwise be hidden, and the offsetHeight will be 0
this.$nextTick(() => this.getImageDimensions());
}
},
},
};
Expand Down

0 comments on commit 4c31136

Please sign in to comment.