perf(frontend): Reduce getting clientWidth in MkMediaImage (#11386)

* perf(frontend): Reduce getting clientWidth

* fix

* ✌️
This commit is contained in:
tamaina 2023-07-26 16:50:54 +09:00 committed by GitHub
parent dc452bf89a
commit bc927b8f75
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -22,6 +22,33 @@
</div> </div>
</template> </template>
<script lang="ts">
/**
* アスペクト比算出のためにHTMLElement.clientWidthを使うが
* 大変重たいのでコンテナ要素とメディアリスト幅のペアをキャッシュする
* タイムラインごとにスクロールコンテナが存在する前提だが
*/
const widthCache = new Map<Element, number>();
/**
* コンテナ要素がリサイズされたらキャッシュを削除する
*/
const ro = new ResizeObserver(entries => {
for (const entry of entries) {
widthCache.delete(entry.target);
}
});
function getClientWidthWithCache(targetEl: HTMLElement, containerEl: HTMLElement) {
if (widthCache.has(containerEl)) return widthCache.get(containerEl)!;
const width = targetEl.clientWidth;
widthCache.set(containerEl, width);
ro.observe(containerEl);
return width;
}
</script>
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, shallowRef } from 'vue'; import { onMounted, shallowRef } from 'vue';
import * as misskey from 'misskey-js'; import * as misskey from 'misskey-js';
@ -62,7 +89,8 @@ function calcAspectRatio() {
return; return;
} }
const width = gallery.value.clientWidth; if (!container.value) container.value = getScrollContainer(root.value);
const width = container.value ? getClientWidthWithCache(root.value, container.value) : root.value.clientWidth;
const heightMin = (ratio: number) => { const heightMin = (ratio: number) => {
const imgResizeRatio = width / img.properties.width; const imgResizeRatio = width / img.properties.width;
@ -84,7 +112,6 @@ function calcAspectRatio() {
gallery.value.style.height = heightMin(3 / 2); gallery.value.style.height = heightMin(3 / 2);
break; break;
default: { default: {
if (!container.value) container.value = getScrollContainer(root.value);
const maxHeight = Math.max(64, (container.value ? container.value.clientHeight : getBodyScrollHeight()) * 0.5 || 360); const maxHeight = Math.max(64, (container.value ? container.value.clientHeight : getBodyScrollHeight()) * 0.5 || 360);
if (width === 0 || !maxHeight) return; if (width === 0 || !maxHeight) return;
const imgResizeRatio = width / img.properties.width; const imgResizeRatio = width / img.properties.width;