Skip to content

Commit b140aa7

Browse files
committed
feat(highlighter): auto update position/size (30fps)
1 parent ac45d1a commit b140aa7

4 files changed

Lines changed: 105 additions & 8 deletions

File tree

packages/app-backend-core/src/highlighter.ts

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { isBrowser } from '@vue-devtools/shared-utils'
22
import { BackendContext } from '@vue-devtools/app-backend-api'
3+
import { ComponentBounds } from '@vue/devtools-api'
34
import { JobQueue } from './util/queue'
45

56
let overlay: HTMLDivElement
67
let overlayContent: HTMLDivElement
8+
let currentInstance
79

810
function createOverlay () {
911
if (overlay || !isBrowser) return
@@ -64,31 +66,46 @@ export async function highlight (instance, ctx: BackendContext) {
6466
size.appendChild(multiply)
6567
size.appendChild(document.createTextNode((Math.round(bounds.height * 100) / 100).toString()))
6668

69+
currentInstance = instance
70+
6771
await showOverlay(bounds, [pre, text, post, size])
6872
}
73+
74+
startUpdateTimer(ctx)
6975
})
7076
}
7177

7278
export async function unHighlight () {
7379
await jobQueue.queue(async () => {
7480
overlay?.parentNode?.removeChild(overlay)
7581
overlayContent?.parentNode?.removeChild(overlayContent)
82+
currentInstance = null
83+
84+
stopUpdateTimer()
7685
})
7786
}
7887

79-
function showOverlay ({ width = 0, height = 0, top = 0, left = 0 }, children: Node[] = []) {
88+
function showOverlay (bounds: ComponentBounds, children: Node[] = null) {
8089
if (!isBrowser || !children.length) return
8190

82-
overlay.style.width = Math.round(width) + 'px'
83-
overlay.style.height = Math.round(height) + 'px'
84-
overlay.style.left = Math.round(left) + 'px'
85-
overlay.style.top = Math.round(top) + 'px'
91+
positionOverlay(bounds)
8692
document.body.appendChild(overlay)
8793

8894
overlayContent.innerHTML = ''
8995
children.forEach(child => overlayContent.appendChild(child))
9096
document.body.appendChild(overlayContent)
9197

98+
positionOverlayContent(bounds)
99+
}
100+
101+
function positionOverlay ({ width = 0, height = 0, top = 0, left = 0 }) {
102+
overlay.style.width = Math.round(width) + 'px'
103+
overlay.style.height = Math.round(height) + 'px'
104+
overlay.style.left = Math.round(left) + 'px'
105+
overlay.style.top = Math.round(top) + 'px'
106+
}
107+
108+
function positionOverlayContent ({ wifth = 0, height = 0, top = 0, left = 0 }) {
92109
// Content position (prevents overflow)
93110
const contentWidth = overlayContent.offsetWidth
94111
const contentHeight = overlayContent.offsetHeight
@@ -110,3 +127,35 @@ function showOverlay ({ width = 0, height = 0, top = 0, left = 0 }, children: No
110127
overlayContent.style.left = ~~contentLeft + 'px'
111128
overlayContent.style.top = ~~contentTop + 'px'
112129
}
130+
131+
async function updateOverlay (ctx: BackendContext) {
132+
if (currentInstance) {
133+
const bounds = await ctx.api.getComponentBounds(currentInstance)
134+
if (bounds) {
135+
const sizeEl = overlayContent.children.item(3)
136+
console.log(sizeEl)
137+
const widthEl = sizeEl.childNodes[0] as unknown as Text
138+
widthEl.textContent = (Math.round(bounds.width * 100) / 100).toString()
139+
const heightEl = sizeEl.childNodes[2] as unknown as Text
140+
heightEl.textContent = (Math.round(bounds.height * 100) / 100).toString()
141+
142+
positionOverlay(bounds)
143+
positionOverlayContent(bounds)
144+
}
145+
}
146+
}
147+
148+
let updateTimer
149+
150+
function startUpdateTimer (ctx: BackendContext) {
151+
stopUpdateTimer()
152+
updateTimer = setInterval(() => {
153+
jobQueue.queue(async () => {
154+
await updateOverlay(ctx)
155+
})
156+
}, 1000 / 30) // 30fps
157+
}
158+
159+
function stopUpdateTimer () {
160+
clearInterval(updateTimer)
161+
}

packages/app-backend-core/src/index.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,9 +217,7 @@ async function connect () {
217217
block: 'center',
218218
inline: 'center'
219219
})
220-
setTimeout(() => {
221-
highlight(instance, ctx)
222-
}, 500)
220+
highlight(instance, ctx)
223221
setTimeout(() => {
224222
unHighlight()
225223
}, 2000)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<script>
2+
import { onUnmounted, reactive, ref } from 'vue'
3+
4+
export default {
5+
setup () {
6+
const animate = ref(false)
7+
8+
const size = reactive({
9+
width: 10,
10+
height: 10
11+
})
12+
13+
const timer = setInterval(() => {
14+
if (!animate.value) return
15+
size.width = Math.round(Math.random() * 100)
16+
size.height = Math.round(Math.random() * 100)
17+
}, 1000)
18+
19+
onUnmounted(() => {
20+
clearInterval(timer)
21+
})
22+
23+
return {
24+
size,
25+
animate
26+
}
27+
}
28+
}
29+
</script>
30+
31+
<template>
32+
<div
33+
class="animation"
34+
:style="{
35+
width: `${size.width * 10}px`,
36+
height: `${size.height * 10}px`,
37+
}"
38+
@click="animate = !animate"
39+
/>
40+
</template>
41+
42+
<style lang="postcss" scoped>
43+
.animation {
44+
transition: all 1s linear;
45+
background: #42B983;
46+
}
47+
</style>

packages/shell-dev-vue3/src/App.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import SetupRender from './SetupRender.js'
1515
import Form from './Form.vue'
1616
import Heavy from './Heavy.vue'
1717
import Mixins from './Mixins.vue'
18+
import Animation from './Animation.vue'
1819
1920
import { h } from 'vue'
2021
@@ -38,6 +39,7 @@ export default {
3839
Form,
3940
Heavy,
4041
Mixins,
42+
Animation,
4143
inline: {
4244
render: () => h('h3', 'Inline component definition')
4345
}
@@ -78,6 +80,7 @@ export default {
7880
<AsyncComponent />
7981
<SuspenseExample />
8082
<Provide />
83+
<Animation />
8184
<Condition />
8285
<VModelExample />
8386
<Ghost />

0 commit comments

Comments
 (0)