[D3.js] Text 애니메이션 놀이(세번째)
- 사전학습 :
[D3.js] Circle 심심풀이 놀이
[D3.js] Circle 패턴 놀이
[D3.js] Circle 패턴 놀이(두번째)
[D3.js] Text 애니메이션 놀이(세번째)
새해가 밝았습니다. 새해에는 새로운 내용으로 D3.js 내용을 전개 하려다가 어제 밤에 문득 스팀잇 이라는 문자열을 만들어서 재밌는 애니메이션 효과를 부여하면 재밌을 것 같아서 몇가지 구상 중 이전 post의 내용과 연계해서 만들면 좋지 않을까 해서 Circle 패턴 놀이(두번째) post의 소스를 그대로 사용하여 Text 애니메이션 효과를 만들어 보았습니다. 그러면 어떻게 표현 했는지 살펴보도록 하죠.
1. 실험소스
- 사전학습 : [D3.js] Circle 패턴 놀이(두번째)
사전학습의 내용을 보시고 오세요. 아래 소스는 사전학습의 소스입니다. 이 소스를 Circle 대신에 Text로 해서 재밌는 애니메이션을 만들 예정입니다.
[실험 기본소스]
<body>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
var canvas = d3.select("body").append("svg")
.attr("width",500)
.attr("height",500)
.style("background-color","yellow")
.on("click", circleDrawing);
var rect = canvas.append("rect")
.attr("x","220")
.attr("y","70")
.attr("width","60")
.attr("height","60")
.attr("fill", "blue") //내부색
.attr("stroke","red") //테두리색
.attr("stroke-width","5") //테두리 두께
.attr("opacity","0.5"); //불투명도
function circleDrawing() {
var mouseXY = d3.mouse(this);
var circle = canvas.append("circle")
.attr("cx",mouseXY[0]) //시작위치
.attr("cy",mouseXY[1])
.attr("r",5)
.attr("fill", d3.hsl((Math.random()*1000 % 360), 1, 0.5))
.transition()
.duration(2000)
.ease(Math.sqrt)
.attr("cx",250)
.attr("cy",250)
.attr("r", 20)
.transition()
.duration(2000)
.ease(Math.sqrt)
.attr("cx",480)
.attr("cy",20)
.transition()
.duration(2000)
.ease(Math.sqrt)
.attr("cx",480)
.attr("cy",480)
.transition()
.duration(2000)
.ease(Math.sqrt)
.attr("cx",20)
.attr("cy",480)
.transition()
.duration(2000)
.ease(Math.sqrt)
.attr("cx",20)
.attr("cy",20)
.transition()
.duration(2000)
.ease(Math.sqrt)
.attr("cx",250)
.attr("cy",20)
.transition()
.duration(2000)
.ease(Math.sqrt)
.attr("cx",250)
.attr("cy",100)
.remove();
}
</script>
</body>
2. Text 애니메여션 효과
- 동작 : 랜덤 클릭한 위치에서 한글자를 생성하고 그 글자는 중심으로 이동하고 특정 경로를 향햐 움직였다가 해당 글자의 위치로 이동 한 수에 소멸한다는 내용으로 코딩을 설계 했습니다.
먼저, 실험에 사용 할 문자열을 만들었습니다.
var data = "STEEMIT!GO";
위와 같이 "STEEMIT!GO"라는 문자열을 만들어 넣고 이 문자열에서 한글자씩 랜덤으로 생성도록 코딩을 합니다.
var ch_Val = (Math.random()*10 % 10).toFixed(0);
위와 같이 코딩하면 data[ch_Val] 하면 특정한 위치(index)에 있는 알파벳을 지정 할 수 있습니다.
var moveText = canvas.append("text")
.attr("x",mouseXY[0]) //시작위치
.attr("y",mouseXY[1])
.attr("fill", d3.hsl((Math.random()*1000 % 360), 1, 0.5))
.attr("font-family","sans-serif")
.attr("font-size","30px")
.text(data[ch_Val])
위과 같이 코딩을 함으로써 text 태그가 추가 될때마다 ch_Val값은 랜덤 위치(index)의 문자를 출력하게 됩니다.
그리고 나머지 글자의 이동은 사전학습의 circle의 이동 경로와 동일 합니다.
그리고 글자의 최종 목적지는 캔버스의 각 글자의 마지막 위치를 잡아 놓았습니다.
var endText = canvas.selectAll("text").data(data)
.enter()
.append("text")
.attr("x",function(d,i){return 100+i*30;})
.attr("y",100)
.attr("fill", "yellow")
.attr("font-family","sans-serif")
.attr("font-size","30px")
.text(function (d){return d;});
문자열 데이터를 한글자씩 x,y의 위치에 배치 합니다. 이 위치는 아래 결과와 같이 배치 했습니다.
위 그림을 보는 것 처럼 글자는 생성 된 랜덤 글자들이 이동하는데 마지막에 도달 할 글자의 위치라고 생각 하시면 됩니다.
그러면 위 수정 된 코딩을 종합하여 소스를 완성을 해보겠습니다.
3. 전체소스
<body>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
var data = "STEEMIT!GO";
var canvas = d3.select("body").append("svg")
.attr("width",500)
.attr("height",500)
.style("background-color","black")
.on("click", circleDrawing);
var endText = canvas.selectAll("text").data(data)
.enter()
.append("text")
.attr("x",function(d,i){return 100+i*30;})
.attr("y",100)
.attr("fill", "yellow")
.attr("font-family","sans-serif")
.attr("font-size","30px")
.text(function (d){return d;});
function circleDrawing() {
var mouseXY = d3.mouse(this);
var ch_Val = (Math.random()*10 % 10).toFixed(0);
var moveText = canvas.append("text")
.attr("x",mouseXY[0]) //시작위치
.attr("y",mouseXY[1])
.attr("fill", d3.hsl((Math.random()*1000 % 360), 1, 0.5))
.attr("font-family","sans-serif")
.attr("font-size","30px")
.text(data[ch_Val])
.transition()
.duration(2000)
.ease(Math.sqrt)
.attr("x",250)
.attr("y",250)
.transition()
.duration(2000)
.ease(Math.sqrt)
.attr("x",480)
.attr("y",20)
.transition()
.duration(2000)
.ease(Math.sqrt)
.attr("x",480)
.attr("y",480)
.transition()
.duration(2000)
.ease(Math.sqrt)
.attr("x",20)
.attr("y",480)
.transition()
.duration(2000)
.ease(Math.sqrt)
.attr("x",20)
.attr("y",20)
.transition()
.duration(2000)
.ease(Math.sqrt)
.attr("x",250)
.attr("y",20)
.transition()
.duration(2000)
.ease(Math.sqrt)
.attr("x",function(){return 100+ch_Val*30;})
.attr("y",100)
.remove();
}
</script>
</body>
[결과]
마무리
재밌는 놀이였네요. 결과는 알파벳 전체가 다 나왔으면 했는데 랜덤으로 돌려도 특정 알파벳이 집중적으로 나왔네요. 이전 시간의 Circle보다 더 멋진 느낌의 애니메이션 놀이였네요.
이런식으로 post를 쓰면 끝도 없으니 그냥 이정도로 이번 내용은 마무리 합니다. 나머지 상상력 표현은 여러분들의 상상력에 맡기겠습니다.