首页 > 解决方案 > 翻译一个元素回到原点

问题描述

我试图在鼠标沿随机 340° 方向移动(不包括光标的 20°)时使元素移动,因此元素不会移动到光标,但是当我翻译时它总是回到原点,好像没有翻译。这是代码:

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>SVG</title>
</head>

<body>
    <svg id="m" width="40" height="40">
        <circle cx="20" cy="20" r="20" fill="red" stroke="red" stroke-width="1"/>
    </svg>
    
    <script>
let m = document.getElementById("m");
let angle = Math.floor(Math.random() * 340) * Math.PI / 180;
var timestamp, lastMouseX, lastMouseY = null;

let setCursorPosition = function(e) {

  //mousespeed
  if (timestamp === null) {
        timestamp = Date.now();
        lastMouseX = e.screenX;
        lastMouseY = e.screenY;
        return;
    }
    var now = Date.now();
    var dt =  now - timestamp;
    var dx = e.screenX - lastMouseX;
    var dy = e.screenY - lastMouseY;
    var speedX = Math.round(dx / dt * 100);
    var speedY = Math.round(dy / dt * 100);
    
    timestamp = now;
    lastMouseX = e.screenX;
    lastMouseY = e.screenY;
  //
  
  m.style.transform = "translate(" + Math.cos(angle)*speedX + "px," + Math.sin(angle)*speedY + "px)"; 
};

document.addEventListener("mousemove", e => setCursorPosition(e));
    </script> 
</body>

</html>

谢谢

也告诉我元素的方向的实现是不是和我想要的一样,我有一种感觉是不对的

标签: javascripthtmlcsstransform

解决方案


我不完全确定你在这里做什么,但我玩过你的代码,我想我让它按照你想要的方式运行。我注意到的第一件事(非常轻微)是这一行:

var timestamp, lastMouseX, lastMouseY = null;

应该:

var timestamp = null, lastMouseX = null, lastMouseY = null;

否则,您实际上并没有设置timestamplastMouseX最初。

更重要的是,您的元素继续返回其原点的原因是,当您减速鼠标时,它的鼠标输入非常小,speedX并且speedY在每次鼠标移动结束时设置为低值。

为了解决这个问题,我在你的转换命令之前添加了这一行:

if (Math.abs(speedX) < 40 && Math.abs(speedY) < 40) return;

另外,为了让运动更平滑一点,我还为您的事件监听器添加了一个油门,这样setCursorPosition就不会经常调用它(减少抖动运动),并且我在样式中添加了一个过渡。

function throttle(func, interval) {
    var lastCall = 0;
    return function() {
        let curTime = Date.now();
        if (lastCall + interval < curTime) {
            lastCall = curTime;
            return func.apply(this, arguments);
        }
    };
}   
      
document.addEventListener("mousemove", throttle(setCursorPosition, 20));
/* ^ replace original document.addEventListener() with this */
#m {
  transition: transform 140ms;
  margin: 200px; //just so I could always see it on the screen
}

我用于最小速度、油门和过渡的数字纯粹是实验性的,因此请随意根据自己的喜好使用它们。


推荐阅读