프로필사진
owgno6
CODELIB
Recent Posts
Recent Comments
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Archives
Today
Total

티스토리 뷰

D3.js

12 Real-Time Transition

owgno6 2018. 7. 20. 15:09


Path Transitions

시계열 데이터의 실시간 표시를 구현할 때  종종 x 축을 사용하여 시간을 위치로 인코딩합니다. 

시간이 경과함에 따라 새로운 데이터가 오른쪽에서 나오고 오래된 데이터가 왼쪽으로 미끄러져 나옵니다. 

그러나 D3에 내장 된  path interpolators(경로 보간)를 사용 하면 몇 가지 놀라운 동작이 나타날 수 있습니다.





위 차트는 다소 산만합니다.  흔딜리고 있다는 느낌을 받습니다.

하지만 자세히보면 차트내 데이터가 오른쪽에서 왼쪽으로 이동하고있음을 알 수 있습니다.

(데이터는 랜덤데이터로 가정하여 받습니다.)




흔들리는 느낌을 제거하기 위해 select를 지정해주고 transform해줍니다.

그리고 x축도 그려넣습니다.

설명은 아래에서 같이 자세하게 다루겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function tick() {
 
data.push(random());
 
d3.select(this)
.attr("d", line)
.attr("transform"null);
 
d3.active(this)
.attr("d", line)
.transition()
.on("start", tick);
 
data.shift();
 
}






