diff options
Diffstat (limited to 'packages/client/src/directives/get-size.ts')
| -rw-r--r-- | packages/client/src/directives/get-size.ts | 61 |
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>; |