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

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

@ -1,13 +1,17 @@
<script>
import { fade } from "svelte/transition"
export let top
export let left
export let width
export let height
export let text
export let color
export let transition = false
</script>
<div
in:fade={{ delay: transition ? 65 : 0, duration: transition ? 130 : 0 }}
class="indicator"
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 { builderStore } from "../store"
import Indicator from "./Indicator.svelte"
import { domDebounce } from "../utils/domDebounce"
let indicators = []
let interval
@ -29,13 +30,17 @@
}
indicators = newIndicators
}
const debouncedUpdate = domDebounce(updatePosition)
onMount(() => {
interval = setInterval(updatePosition, 100)
debouncedUpdate()
interval = setInterval(debouncedUpdate, 100)
document.addEventListener("scroll", debouncedUpdate, true)
})
onDestroy(() => {
clearInterval(interval)
document.removeEventListener("scroll", debouncedUpdate, true)
})
</script>

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

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