javascripthtmlcsstouch

Disable javascript (custom cursor) on touch devices


Is it possible to run a piece of JavaScript on mobile/tablet devices only? I'd like to do something a bit better than display: none and it makes sense to stop the script from running if it's not required.

Basically I have a custom cursor effect, that is only required when it follows the cursor on desktop with a mouse/trackpad.

This is the script I have:

var cursor = document.querySelector('.cursor-outer');
var cursorinner = document.querySelector('.cursor');
var a = document.querySelectorAll('a');
 
var moveCursor = true;
var radiusOfCursor = parseInt(getComputedStyle(cursor).getPropertyValue('width')) / 2; // radiusOfCursor = (width_of_cursor / 2).
     
document.addEventListener('mousemove', function (e) {
  var x = e.clientX;
  var y = e.clientY;
  cursorinner.style.left = x + 'px';
  cursorinner.style.top = y + 'px';
  
  if (!moveCursor) return;
  
  cursor.style.marginLeft = `calc(${e.clientX}px - ${radiusOfCursor}px)`;
  cursor.style.marginTop = `calc(${e.clientY}px - ${radiusOfCursor}px)`; 
  
  moveCursor = false;
  
  setTimeout(() => {
    moveCursor = true;
  }, 32) // The wait time. I chose 95 because it seems to work just fine for me.
});
 
 /* Centre pointer after stopping */
 
function mouseMoveEnd() {
  cursor.style.marginLeft = `calc(${cursorinner.style.left} - ${radiusOfCursor}px)`;
  cursor.style.marginTop = `calc(${cursorinner.style.top} - ${radiusOfCursor}px)`;
}
 
var x;
document.addEventListener('mousemove', function() { 
  if (x) clearTimeout(x); 
  x = setTimeout(mouseMoveEnd, 10); 
}, false);
 
 /* End */
 
document.addEventListener('mousedown', function() {
  cursor.classList.add('click');
  cursorinner.classList.add('cursorinnerhover');
});
 
 document.addEventListener('mouseup', function() {
  cursor.classList.remove('click');
  cursorinner.classList.remove('cursorinnerhover');
 });
 
a.forEach(item => {
  item.addEventListener('mouseover', () => {
    cursor.classList.add('hover');
  });
  item.addEventListener('mouseleave', () => {
    cursor.classList.remove('hover');
  });
});
 
a.forEach((item) => {
  const interaction = item.dataset.interaction;
  
  item.addEventListener("mouseover", () => {
    cursorinner.classList.add(interaction);
  });
  item.addEventListener("mouseleave", () => {
    cursorinner.classList.remove(interaction);
  });
});
* {
  cursor: none;
}

.cursor-outer {
    border: 2px solid black;
    border-radius: 100%;
    box-sizing: border-box;
    height: 32px;
    pointer-events: none;
    position: fixed;
        top: 16px;
        left: 16px;
      transform: translate(-50%, -50%);
        transition: height .12s ease-out, margin .12s ease-out, opacity .12s ease-out, width .12s ease-out;
    width: 32px;
    z-index: 100;
}

.cursor {
    background-color: black;
    border-radius: 100%;
    height: 4px;
    opacity: 1;
    position: fixed;
    transform: translate(-50%, -50%);
    pointer-events: none;
    transition: height .12s, opacity .12s, width .12s;
    width: 4px;
    z-index: 100;
}
<div class="cursor-outer"></div>
<div class="cursor"></div>


Solution

  • Option #1

    You can use something similar to this to determine if a device is touch-enabled:

    isTouchDevice = () => {
      return ( 'ontouchstart' in window ) ||
        ( navigator.maxTouchPoints > 0 ) ||
        ( navigator.msMaxTouchPoints > 0 );
    };
    

    This is adapted from Patrick H. Lauke's Detecting touch article on Mozilla.

    Then just: if (isTouchDevice()) { /* Do touch screen stuff */}

    Option #2

    But maybe a pure CSS approach could work better in your situation, like:

    @media (hover: none) {
     .cursor {
        pointer-events: none;
      }
    }
    

    Option #3

    If you don't mind using a third-party library, then Modernizr is really great for detecting things like this in the user's environment. Specifically, Modernizr.pointerevents will confirm if touchscreen is being used.