Hugely improve performance of selection and highlight indicators in builder preview

This commit is contained in:
Andrew Kingston 2021-06-10 09:05:08 +01:00
parent 5911065da4
commit 686205ec4b
5 changed files with 60 additions and 21 deletions

View File

@ -2,6 +2,7 @@
import { onMount, onDestroy } from "svelte" import { onMount, onDestroy } from "svelte"
import { builderStore } from "../store" import { builderStore } from "../store"
import Indicator from "./Indicator.svelte" import Indicator from "./Indicator.svelte"
import { domDebounce } from "../utils/domDebounce"
let indicators = [] let indicators = []
let interval let interval
@ -34,11 +35,17 @@
indicators = newIndicators indicators = newIndicators
} }
const debouncedUpdate = domDebounce(updatePosition)
const onMouseOver = e => { const onMouseOver = e => {
const element = e.target.closest("[data-type='component']") const element = e.target.closest("[data-type='component']")
componentId = element?.dataset?.id const newId = element?.dataset?.id
componentName = element?.dataset?.name const newName = element?.dataset?.name
if (newId !== componentId) {
componentId = newId
componentName = newName
debouncedUpdate()
}
} }
const onMouseLeave = () => { const onMouseLeave = () => {
@ -47,27 +54,33 @@
} }
onMount(() => { onMount(() => {
interval = setInterval(updatePosition, 100) debouncedUpdate()
window.addEventListener("mouseover", onMouseOver) interval = setInterval(debouncedUpdate, 100)
document.documentElement.addEventListener("mouseleave", onMouseLeave) document.addEventListener("mouseover", onMouseOver)
document.addEventListener("mouseleave", onMouseLeave)
document.addEventListener("scroll", debouncedUpdate, true)
}) })
onDestroy(() => { onDestroy(() => {
clearInterval(interval) clearInterval(interval)
window.removeEventListener("mouseover", onMouseOver) document.removeEventListener("mouseover", onMouseOver)
document.documentElement.removeEventListener("mouseleave", onMouseLeave) document.removeEventListener("mouseleave", onMouseLeave)
document.removeEventListener("scroll", debouncedUpdate, true)
}) })
</script> </script>
{#if componentId !== $builderStore.selectedComponentId} {#key componentId}
{#each indicators as indicator, idx} {#if componentId !== $builderStore.selectedComponentId}
<Indicator {#each indicators as indicator, idx}
top={indicator.top} <Indicator
left={indicator.left} top={indicator.top}
width={indicator.width} left={indicator.left}
height={indicator.height} width={indicator.width}
text={idx === 0 ? componentName : null} height={indicator.height}
color="rgb(120, 170, 244)" text={idx === 0 ? componentName : null}
/> color="rgb(120, 170, 244)"
{/each} transition
{/if} />
{/each}
{/if}
{/key}

View File

@ -1,13 +1,17 @@
<script> <script>
import { fade } from "svelte/transition"
export let top export let top
export let left export let left
export let width export let width
export let height export let height
export let text export let text
export let color export let color
export let transition = false
</script> </script>
<div <div
in:fade={{ delay: transition ? 65 : 0, duration: transition ? 130 : 0 }}
class="indicator" class="indicator"
style="top: {top}px; left: {left}px; width: {width}px; height: {height}px; --color: {color};" style="top: {top}px; left: {left}px; width: {width}px; height: {height}px; --color: {color};"
> >

View File

@ -2,6 +2,7 @@
import { onMount, onDestroy } from "svelte" import { onMount, onDestroy } from "svelte"
import { builderStore } from "../store" import { builderStore } from "../store"
import Indicator from "./Indicator.svelte" import Indicator from "./Indicator.svelte"
import { domDebounce } from "../utils/domDebounce"
let indicators = [] let indicators = []
let interval let interval
@ -29,13 +30,17 @@
} }
indicators = newIndicators indicators = newIndicators
} }
const debouncedUpdate = domDebounce(updatePosition)
onMount(() => { onMount(() => {
interval = setInterval(updatePosition, 100) debouncedUpdate()
interval = setInterval(debouncedUpdate, 100)
document.addEventListener("scroll", debouncedUpdate, true)
}) })
onDestroy(() => { onDestroy(() => {
clearInterval(interval) clearInterval(interval)
document.removeEventListener("scroll", debouncedUpdate, true)
}) })
</script> </script>

View File

@ -2,6 +2,7 @@
import { onMount, onDestroy } from "svelte" import { onMount, onDestroy } from "svelte"
import SettingsButton from "./SettingsButton.svelte" import SettingsButton from "./SettingsButton.svelte"
import { builderStore } from "../store" import { builderStore } from "../store"
import { domDebounce } from "../utils/domDebounce"
const verticalOffset = 28 const verticalOffset = 28
const horizontalOffset = 2 const horizontalOffset = 2
@ -63,13 +64,17 @@
measured = true measured = true
} }
} }
const debouncedUpdate = domDebounce(updatePosition)
onMount(() => { onMount(() => {
interval = setInterval(updatePosition, 100) debouncedUpdate()
interval = setInterval(debouncedUpdate, 100)
document.addEventListener("scroll", debouncedUpdate, true)
}) })
onDestroy(() => { onDestroy(() => {
clearInterval(interval) clearInterval(interval)
document.removeEventListener("scroll", debouncedUpdate, true)
}) })
</script> </script>

View File

@ -0,0 +1,12 @@
export const domDebounce = callback => {
let active = false
return e => {
if (!active) {
window.requestAnimationFrame(() => {
callback(e)
active = false
})
active = true
}
}
}