JSFiddle - React, Tailwind, and code Playground
by skirtle
HTML
<script src="https://unpkg.com/[email protected]/dist/vue.global.js"></script>
<div id="app">
<my-eye></my-eye>
</div>
CSS
.wrapper {
width: 0;
height: 0;
position: fixed;
left: 50vw;
top: 50vh;
}
.box {
width: 100px;
height: 100px;
border: 2px solid #000;
position: relative;
left: -50px;
top: -50px;
}
.inner-box {
position: absolute;
top: 0;
bottom: 10px;
left: 0;
right: 10px;
}
.circle {
background: #009;
border-radius: 5px;
position: absolute;
height: 10px;
width: 10px;
margin-right: -10px;
}
JavaScript
const MyEye = {
template: `
<div class="wrapper">
<div class="box">
<div class="inner-box">
<div class="circle" :style="styles" />
</div>
</div>
</div>
`,
data () {
return {
x: 0,
y: 0,
viewportHeight: 1,
viewportWidth: 1
}
},
created () {
this.updateViewportSize()
},
mounted () {
document.addEventListener('mousemove', this.onMouseMove)
window.addEventListener('resize', this.updateViewportSize)
},
unmounted () {
document.removeEventListener('mousemove', this.onMouseMove)
window.removeEventListener('resize', this.updateViewportSize)
},
computed: {
styles () {
return {
left: percent(this.x, this.viewportWidth),
top: percent(this.y, this.viewportHeight)
}
function percent (value, total) {
return Math.round((value * 100 / total)) + '%'
}
}
},
methods: {
onMouseMove (ev) {
this.x = ev.clientX
this.y = ev.clientY
},
updateViewportSize () {
this.viewportHeight = window.innerHeight
this.viewportWidth = window.innerWidth
}
}
}
Vue.createApp({
components: {
MyEye
}
}).mount('#app')