Matrix code rain 만들기
Matrix Code Rain 을 구현해보려고 한다.
구성
- 초당 8-10회 종방향으로 좌표를 이동시키면서, 글자를 찍는다.
setInterval(()=>{
// 글자를 찍기전에, 이 전 실행으로 그렸던, 폰트들을 지운다.
app.clearRect();
app.write();
},120)
app = {
write: function(){
for(let i=0; i< coord_x.length; i++){
const _x = coord_x[i];
const _y = coord_y[i];
const charLength = characterLength[i];
const _fontSize = randomFontSize[i];
app.context.font = `${_fontSize}px sans-serif`;
// 문자열 출력 함수
app.context.fillText("A", _x, _y)
if(coord_y[i]>convasHeight){
coord_y[i]=-150;
}else coord_y[i]+=100; // 항목 3에서, 이부분에서 속도의 변화를 주려고 한다.
}
}
}
- 이동된 좌표에, 문자열을 그린다.
const characters = ["ヲ","ァ","ィ","ゥ","9"]
app={
...app,
// 문자열을 찍는 함수, 시작할 좌표값고, 문자열의 길이를 넘겨받아서, 랜덤한 문자열을 찍는다.(characters 라는 문자열 배열이 이미 있음, 랜덤한 인덱스로 값을 가져오기만 하면 됨)
verticalCharacterWrite: function(x, y, length){
let chars = "";
// randomNumber(maxNumber)는 랜덤한 정수형 숫자 반환함수
const rand_length = randomNumber(rainCharacterLength);
let dy = y;
// 문자열을 그린다. 문자열을 그리면서, 문자들이 겹치지 않게 y좌표를 이동해주면서, 한글자씩, 주어진 length만큼 찍는다.
for(let i=0; i< length; i++){
const rand_index = randomNumber(characters.length-1);
const rand_char = characters[rand_index];
app.context.fillText(rand_char, x, dy);
const diff = app.context.measureText(rand_char).actualBoundingBoxAscent;
dy+=diff;
};
},
}
- 문자열이 떨어지는 속도, 폰트의 색상 등에서 변화를 준다.
// 앞서 항목 1에서 설명한 write함수에서, 폰트가 비처럼 떨어질 때, 떨어지는 속도에 대한 변화를 만들어준다.
write: function(){
for(let i=0; i< coord_x.length; i++){
const _x = coord_x[i];
const _y = coord_y[i];
const charLength = characterLength[i];
const _fontSize = randomFontSize[i];
app.context.font = `${_fontSize}px sans-serif`;
// 문자열 출력 함수 [수정] -> verticalCharacterWrite
// app.context.fillText("A", _x, _y);
app.verticalCharacterWrite(_x, _y, charLength);
if(coord_y[i]>convasHeight){
coord_y[i]=-150;
}else coord_y[i]+= rainSpeed[i]; // 항목 3에서, 이부분에서 속도의 변화를 주려고 한다.
}
}
// 앞서 항목 2에서 설명한, verticalCharacterWrite에서 폰트 스타일에 변화를 준다.
verticalCharacterWrite: function(x, y, length){
let chars = "";
const rand_length = randomNumber(rainCharacterLength);
let dy = y;
for(let i=0; i< length; i++){
const rand_index = randomNumber(characters.length-1);
const rand_char = characters[rand_index];
console.log("context" , app.context);
if(i %2 == 1)app.setCharstyle("#2ba64f",2, "#1ca344");
if(i %2 == 0)app.setCharstyle("#2ba64f",2, "#0b752a");
if(i <= 6){
if(i %3 == 1)app.setCharstyle("#2ba64f",2, "#174d27");
if(i %3 == 2)app.setCharstyle("#2ba64f",0, "#095921");
if(i %3 == 0)app.setCharstyle("#2ba64f",0, "#095921");
}
if(i == length - 1) app.setCharstyle("#eee",0, "#92e0a9");
if(i == length - 1) app.setCharstyle("#eee",0, "#e3ffeb");
if(i == length - 2) app.setCharstyle("#eee",3, "#66cc84");
app.context.fillText(rand_char, x, dy);
const diff = app.context.measureText(rand_char).actualBoundingBoxAscent;
dy+=diff;
};
},
번외
최초 계획은, transform으로 글자를 변형시켜서 비처럼 떨어지게 할 생각이었으나, 그렇게 되면, 글자 한글자 한글자 마다 수시로 바뀌어야 하는, 모션 특성상 부하가 많아질 것 같아서, canvas 에서 구현하는 방향으로 변경. but 다음의 내용을 알게 되었다.
- text glowing 효과 -> text-shadow
- text gradation 효과 -> background-image, background-clop, web-kit-text-fill-color, background-size 콤비네이션 이용
// 예제
2. background-image, webkit-background-clip,web-kit-text-fill-color, background-size 콤비네이션을 사용한다.(transform: rotation과 궁합이 좋지 않다.)
background-image: gradation();
// 브라우저가 webkit 계열이 아닌경우에는, 속성이 안먹으니까, 그냥 컬러로 단색 톤으로 나오게 처리를 해둔다.
background-clip(fallback)
color:green(fallback);
// webkit브라우저에서만 작동
web-kit-text-fill-color: transparent;
web-kit-background-clip: text;
마무리
위 코드는 실제 소스의 일부이지만, 위 코드만으로는 구현이 충분하지가 않습니다. 이 글은, 대략적인 아이디어의 전달을 목적으로 하고 있습니다.
혼자서 구현해보시다가, 막히시는 부분이 있을 때, 어떤 아이디어로 접근을 해야 문제를 풀수 있는 지 정도로 참고하시는 게 좋을 것 같습니다.
아래 깃허브 저장소 링크를 걸어놓을 테니, 소스 전체를 확인하시고 싶은 분들은, 아래 링크에서 확인하시면 될 것 같습니다.
구현내용: codepen
구현내용: https://github.com/jimyeong/animations
Leave a comment