Vue

by khamer

HTML

<div id="app">
  <looker :x="x" :y="y"></looker>
</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',
}

const Looker = {
	template: '<img class="cam" :src="src" alt="" />',
  props: ['x', 'y'],
  computed: {
  	src() {
	   	if (!this.$el) {
      	return imgs.load
      }
    	
      const { left, top, width, height } = this.$el.getBoundingClientRect()
      const relativeX = left + width/2 - this.x
      const relativeY = top + height/2 - this.y
            
      if (relativeX*relativeX + relativeY*relativeY > 40000) {
      	return imgs.load
      }
      if (relativeX*relativeX + relativeY*relativeY < 2500) {
      	return imgs.active
      }
      if (Math.abs(relativeX) > Math.abs(relativeY) && relativeX > 0) {
      	return imgs.e
      }
      if (Math.abs(relativeX) > Math.abs(relativeY) && relativeX < 0) {
      	return imgs.w
      }
      if (Math.abs(relativeX) < Math.abs(relativeY) && relativeY > 0) {
      	return imgs.s
      }
      if (Math.abs(relativeX) < Math.abs(relativeY) && relativeY < 0) {
      	return imgs.n
      }
    }
  }
}

new Vue({
	components: { Looker },
  el: "#app",
  data: {
    x: null,
    y: null,
  },
  created() {
	  addEventListener('mousemove', ({x, y}) => {
    	this.x = x
      this.y = y
    })
  },
})