元素上的 CSS 过渡更平滑

Smoother CSS transitions on element

const dot = document.querySelector( `.dot` ).style;

function getRandomInteger( min,max ) {
  min = Math.ceil( min );
  max = Math.floor( max );
  return Math.floor( Math.random() * ( max - min + 1 ) ) + min;
}

// use randomInteger for x and y values 
// for transform: translate( x%,y% )
// range here will be from negative integer 
// to positive integer. The CSS unit is a %
function move( element,range ) { 
  element.transform = 
    `
      translate( 
        ${ getRandomInteger( -range,range ) }%,
        ${ getRandomInteger( -range,range ) }%
      )
    ` 
}

//range here is 250 negative ad positive percent
setInterval( function() { move( dot,250 ) },500 );
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
html, body {
  overflow: hidden;
  height: 100%;
}
body {
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #eee;
}
.dot {
  border-style: none;
  border-radius: 50%;
  width: 2.5rem;
  height: 2.5rem;
  background-color: rgba( 0,0,0,0.5 );
  transition-property: transform;
  transition-duration: 2s;
  transition-timing-function: ease-in-out;
}
<hr class='dot'>

上面的代码将一个点移动到页面上的随机位置。

它按预期工作,除了从一个位置到另一个位置的转换。 目标 是每个动作之间更平滑的过渡。

最初的想法是通过类似于物体轻轻漂浮在水面上的微妙运动来创建漂浮或悬停效果。

我们在最后 CSS 行中使用 transition-timing-function: ease-in-out 来尝试减少上面方向变化的突然性。然而,将计时功能更改为任何值似乎并没有多大帮助。包括自定义 cubic-bezier 值。

怎样才能让动画变向不那么突然,整体动作更流畅?

您可以通过javascript创建一个包含关键帧的列表,并根据该列表创建一个新的动画。通过这种方式,您将避免 setInterval 并且浏览器将自行为您的元素设置动画。

如果你想要更流畅的运动,你应该使用更少的随机值并提供关键帧列表与窒息位置。

function getRandomInteger(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

const range = 200;
const steps = 50;

const keyframes = Array.apply(null, Array(50)).map(() => {
  return {
    transform: `translate(${getRandomInteger(-range, range)}%, ${getRandomInteger(-range, range)}%)`
  };
});

document.querySelector('.dot').animate(keyframes, {
  duration: steps * 500, // 0.5 sec for keyframe
  direction: 'alternate',
  fill: 'both',
  iterations: Infinity
});
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html,
body {
  overflow: hidden;
  height: 100%;
}

body {
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #eee;
}

.dot {
  border-style: none;
  border-radius: 50%;
  width: 2.5rem;
  height: 2.5rem;
  background-color: rgba( 0, 0, 0, 0.5);
}
<hr class='dot'>

如果您想实现真正平滑的运动,您应该删除随机化并使用一些数学函数来定义路径。这是基于利萨如曲线的示例,但您可以使用任何其他曲线。

function getLissajousCurve(radius, steps, a, b, d, A, B) {
  const result = [];
  for (let t = 0; t <= 2 * Math.PI; t += Math.PI / steps) {
    const x = radius * A * Math.sin(a * t + d);
    const y = radius * B * Math.sin(b * t);
    result.push([x, y]);
  }
  return result;
}

const steps = 50;

const curve = getLissajousCurve(200, steps, 4, 5, 0, 1, 1);

const keyframes = curve.map(([x, y]) => {
  return {
    transform: `translate(${x}%, ${y}%)`
  };
});

document.querySelector('.dot').animate(keyframes, {
  duration: steps * 500, // 0.5 sec for keyframe
  direction: 'alternate',
  fill: 'both',
  iterations: Infinity
});
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html,
body {
  overflow: hidden;
  height: 100%;
}

body {
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #eee;
}

.dot {
  border-style: none;
  border-radius: 50%;
  width: 2.5rem;
  height: 2.5rem;
  background-color: rgba( 0, 0, 0, 0.5);
}
<hr class='dot'>