본문 바로가기
블로그 이미지

방문해 주셔서 감사합니다! 항상 행복하세요!

  
   - 문의사항은 메일 또는 댓글로 언제든 연락주세요.
   - "해줘","답 내놔" 같은 질문은 답변드리지 않습니다.
   - 메일주소 : lts06069@naver.com


Html 캔버스/Html 캔버스 에니메이션

HTML Canvas 룰렛 기능(roulette)

야근없는 행복한 삶을 위해 ~
by 마샤와 곰 2022. 1. 21.

 

* 게시글 하단의 제 깃허브 주소를 통해 실제 구현된 모습을 볼 수 있습니다


HTML Canvas로 만든 룰렛 기능(roulette) 입니다.
룰렛은 원형 판이 빙글빙글 돌아가다 멈추는 기능입니다.

요런게 룰렛이죠~


캔버스에서 이러한 룰렛기능을 만드려면 부채꼴(circular sector)을 그려주는 방법을 사용하면 됩니다.
원을 그려준 다음에 해당 각도를 계속해서 증가하면 빙글빙글 돌아 갈 것 입니다.
먼저 그려줄 부채꼴을 계산합니다.

const canvas = document.getElementById('canvas') 
const ctx = canvas.getContext('2d') 
let width = canvas.width 
let height = canvas.height 

const devide = 12 //나눌 갯수 입니다 
const degree = 360 //원은 360도..ㅋ 
const goalDegree = 270 + degree / devide //목표지점에서 끝부분 값 입니다 

let data = [] 
for(let i=0;i < devide;i++){ 
    let json = {first : degree/devide*i, last : degree/devide*(i+1), text : (i+1)} 
    data.push(json) 
}


원은 360도로 되어 있습니다.
해당 값을 12로 나누면 12개의 부채꼴이 생성이 됩니다.시작각도는 12로 나눈뒤에 i변수만큼 곱해주면 쉽게 구할 수 있으며, 종료각도는 i에 1을 더해서 360/12만큼 증가시키면 시작 ~ 종료각을 구할 수 있습니다.

여기서 goalDegree라는 변수는 최상단의 목표지점 입니다.HTML 캔버스에서는 최상단의 북쪽 지점이 360도가 아니라 270도이기 때문 입니다.그러므로 최상단의 270도에 부채꼴의 갯수를 360으로 나눈 값을 목표지점으로 선정하여 줍니다

캔버스에서의 각도는 위 사진처럼 되어 있습니다


이렇게 계산된 데이터를 가지고 그려봅니다.
그릴때 중요한 것은 save, restore 및 beginpath, closepath 함수를 반드시 활용하여 한붓그리기 효과가 되지 않도록 해 주는 것 입니다.

//#1. 부채꼴을 그립니다 
data.forEach( item => { 
    ctx.save() 
    ctx.beginPath() 
    ctx.lineWidth = 2 
    ctx.strokeStyle = 'gray' 
    ctx.moveTo(width/2, height/2) 
    ctx.arc(width/2, height/2, width/2, (Math.PI / 180) * (item.first), (Math.PI / 180) * (item.last), false) 
    ctx.closePath() 
    ctx.stroke() 
    ctx.restore() 
}) 
//#2. 가운에 원을 그립니다. 
ctx.save()
ctx.beginPath() 
ctx.lineWidth = 2 
ctx.fillStyle = '#B4B4B4' 
ctx.moveTo(width/2, height/2) 
ctx.arc(width/2, height/2, width*0.05, (Math.PI / 180) * 0, (Math.PI / 180) * 360, false) 
ctx.closePath() 
ctx.fill() 
ctx.restore()


이렇게 하면 아래와 같은 부채꼴 모양의 그림을 그릴 수 있습니다.
상단의 화살표 모양은 270도 이며, 목표 부채꼴이 270도 ~ 270+(360/12) 사이에 존재하면 당첨된 번호를 의미 합니다.

