前編に続き、
を、考察していきます。プロジェクト1選目は、下記リンクにて確認できます。
#getBoundingClientRect()
任意の要素の大きさ(height,width)と、ビューポートに対する位置を返す。
#clientX clientY
イベント発生時のマウスの座標を返す。
このプロジェクトではmousemove
イベントが発生した時にカーソルの位置を取得しています。
// Mouse position
const useMousePosition = () => {
const [position, setPosition] = useState({ x: 0, y: 0 });
useEffect(() => {
const setFromEvent = e => setPosition({ x: e.clientX, y: e.clientY });
window.addEventListener("mousemove", setFromEvent);
return () => {
window.removeEventListener("mousemove", setFromEvent);
};
}, []);
return position;
};
#Math.atan2(y,x)
指定した座標を元に平面上の角度を取得できる。第1引数にy座標、第2引数にx座標を指定するのに注意。このプロジェクトでは上記のgetBoundingClientRect
とclientX clientY
で取得した座標を元に、画面右下のマウスをキャッチしてくるおじさんから角度を計算しています。
const Grabber = ({ state, gameOver, extended, onCursorGrabbed }) => {
const mousePos = useMousePosition();
const [ref, position] = usePosition();
const hasCursor = false;
// Calculate rotation of armWrapper
const x = position.left + position.width * 0.5;
const y = position.top + position.height * 0.5;
const angle = gameOver ? 0 : Math.atan2(mousePos.x - x,-(mousePos.y - y)) * (180 / Math.PI);
// Ensure value is within acceptable range (-75 to 75)
const rotation = Math.min(Math.max(parseInt(angle), -79), 79);
const grabberClass = `grabber grabber--${state} ${extended && "grabber--extended"}`;
const wrapperStyle = { transform: `rotate(${rotation}deg)` };
let handImageSrc = ASSETS[state];
return (
<div className={grabberClass}>
<div className="grabber__body"></div>
<img className="grabber__face" src={ASSETS.head} />
<div className="grabber__arm-wrapper" ref={ref} style={wrapperStyle}>
<div className="grabber__arm">
<img
className="grabber__hand"
src={handImageSrc}
onMouseEnter={onCursorGrabbed}
/>
</div>
</div>
</div>
);
};
Math.atan2で計算した角度はラジアンなので、度数法に変換するために、(180 / Math.PI)
を乗じています。
ここまでは理解できたのですが、本来ならy座標を指定する第1引数にx座標、x座標を指定する第2引数にy座標を指定している点や、変数rotationの計算式で出てくる79
と-79
いう数字の意味が理解できませんでした。
どなたか解説頂けると幸いです。
#アウトプット
この前編、後編の考察で学んだことをアウトプットしてみました。
下のリンクをクリックすると柴犬をなでなでできると思うので、なでていってやってください。(スマホ対応してないです。)