127 lines
2.5 KiB
Vue
127 lines
2.5 KiB
Vue
<script setup>
|
|
import { computed } from "vue"
|
|
|
|
const props = defineProps({
|
|
rect: {
|
|
type: Object,
|
|
required: true
|
|
},
|
|
allowInteraction: {
|
|
type: Boolean,
|
|
default: true
|
|
}
|
|
})
|
|
|
|
const overlayStyle = computed(() => {
|
|
|
|
if (!props.rect) return null;
|
|
|
|
const { top, left, width, height } = props.rect
|
|
|
|
return {
|
|
top: {
|
|
top: 0,
|
|
left: 0,
|
|
width: '100vw',
|
|
height: `${top}px`
|
|
},
|
|
left: {
|
|
top: `${top}px`,
|
|
left: 0,
|
|
width: `${left}px`,
|
|
height: `${height}px`
|
|
},
|
|
right: {
|
|
top: `${top}px`,
|
|
left: `${left+width}px`,
|
|
width: `calc(100vw - ${left+width}px)`,
|
|
height: `${height}px`
|
|
},
|
|
bottom: {
|
|
top: `${top+height}px`,
|
|
left: 0,
|
|
width: "100vw",
|
|
height: `calc(100vh - ${top+height}px)`
|
|
},
|
|
highlight: {
|
|
top: `${top}px`,
|
|
left: `${left}px`,
|
|
width: `${width}px`,
|
|
height: `${height}px`
|
|
},
|
|
}
|
|
})
|
|
</script>
|
|
|
|
|
|
<template>
|
|
|
|
<Teleport to="body">
|
|
<Transition name="tour-fade">
|
|
<div v-if="rect && overlayStyle">
|
|
<div
|
|
class="tour-mask"
|
|
:style="overlayStyle.top"
|
|
/>
|
|
<div
|
|
class="tour-mask"
|
|
:style="overlayStyle.left"
|
|
/>
|
|
<div
|
|
class="tour-mask"
|
|
:style="overlayStyle.right"
|
|
/>
|
|
<div
|
|
class="tour-mask"
|
|
:style="overlayStyle.bottom"
|
|
/>
|
|
<div
|
|
class="tour-highlight"
|
|
:style="overlayStyle.highlight"
|
|
/>
|
|
<div
|
|
v-if="!allowInteraction"
|
|
class="tour-blocker"
|
|
/>
|
|
</div>
|
|
</Transition>
|
|
</Teleport>
|
|
|
|
</template>
|
|
|
|
|
|
<style scoped>
|
|
.tour-mask {
|
|
position: fixed;
|
|
z-index: 9998;
|
|
background: rgba(0,0,0,.55);
|
|
pointer-events: auto;
|
|
}
|
|
|
|
.tour-blocker {
|
|
position: fixed;
|
|
inset: 0;
|
|
z-index: 9998;
|
|
background: transparent;
|
|
pointer-events: auto;
|
|
}
|
|
|
|
.tour-highlight {
|
|
position: fixed;
|
|
z-index: 9998;
|
|
border: 2px solid white;
|
|
border-radius: 8px;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.tour-fade-enter-active,
|
|
.tour-fade-leave-active {
|
|
transition: opacity .2s;
|
|
}
|
|
|
|
.tour-fade-enter-from,
|
|
.tour-fade-leave-to {
|
|
opacity: 0;
|
|
}
|
|
</style>
|