다음은 조금 부드럽게 transition해줍니다..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function tick() {
 
    data.push(random());
 
    d3.select(this)
     .attr("d", line)
     .attr("transform"null); 
    d3.active(this)
     .attr("transform""translate(" + x(-1+ ",0)"
  .transition() 
     .on("start", tick);
 
    data.shift(); 
}


새로운 데이터를 뒤쪽에 push 해줍니다. [line 3].

기존 변환 행렬을 초기화합니다. [line 5 ~ 7].

그리고 초기화된 선을 다시 그려줍니다.  [line 5 ~ 7].

변환 행렬을 설정해줍니다. [line 8 ~ 11].

데이터 포인트를 왼쪽으로 밀어줍니다. [line 9].

path를 다시 그리는 방식이 아니라 좌표를 변환함으로써 출렁거리는 것을 막습니다.

변환 시작 [line 10].

이전 데이터(가장 오래된 데이터) 포인트를 앞으로 pop 하여 제거합니다. [line 13].





Real-Time Transitions

다음은 시간에 따라서 데이터를 입력받는 실시간차트입니다.

다양하게 활용할 수 있습니다.

버튼을 눌렀을 때 데이터가 찍힌다던지, 키패드를 눌렀을때 찍힌다던지 등

사용자의 행동이나 외부로부터  받는 데이터를  기록이나 관찰할 때 유용합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html>
<html>
<style>
.x.axis line {
  shape-rendering: auto;
}

.line {
  fill: none;
  stroke: #000;
  stroke-width: 1.5px;
}
</style>
<svg width="960" height="170"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
 
<div id="myDiv"><input type="button" id="myDiv" value="Click Me!" /></div>
<!-- <input type="button" id="myDiv" value="Click!" /> -->
<script type= "text/javascript">
 
var n = 243, // x축 범위 변수
    duration = 750,
    now = new Date(Date.now() - duration),
 
    count = 0,
//     random = d3.randomNormal(0, .2),
    data = d3.range(n).map(function() { return 0; }); // 0~0으로 x축(n값) 범위를 초기화한다.
// var now =  new Date(function() {return (Date.now() - duration)});
var svg = d3.select("svg");
var margin = {top: 20, right : 20, bottom: 20, left: 40},
    width = +svg.attr("width"- margin.left - margin.right,
    height = +svg.attr("height"- margin.top - margin.bottom,
    g = svg.append("g")
    .attr("transform""translate(" + margin.left + "," + margin.top + ")");
var x = d3.scaleTime() // 시간속성(scale Time) 사용. 그래프의 width에 맞추어 x축을 (n-2 = 0~241)로 나눈다.
    .domain([now - (n - 2* duration, now - duration])
    .range([0, width]);
var y = d3.scaleLinear() // 그래프의 height에 맞추어 y축을 -1~1로 나눈다.
    .range([height, 0]);
var line = d3.line() // svg line 설정
    .x(function(d, i) { return x(now - (n - 1 - i) * duration); })
    .y(function(d, i) { return y(d); });
 
g.append("defs").append("clipPath") // clipPath 설정. 보여지는 부분
    .attr("id""clip")
    .append("rect")
    .attr("width", width)
    .attr("height", height);
 
var axis = g.append("g")
    .attr("class""x axis")
    .attr("transform""translate(0," + (height) +")")
    .call(x.axis = d3.axisBottom(x));
 
 
g.append("g"// y축에 대한 그룹 엘리먼트 설정
    .attr("class""axis axis--y")
    .call(d3.axisLeft(y));
 
g.append("g")
    .attr("clip-path""url(#clip)")
    .append("path") // path: 실제 데이터 구현 부
    .datum(data)
    .attr("class""line"// (CSS)
    .transition()
    .duration(750)
    .ease(d3.easeLinear)
    .on("start", tick);
 
 
$("#myDiv").on("click"function(){
    ++count;
});
 
// $("#myDiv").on("click", function(){
//     $.ajax("/D3js/WebChart/opn.jsp")
//         .done(function() {
//             alert("request success!", ++count);
//                 })
// });
 
/* ------------------------------ */
// $(document).ready(function(){
//     $("#myDiv").click(function(){
//         ++count;
//     });
// });
 
/* ------------------------------ */
// d3.select(window)
//.on("scroll", function() { ++count; }); // 스크롤이 조절될 때
//.on("keydown", function() { ++count; }); // 키패드를 눌렀을 때
//.on("mousedown", function() { ++count; }); // 마우스 버튼을 눌렀을 때
//.on("resize", function() { ++count; }); // 창크기가 조절될 때
 
 
function tick() {
 
    now = new Date();
    x.domain([now - (n - 2* duration, now - duration]);
    y.domain([0, d3.max(data)]);
    data.push(Math.min(30, count)); // 새로운 데이터 포인트를 뒤에 push.
    count = 0;
 
    d3.select(this) // 기본 변환행렬 초기화
        .attr("d", line)
        .attr("transform"null); // 선을 다시 그린다.
 
    axis.transition() // x축 설정, transition화
        .duration(750)
        .ease(d3.easeLinear)
        .call(x.axis);
 
    d3.active(this) // 변환행렬 설정
        .attr("transform""translate(" + x(now - (n - 1* duration) + ")") // 왼쪽으로 민다.
        .transition() // 변환 start
        .on("start", tick);
 
    data.shift(); //이전 데이터 포인트를 앞으로 pop.
}
</script>
</html>




한번 확인해보세요!

https://www.w3schools.com/code/tryit.asp?filename=FTG03WJA58Q1




위 실시간 차트를 응용해서 사용할 수도 있습니다.

DB와 연동하였을때는 해당 값이 insert되었을 때, push나 pop이 이루어질때 데이터차트를 실시간으로 기록하며 남길 수 있습니다.

실생활을 예를 들어 페이지 방문수 차트나 해당게시판 클릭횟수 등이 있습니다.


실시간 차트가 아니여도 DB와 연동하여 

데이터와 상황에 적절한 차트를 다양하게 구현할 수도 있습니다.













마침.


'D3.js' 카테고리의 다른 글

D3.js V4  (0) 2018.08.10
11 Multi Line Chart(다중 곡선 차트)  (0) 2018.06.29
10 CSV(외부파일)로 차트(Chart) 구현  (0) 2018.06.25
09 TSV(외부파일)로 차트(Bar Chart) 구현  (1) 2018.06.21
07 원형 차트(Pie & Doughnut Chart)  (1) 2018.06.15
댓글