summaryrefslogtreecommitdiff
path: root/packages/client/src/directives/get-size.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/client/src/directives/get-size.ts')
-rw-r--r--packages/client/src/directives/get-size.ts61
1 files changed, 41 insertions, 20 deletions
diff --git a/packages/client/src/directives/get-size.ts b/packages/client/src/directives/get-size.ts
index e3b5dea0f3..1fcd0718dc 100644
--- a/packages/client/src/directives/get-size.ts
+++ b/packages/client/src/directives/get-size.ts
@@ -1,34 +1,55 @@
import { Directive } from 'vue';
-export default {
- mounted(src, binding, vn) {
- const calc = () => {
- const height = src.clientHeight;
- const width = src.clientWidth;
+const mountings = new Map<Element, {
+ resize: ResizeObserver;
+ intersection?: IntersectionObserver;
+ fn: (w: number, h: number) => void;
+}>();
+
+function calc(src: Element) {
+ const info = mountings.get(src);
+ const height = src.clientHeight;
+ const width = src.clientWidth;
- // 要素が(一時的に)DOMに存在しないときは計算スキップ
- if (height === 0) return;
+ if (!info) return;
- binding.value(width, height);
- };
+ // アクティベート前などでsrcが描画されていない場合
+ if (!height) {
+ // IntersectionObserverで表示検出する
+ if (!info.intersection) {
+ info.intersection = new IntersectionObserver(entries => {
+ if (entries.some(entry => entry.isIntersecting)) calc(src);
+ });
+ }
+ info.intersection.observe(src);
+ return;
+ }
+ if (info.intersection) {
+ info.intersection.disconnect()
+ delete info.intersection;
+ };
- calc();
+ info.fn(width, height);
+};
- // Vue3では使えなくなった
- // 無くても大丈夫か...?
- // TODO: ↑大丈夫じゃなかったので解決策を探す
- //vn.context.$on('hook:activated', calc);
+export default {
+ mounted(src, binding, vn) {
- const ro = new ResizeObserver((entries, observer) => {
- calc();
+ const resize = new ResizeObserver((entries, observer) => {
+ calc(src);
});
- ro.observe(src);
+ resize.observe(src);
- src._get_size_ro_ = ro;
+ mountings.set(src, { resize, fn: binding.value, });
+ calc(src);
},
unmounted(src, binding, vn) {
binding.value(0, 0);
- src._get_size_ro_.unobserve(src);
+ const info = mountings.get(src);
+ if (!info) return;
+ info.resize.disconnect();
+ if (info.intersection) info.intersection.disconnect();
+ mountings.delete(src);
}
-} as Directive;
+} as Directive<Element, (w: number, h: number) => void>;