새해가 밝았습니다. 새해에는 새로운 내용으로 D3.js 내용을 전개 하려다가 어제 밤에 문득 스팀잇 이라는 문자열을 만들어서 재밌는 애니메이션 효과를 부여하면 재밌을 것 같아서 몇가지 구상 중 이전 post의 내용과 연계해서 만들면 좋지 않을까 해서 Circle 패턴 놀이(두번째) post의 소스를 그대로 사용하여 Text 애니메이션 효과를 만들어 보았습니다. 그러면 어떻게 표현 했는지 살펴보도록 하죠.
사전학습의 내용을 보시고 오세요. 아래 소스는 사전학습의 소스입니다. 이 소스를 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>
먼저, 실험에 사용 할 문자열을 만들었습니다.
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의 위치에 배치 합니다. 이 위치는 아래 결과와 같이 배치 했습니다.
위 그림을 보는 것 처럼 글자는 생성 된 랜덤 글자들이 이동하는데 마지막에 도달 할 글자의 위치라고 생각 하시면 됩니다.
그러면 위 수정 된 코딩을 종합하여 소스를 완성을 해보겠습니다.
<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를 쓰면 끝도 없으니 그냥 이정도로 이번 내용은 마무리 합니다. 나머지 상상력 표현은 여러분들의 상상력에 맡기겠습니다.