Search code examples
javascripthtmlcsstransformationonmouseclick

Start CSS transformation at mouse position


I simply want the transformation to start at the clicked mouse position.

It does not work (as I expected). Why not and what should I change?

var x, y;
const hint = document.getElementById('hint');
const pageOverlay = document.getElementById('pageOverlay');

document.addEventListener("DOMContentLoaded", () => {

  document.addEventListener("click", (e) => {
    console.info('clicked at ' + x + ', ' + y);
    hide(hint);
    expand(pageOverlay);
  });

  document.onmousemove = function (e) {
    x = e.clientX;
    y = e.clientY;
  };
});

function hide(elm) {
  elm.setAttribute("style", "visibility: hidden; opacity: 0");
}

function expand(elm) {
  elm.setAttribute("style", 
   "transform-origin:" + x + "px " + y + "px;" +
   "visibility: visible;" +
   "opacity: 1;" +
   "transform: scale(1)");
}
.pageOverlay {
  position: fixed;
  z-index: 1000;
  left: 0;
  top: 0;
  width: 100vw;
  height: 100vh;
  background: lightblue; 
  opacity: 0;
  visibility: hidden;  
  transition: 0.8s linear;
  transform: scale(.2);
}
<span id="hint">Click somewhere!<br/><br/>
 I want/expect the transformation to start at the mouse position.</span>
 
 <div id="pageOverlay" class="pageOverlay">
  <h1>Overlay</h1> 
 </div>

Codepen: https://codepen.io/r-w-c/pen/jOoPRBY


Solution

  • OK, so I don't understand exactly what you want, but I think I got an idea of it. The issue persists because you're not only animating the scale effect, but also the re-positioning of the element. By changing your transition property to transition: transform 0.8s linear;, the overlay will move instantly and then start expanding.

    var x, y;
    const hint = document.getElementById('hint');
    const pageOverlay = document.getElementById('pageOverlay');
    
    document.addEventListener("DOMContentLoaded", () => {
    
      document.addEventListener("click", (e) => {
        console.info('clicked at ' + x + ', ' + y);
        hide(hint);
        expand(pageOverlay);
      });
    
      document.onmousemove = function (e) {
        x = e.clientX;
        y = e.clientY;
      };
    });
    
    function hide(elm) {
      elm.setAttribute("style", "visibility: hidden; opacity: 0");
    }
    
    function expand(elm) {
      elm.setAttribute("style", 
       "transform-origin:" + x + "px " + y + "px;" +
       "visibility: visible;" +
       "opacity: 1;" +
       "transform: scale(1)");
    }
    .pageOverlay {
      position: fixed;
      z-index: 1000;
      left: 0;
      top: 0;
      width: 100vw;
      height: 100vh;
      background: lightblue; 
      opacity: 0;
      visibility: hidden;  
      transition: transform 0.8s linear;
      transform: scale(.2);
    }
    <span id="hint">Click somewhere!<br/><br/>
     I want/expect the transformation to start at the mouse position.</span>
     
     <div id="pageOverlay" class="pageOverlay">
      <h1>Overlay</h1> 
     </div>