Browse Source

Hugely improve performance of selection and highlight indicators in builder preview

gh-pages
Andrew Kingston 5 years ago
parent
commit
686205ec4b
  1. 51
      packages/client/src/components/HoverIndicator.svelte
  2. 4
      packages/client/src/components/Indicator.svelte
  3. 7
      packages/client/src/components/SelectionIndicator.svelte
  4. 7
      packages/client/src/components/SettingsBar.svelte
  5. 12
      packages/client/src/utils/domDebounce.js

51
packages/client/src/components/HoverIndicator.svelte

@ -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}

4
packages/client/src/components/Indicator.svelte

@ -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};"
> >

7
packages/client/src/components/SelectionIndicator.svelte

@ -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>

7
packages/client/src/components/SettingsBar.svelte

@ -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>

12
packages/client/src/utils/domDebounce.js

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