Vue

by khamer

HTML

<div id="app">
  <img class="cam" :src="src" alt="">
</div>

CSS

html, body, #app {
    height: 100%;
}

#app {
  display: flex;
  justify-content: center;
  align-items: center;
}

.cam {
  max-width: 100vw;
  max-height: 100vh;
  height: auto;
}

Vue

const imgs = {
	active: 'https://i.imgur.com/dywrytN.jpg',
  load: 'https://i.imgur.com/bFgoucS.jpg',
  e: 'https://i.imgur.com/hFor71e.jpg',
  ne: 'https://i.imgur.com/JxcqY3a.jpg',
  n: 'https://i.imgur.com/QhDtoNE.jpg',
  s: 'https://i.imgur.com/uk9hP8K.jpg',
  nw: 'https://i.imgur.com/210YfND.jpg',
  se: 'https://i.imgur.com/pnmZ6Sz.jpg',
  sw: 'https://i.imgur.com/uPdC3HI.jpg',
  w: 'https://i.imgur.com/az8lnBJ.jpg',
}

new Vue({
  el: "#app",
  data: {
  	direction: 'load',
    x: null,
    y: null,
  },
  computed: {
  	src() {
    	return imgs[this.direction];
    },
  },
  created() {
	  addEventListener('mousemove', ({x, y}) => {
    	const rX = x - innerWidth / 2;
      const rY = y - innerHeight / 2;
      let a = Math.atan(rY/rX) + (rX < 0 ? Math.PI : 0);
      if (a < 0) {
      	a += 2 * Math.PI;
      }
      a = a * 180 / Math.PI + 22.5;
      
      if (Math.abs(rX) < 50 && Math.abs(rY) < 50) {
      	this.direction = 'active'
        return;
      }
      
      if (a < 45) {
      	this.direction = 'e'
      } else if (a < 90) {
      	this.direction = 'se'
      } else if (a < 135) {
      	this.direction = 's'
      } else if (a < 180) {
      	this.direction = 'sw'
      } else if (a < 225) {
      	this.direction = 'w'
      } else if (a < 270) {
      	this.direction = 'nw'
      } else if (a < 315) {
      	this.direction = 'n'
      } else if (a < 360) {
      	this.direction = 'ne'
      } else {
      	this.direction = 'e'
      }
    })
  },
})