smooth animation
Move an object while drawing a circle
by uto usui
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.3/TweenMax.min.js"></script>
<div class="target"></div>
<div class="ring"></div>
SCSS
body {
position: relative;
width: 100vw;
height: 100vh;
transform-style: preserve-3d;
perspective: 500px;
background-color: #E9EFFF;
}
.target {
width: 50px;
height: 50px;
background-color: #25ECB7;
transform-origin: 50% 50% 50%;
border-radius: 100%;
}
.ring {
position: absolute;
top: 50%;
left: 50%;
width: calc(100vw / 2 - 50px * 2 - 10px);
height: calc(100vw / 2 - 50px * 2 - 10px);
border: 1px solid #898FB2;
border-radius: 100%;
transform: translate(-50%, -50%);
}
Babel + JSX
class smoothMove {
/**
*
* @param target {Object}
* @param speed {Number}
* @param wrapWidth {Number}
* @param wrapHeight {Number}
*/
constructor(target, speed = 2, wrapWidth = window.innerWidth, wrapHeight = window.innerHeight) {
this.target = target;
// 角度
this.angle = 0;
// スピード
this.speed = speed;
// 中心の座標
this.center = {
x: wrapWidth / 2 - this.target.width() / 2,
y: wrapHeight / 2 - this.target.height() / 2
};
// 動く範囲を円の半径で表現
// この倍の値(直径)が移動範囲になる
this.radius = window.innerHeight / 4;
return this;
}
/**
* ラジアンに変換する
* @param angle
* @returns {number}
*/
getRadian(angle) {
return angle * Math.PI / 180;
}
/**
* アニメーションを始める
*/
play() {
let radian = this.getRadian(this.angle);
// Math.sin(radian)は-1から1までを正弦波で返す
// radiusをかけることでそれを半径とする円の範囲でアニメーション
let offsetX = Math.sin(radian) * this.radius;
let offsetY = Math.cos(radian) * this.radius;
TweenMax.set(this.target, {
x: this.center.x + offsetX,
y: this.center.y + offsetY,
});
// アニメーションで使用する角度を進める量
// つまり、速度
this.angle += this.speed;
requestAnimationFrame(() => {
this.play();
});
}
}
let anim = new smoothMove($('.target'));
anim.play();