개발
온라인 코인 토스 사이트 구현
어쩌다 동전던지기로 뭘 결정할일이 있어서 온라인 사이트에서 코인 토스를 구현한게 없을까 뒤적이다가 괜찮은게 없어서 이왕에 한번 만들어보자 결심하고 만든 기능이다.

코인을 클릭하면 코인토스를 실행할 수 있고, 자신이 실행한 코인토스 결과를 그 페이지 안에서 아래에 통계로써 기록해준다.
코인토스의 확률은 아래코드와 같이 자바스크립트에서 제공하는 Math rand 함수를 이용했다.
const newDeg = (() => {
const rand = Math.random() >= 0.5;
return currentDeg + 180 * flipCount + (rand ? 0 : 180);
})();
Copy
엄청난 난수가 아닌 실제 1/2 구분만 하면되고, 매번 클릭에 따른 요청 딜레이에 따라 충분히 랜덤값을 얻을 수 있어 간단하게 구현할 수 있다.
이후에 결과값을 화면에 띄워주고, 현재 결과를 아래 통계 테이블에 기록해주면 되는 간단한 기능이라 볼 수 있다.
실제 코인 토스 함수는 아래와 같다.
<script>
let totalCount = 0;
let headsCount = 0;
let isAnimating = false;
function tossCoin() {
if (isAnimating) return;
const sound = new Audio('/coin.mp3');
sound.play().catch(e => {
console.warn("Coin sound failed to play", e);
});
isAnimating = true;
const coin = document.getElementById("coin");
const move = document.getElementById("coin-move");
const result = document.getElementById("result");
const resultBody = document.getElementById("resultBody");
const shadow = document.getElementById("coin-shadow");
const currentRotation = coin.style.transform || "rotateX(0deg)";
const currentDegMatch = currentRotation.match(/rotateX\((\d+)deg\)/);
const currentDeg = currentDegMatch ? parseInt(currentDegMatch[1], 10) : 0;
const flipCount = 5;
const newDeg = (() => {
const rand = Math.random() >= 0.5;
return currentDeg + 180 * flipCount + (rand ? 0 : 180);
})();
coin.style.transition = "transform 1.0s cubic-bezier(0.33, 0, 0.2, 1)";
move.style.transition = "transform 0.6s ease-in-out";
move.style.transform = "translateY(-100px)";
shadow.style.transform = "scale(0.5)";
shadow.style.opacity = "0.3";
const shine = document.querySelector('.coin .shine');
shine.style.opacity = '1';
setTimeout(() => {
shine.style.opacity = '0';
}, 400);
const tossMessages = [
"운명의 코인토스!",
"자, 결과는 무엇일까?",
"긴장되는 순간!",
"앞일까? 뒷일까?",
"결정의 시간이야!",
"운에 맡겨보자!",
"돌려돌려 동전판~",
"한 번 던져보자!",
"흥미진진한 토스!"
];
result.textContent = tossMessages[Math.floor(Math.random() * tossMessages.length)];
setTimeout(() => {
// 기존보다 리얼한 느낌을 위해 rotateZ 추가
const zWobble = (Math.random() - 0.5) * 40; // -20도~20도 정도의 비틀림
coin.style.transform = `rotateX(${newDeg}deg) rotateZ(${zWobble}deg)`;
}, 30);
setTimeout(() => {
move.style.transform = "translateY(0px)";
shadow.style.transform = "scale(1)";
shadow.style.opacity = "1";
}, 600);
setTimeout(() => {
const finalDeg = newDeg % 360;
const isFront = finalDeg % 360 === 0;
totalCount++;
if (isFront) headsCount++;
const resultProbability = isFront
? ((headsCount / totalCount) * 100).toFixed(1)
: (((totalCount - headsCount) / totalCount) * 100).toFixed(1);
result.textContent = isFront ? "앞면!" : "뒷면!";
const row = document.createElement("tr");
row.innerHTML = `
<td>${totalCount}</td>
<td>${isFront ? "앞면" : "뒷면"}</td>
<td>${resultProbability}%</td>
`;
resultBody.insertBefore(row, resultBody.firstChild);
isAnimating = false;
}, 1000);
}
</script>
Copy
실제 동전의 앞뒷면을 랜덤으로 구현하는 코드보다 실제 코인토스처럼 보이게 하기위한 별도의 스타일, 스크립트 처리가 더 많은게 함정이긴하다만...
데스크탑 버전
그래도 결과를 보면 참 만족스럽다.
나름 모바일 사용성도 꽤나 고려했고, 동전 던지기다운 느낌좀내려고 반사광 처리나 동전 튕기는 소리도 그럴듯하게 추가해보았다.
모바일 버전
모바일 버전이 손으로 직접 누르는 느낌때문에 더 동전 던지는 느낌은 있다.
#JavaScript #블로그
회사에서 커피 내기할 때 딱인듯!