I’m trying remake a javascript code for collision detection in Vue.js

Introduction I am new to Vue.js and I am currently working on my college project which requires collision detection in Vue.js.

Here is the code pen link of the working code: https://codepen.io/dropinks/pen/MrzPXB

I am trying to do the same in vue.js. But I am getting a ReferenceError ‘document is not defined’

Here is a impletmentation what i did:

templete code:

        <div class="container">
            <div class="rectangle-1" id="rect">Hover Me </div>
            <div class="rectangle-2" id="dragMe">Drag Me</div>
          </div>

script :

<script>
export default {
data:{
  dragMe: '',
  rect:''
},

created:function(){
  this.myFunction()
},
methods:{
myFunction:function(){
  rect = document.getElementById("rect");
  dragMe = document.getElementById("dragMe");
  
  initDrag({
    element: dragMe,
    drag: function(){isCollapsed(dragMe, rect);},
  });
},

isCollapsed: function(dragMe, rect){
  var object_1 = dragMe.getBoundingClientRect();
  var object_2 = rect.getBoundingClientRect();
  
  if (object_1.left < object_2.left + object_2.width  && object_1.left + object_1.width  > object_2.left &&
        object_1.top < object_2.top + object_2.height && object_1.top + object_1.height > object_2.top) {
    rect.classList.add("collide");
  }
  else{
    rect.classList.remove("collide");
  }
},



initDrag: function(options){
  var element = options.element;
  var mousedown, mouseup, mousemove,
      dragStart, initX, initY,
      offsetLeft, offsetTop;
  
  function mouseMove(ev){
    if(dragStart){
      var newX = offsetLeft + (ev.pageX - initX);
      var newY = offsetTop + (ev.pageY - initY);

      element.style.top = newY+"px";
      element.style.left = newX+"px";
      
      options.drag.call();
    }
  }
  
  function mouseUp(ev){
    dragStart = false;
    document.removeEventListener("mousemove", mouseMove, false);
    document.removeEventListener("mouseup", mouseUp, false);
    
    options.stop.call();
  }
  
  function mouseDown(ev){
    initX = ev.pageX;
    initY = ev.pageY;
    dragStart = true;
    offsetLeft = element.offsetLeft;
    offsetTop = element.offsetTop;
    document.addEventListener("mousemove", function(ev){mouseMove(ev)}, false);
    document.addEventListener("mouseup", function(ev){mouseUp(ev)}, false);
    
    options.start.call();
  }
  
  element.addEventListener("mousedown", function(ev){mouseDown(ev)}, false);
}
}
}
</script>


Here is an image of the error page from nuxt.js

Reference error: document not defined

Answer

The error you’re getting is because Nuxt has a server-side context where it’s trying to pre-fetch the data for you and pre-render it.

https://nuxtjs.org/docs/2.x/concepts/nuxt-lifecycle

What you need to do is ensure you’re running that code only on the client-side. I know this sounds confusing, but remember Nuxt is a universal framework, and it tries to render your site on the backend to improve your SEO and yield the initial markup. That’s why you’re getting the error.

What you can do is wrap the code that’s using the document in an if to make sure you’re only running it client-side

created:function(){
  if (process.client) {
      this.myFunction()
  }
},

The added complexity you’re facing is coming from Nuxt, and not Vue.JS 🙂

EDIT I’ve noticed a lot of mistakes in your question’s code, so if you could please correct them it would be nice! I’ve gone ahead and created an example CodeSanbox with a working solution to your problem which you can checkout. The problem I noticed are:

  • You have syntax error forgetting accessing this.dragMe and this.rect
  • You didn’t return an object in your data ( this is a very important one! )
  • the pasted code isn’t syntaxly correct

Having said all of that here is a working solution from CodeSandbox: https://codesandbox.io/s/zen-panini-n6j8c?file=/pages/index.vue