프로필사진
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

04 툴팁(Tooltip)

owgno6 2018. 6. 4. 11:56


툴팁(tooltip) 기능은

그림과 같이 차트 bar(도형)에 마우스를 올리면 

별도의 작은 창에 관련 데이터를 보여주는 기능을 구현한다.

해당 데이터값의 상세데이터를 표현하고자 할때 사용한다.



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
<!DOCTYPE html>
<meta charset="utf-8">
<style>
svg {
    border: 1px solid;
}
.bar {
    fill: LightCoral;
}
.bar:hover {
    fill: maroon;
/*     DarkSlateBlue; */
    cursor: pointer;
}
.text {
    fill: white;
    font-weight:bold;
}
.grid line {
  stroke: lightgrey;
  stroke-opacity: 0.7;
  shape-rendering: crispEdges;
}
.toolTip {
    position: absolute;
    border: 0 none;
    border-radius: 4px 4px 4px 4px;
    background-color: white;
    padding: 5px;
    text-align: center;
    font-size: 11px;
}
</style>
<svg width="500" height="300"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
    var dataset = [ {x : 'A', y : 7}
                        , {x : 'B', y : 12}
                        , {x : 'C', y : 26}
                        , {x : 'D', y : 41}
                        , {x : 'E', y : 32}
                        , {x : 'F', y : 21}
                        , {x : 'G', y : 9}];
 
    var svg = d3.select("svg");
    var width  = parseInt(svg.style("width"), 10-30;
    var height = parseInt(svg.style("height"), 10)-20;
    var svgG = svg.append("g")
        .attr("transform""translate(30, 0)");
    var xScale = d3.scaleBand()
        .domain(dataset.map(function(d) { return d.x;} ))
        .range([0, width]).padding(0.2);
    var yScale = d3.scaleLinear()
        .domain([0, d3.max(dataset, function(d){ return d.y; })])
        .range([height, 0]);
 
    svgG.append("g")
        .attr("class""grid")
        .attr("transform""translate(0," + height + ")")
        .call(d3.axisBottom(xScale)
            .tickSize(-height)
        );
 
    svgG.append("g")
        .attr("class""grid")
        .call(d3.axisLeft(yScale)
            .ticks(5)
            .tickSize(-width)
        );
 
    var barG = svgG.append("g");
 
    barG.selectAll("rect")
        .data(dataset)
        .enter().append("rect")
            .attr("class""bar")
            .attr("height"function(d, i) {return height-yScale(d.y)})
            .attr("width", xScale.bandwidth())
            .attr("x"function(d, i) {return xScale(d.x)})
            .attr("y"function(d, i) {return yScale(d.y)})
            .on("mouseover"function() { tooltip.style("display"null); })
            .on("mouseout",  function() { tooltip.style("display""none"); })
            .on("mousemove"function(d) {
                tooltip.style("left", (d3.event.pageX + 10+ "px");
                tooltip.style("top", (d3.event.pageY - 10+ "px");
                tooltip.text(d.y); 
            });
 
    barG.selectAll("text")
        .data(dataset)
        .enter().append("text")
        .text(function(d) {return d.y})
            .attr("class""text")
            .attr("x"function(d, i) {return xScale(d.x)+xScale.bandwidth()/2})
            .style("text-anchor""middle")
            .attr("y"function(d, i) {return yScale(d.y) + 15});
 
    var tooltip = d3.select("body").append("div")
        .attr("class""toolTip")
        .style("display""none");
 
</script>
cs

[line 81 ~ 87]

이 기능을 구현하는 방법은

다음 문장을 그대로 코드로 작성하면 된다.

차트 도형에 마우스를 올리면(mouseover) 보이고, 

도형에서 마우스가 벗어나면(mouseout) 안보이게 구현 한다.

마우스가 도형에 올라있는 동안은 마우스를 따라다니면서(mousemove) 

마우스 근처에 작은 창(rect)을 하나 보여준다.

작은 창은 해당 도형의 데이터 값(Y 값)을 출력한다.

위 방법은 d3.js의 일반적인 툴팁표현 방법 표기식이다.


툴팁은 rect(배경, 선등)와 text(값출력)로 구성된

tooltip이라는 SVG 그룹 태그로 (var tooltip = svg.append("g")) [line 98 ~ 100].

평소에는 눈에 보이지 않는다 (display: "none").

이 tooltip은 도형의 

mouseover 이벤트에서 display 값을 지워서(빈문자열) 보이게 하고

mouseout 이벤트에서 display 값을 none로 해서 보이지 않게 한다.

해당 좌표값에 적절한 계산(+10, -10)을 해서 

툴팁이 마우스에 가려지지 않게 했다.


CSS로 간편하게 지정을 했고,

다음 코드와 같이 D3의 append로 생성하고 

toolTip이라는 CSS 클래스를 지정한다.

해당 클래스에서 CSS 속성으로 원하는 데로 지정하면 된다.

여기서는 툴팁 도형을 일반 사각(rect)이 아닌 

모서리가 둥근 사각형으로 구현했다.

SVG Rect는 좌표(x, y)로 위치를 지정했지만

DIV는 left와 right 값으로 지정하고

위치 값도

SVG Rect는 SVG 내에서 위치로 지정했지만

DIV는 부모가 문서(body)이므로 

문서 기준(pageX, pageY)으로 구현하였다.



다음은 툴팁(tooltip)을 좀 더 응용해봤다.


위와 같은 차트의 툴팁은

bar(도형)에서 해당 데이터의 값의 내용을 더 상세하게 보여줄 수 있다.



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
<!DOCTYPE html>
<meta charset="utf-8">
<style>
svg {
    border: 1px solid;
}
.bar {
    fill: LightCoral;
}
.bar:hover {
    fill: maroon;
/*     DarkSlateBlue; */
    cursor: pointer;
}
.text {
    fill: white;
    font-weight:bold;
}
.grid line {
  stroke: lightgrey;
  stroke-opacity: 0.7;
  shape-rendering: crispEdges;
}
.toolTip {
    position: absolute;
    border: 0 none;
    border-radius: 4px 4px 4px 4px;
/*     background-color: white; */
    background: rgba(0, 0, 0, 0.8);
    color : white;
    padding: 1px 10px 1px 10px;
    text-align: center;
}
</style>
<svg width="500" height="300"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
    var dataset = [ {x : 'A', y : 7}
                        , {x : 'B', y : 12}
                        , {x : 'C', y : 26}
                        , {x : 'D', y : 41}
                        , {x : 'E', y : 32}
                        , {x : 'F', y : 21}
                        , {x : 'G', y : 9}];
 
    var svg = d3.select("svg");
    var width  = parseInt(svg.style("width"), 10-30;
    var height = parseInt(svg.style("height"), 10)-20;
    var svgG = svg.append("g")
        .attr("transform""translate(30, 0)");
    var xScale = d3.scaleBand()
        .domain(dataset.map(function(d) { return d.x;} ))
        .range([0, width]).padding(0.2);
    var yScale = d3.scaleLinear()
        .domain([0, d3.max(dataset, function(d){ return d.y; })])
        .range([height, 0]);
 
    svgG.append("g")
        .attr("class""grid")
        .attr("transform""translate(0," + height + ")")
        .call(d3.axisBottom(xScale)
            .tickSize(-height)
        );
 
    svgG.append("g")
        .attr("class""grid")
        .call(d3.axisLeft(yScale)
            .ticks(5)
            .tickSize(-width)
        );
 
    var barG = svgG.append("g");
 
    barG.selectAll("rect")
    .data(dataset)
    .enter().append("rect")
        .attr("class""bar")
        .attr("height"function(d, i) {return height-yScale(d.y)})
        .attr("width", xScale.bandwidth())
        .attr("x"function(d, i) {return xScale(d.x)})
        .attr("y"function(d, i) {return yScale(d.y)})
        .on("mouseover"function() { tooltip.style("display""block"); })
        .on("mouseout",  function() { tooltip.style("display""none"); })
        .on("mousemove"function(d) {
            tooltip.style("left", (d3.event.pageX + 10+ "px");
            tooltip.style("top", (d3.event.pageY - 10+ "px");
            tooltip.html("<p style='font:11px sans-serif'><strong>dataset:</strong> 
<span style='color:red'>" + d.y + "</span>");
        });
 
    barG.selectAll("text")
        .data(dataset)
        .enter().append("text")
        .text(function(d) {return d.y})
            .attr("class""text")
            .attr("x"function(d, i) {return xScale(d.x)+xScale.bandwidth()/2})
            .style("text-anchor""middle")
            .attr("y"function(d, i) {return yScale(d.y) + 15});
 
    var tooltip = d3.select("body").append("div")
        .attr("class""toolTip")
        .style("display""none");
 
</script>
cs


기존 (display: "none")에서 (display: "block")으로 변경해보고 (효과는 같다.) [line 82].

tooltip.html(d.y)속성도 tooltip.text(d.y)에서 CSS효과를 주기위해 변경해봤다. [line 87 ~ 89].







댓글