Vrda's picture
Deploy Learn Pathophysiology WC3 Edition
8b9f7d9
<script setup lang="ts">
import { computed, getCurrentInstance, onMounted, onUnmounted, PropType, ref } from 'vue';
import { getAssetUrl } from '../utils';
import { useConfig } from '../ConfigProvider';
type CursorState =
| 'default'
| 'default-active'
| 'pointer'
| 'pointer-active'
| 'pointer-denied'
| 'hold'
| 'arrow-top'
| 'arrow-right'
| 'arrow-bottom'
| 'arrow-left'
const props = defineProps({
state: {
type: String as PropType<CursorState>,
default: () => 'default',
},
// color: { // TODO: Finish this feature (its hard to mix color and sprites with alpha via css)
// type: String,
// default: () => '#0000',
// }
});
const {theme} = useConfig();
const cursorEl = ref<HTMLElement | null>(null);
const cursorPlaceEl = ref<HTMLElement | null>(null);
const spriteUrl = computed(() => getAssetUrl('cursor.png', theme.value));
function moveCursor(e: MouseEvent) {
if(!cursorEl.value) return;
cursorEl.value.style.transform = `translate(${e.pageX}px, ${e.pageY}px)`;
}
onMounted(() => {
cursorPlaceEl.value = getCurrentInstance()?.proxy?.$el.parentElement;
if(!cursorPlaceEl?.value) {
throw new Error('[warcraft-3-ui]: Cursor - element from "to" prop not found or something went wrong')
}
cursorPlaceEl.value.addEventListener('mousemove', moveCursor);
cursorPlaceEl.value.classList.add('cursored');
})
onUnmounted(()=>{
if(cursorPlaceEl.value){
cursorPlaceEl.value.removeEventListener('mousemove', moveCursor);
cursorPlaceEl.value.classList.remove('cursored');
}
})
</script>
<template>
<div ref="cursorEl" class="cursor__container">
<div :class="`cursor cursor--${props.state}`" />
</div>
</template>
<style lang="scss">
$tile-size: 32px;
.cursored{
cursor: none;
& * {
cursor: none;
}
}
.cursor {
position: relative;
width: $tile-size;
height: $tile-size;
background: v-bind(spriteUrl) no-repeat;
// mix-blend-mode: color;
// border: 1px solid orange;
&__container {
top: 0;
left: 0;
position: fixed;
z-index: 99;
pointer-events: none;
// background-color: v-bind('props.color');
}
&--default-active {
animation: cursor-active 500ms steps(8) infinite;
}
&--pointer {
background-position: (-$tile-size * 1) (-$tile-size * 3);
}
&--pointer-active {
animation: cursor-pointer 500ms steps(8) infinite;
}
&--pointer-denied {
background-position: (-$tile-size * 2) (-$tile-size * 3);
}
&--hold {
background-position: (-$tile-size * 4) (-$tile-size * 3);
}
&--arrow-top {
animation: cursor-arrow 100ms steps(3) infinite;
transform: rotate(-90deg)
}
&--arrow-right {
animation: cursor-arrow 100ms steps(3) infinite;
}
&--arrow-bottom {
animation: cursor-arrow 100ms steps(3) infinite;
transform: rotate(90deg)
}
&--arrow-left {
animation: cursor-arrow 100ms steps(3) infinite;
transform: rotate(-180deg)
}
}
@keyframes cursor-active {
from { background-position: 0 0; }
to { background-position: (-$tile-size * 8) 0; }
}
@keyframes cursor-pointer {
from { background-position: 0 (-$tile-size * 2); }
to { background-position: (-$tile-size * 8) (-$tile-size * 2); }
}
@keyframes cursor-arrow {
from { background-position: (-$tile-size * 5) (-$tile-size * 3); }
to { background-position: (-$tile-size * 8) (-$tile-size * 3); }
}
</style>