저거 화살표는 특수문자 입니다...ㅎ


회전은 매우 쉽습니다.
setInterval이나 setTimeout을 통하여 first와 last의 값을 1씩 증가시켜주면 됩니다.
캔버스는 매우 훌륭하게도 360도가 넘어가는 값에 대해서 알아서 계산을 하여 그림을 그려주기 때문 입니다.
캔버스에서의 애니메이션은 지우기(clear)그리기(draw)가 반복되어 나타나는 효과입니다.
일단 한번 돌려봅니다.

근데...돌긴도는데 밋밋합니다..


각도를 1씩 증가시키되 시간값을 빠르게 하면 점점 빨라지는 효과를 줄 수 있습니다.
그리고 일정 속도와 목표값 까지 동작하고 나면 시간을 줄여서 속도를 늦춰주면 위 사진처럼의 애니메이션 효과를 줄 수가 있습니다.
부채꼴이 좀 밋밋하여 내부에 텍스트를 입혀 봅니다.
내부에 텍스트를 입히기 위해서는 사인(sin)과 코사인(cos) 값을 부채꼴 크기와 넓이 높이등을 가지고 계산하면 텍스트의 좌표값을 구할수가 있습니다.
* 자세한 설명은 제가 작성한 캔버스튜토리얼(차트만들기!) 에서 확인 가능 합니다.
* 주소: https://lts0606.tistory.com/295

요런 느낌입니다.


이렇게 그려주고 나면 아래 사진처럼의 모습을 볼 수 있습니다.
색깔값을 랜덤하게 리턴하는 getRandomColor함수를 만들어 글씨 색상을 랜덤하게 입혀보았습니다.

짜잔~


이제 가장 어려운 구간 입니다.
눈으로는 사실 어느 부채꼴이 목적지에 도달하였는지 알기가 쉽습니다.
만약 위 부채꼴들이 800도만큼 회전하였다면 목적지 값인 270도 ~ 270+(360/12) 값에 누가 위치하는지 알기 위해서는 수식을 통한 분석이 필요 합니다.

다행이도 부채꼴의 시작, 종료각의 값을가진 데이터가 반복문을 통해 오름차순으로 정렬되어 있습니다
data변수를 보면 30씩 증가됨을 볼 수 있습니다. 

 * 360 / 12로 부채꼴을 그렸으므로 부채꼴의 각은 30도 입니다


그러면 배열에서의 가장 첫번째 값을 가지고 와서 목적지의 마지막 값인 270+(360/12) 만큼 빼 준뒤에 해당 값이 270+(360/12) 보다 작으면 빼 주는 행위를 멈춥니다.
그러면 몇번을 빼 주었는지 알 수 있게 됩니다.


위 방법을 통하면 목적지까지의 각도에 도달한 마지막 데이터를 알 수 있게 됩니다.
이러한 모든 내용을 적용한 모습입니다.

오차값이 조금 존재하긴 하지만..잘 동작합니다.

 

최종 동작하는 모습은 아래 제 깃허브에서 확인할 수 있습니다.

https://taeseungryu.github.io/sample/sampleView/roulette/looper.html

 

위 모든 내용이 웹(web)에서 동작하는 캔버스(canvas)로 이루어진 내용 입니다.

 * 플래쉬, 액션스크립트, 유니티 같은 응용 프로그램이 아닙니다~

이상으로 HTML Canvas 룰렛 기능(roulette)에 대해서 정리하여 보았습니다.

문의사항이나 궁금한 점은 언제든 댓글 또는 메일로 연락주세요~ 👻

 

반응형
* 위 에니메이션은 Html의 캔버스(canvas)기반으로 동작하는 기능 입니다. Html 캔버스 튜토리얼 도 한번 살펴보세요~ :)
* 직접 만든 Html 캔버스 애니메이션 도 한번 살펴보세요~ :)

댓글