2016년 11월 15일 대한민국:우즈베키스탄 후반전 패스분포도
Last active
May 15, 2017 15:42
-
-
Save vuski/d96478a9ea8c09447eff0f43f16375eb to your computer and use it in GitHub Desktop.
Passing Distribution KOR : UZB 15 NOV 2016 second half
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<html> | |
<head> | |
<style> | |
body { | |
margin: 0px; | |
} | |
svg text { | |
font-family: Helvetica, YDIYGO320, '08SeoulNamsan B', 돋움체,Arial; | |
font-weight: bold; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="soccer"> | |
<svg id="players" width="640" height="1024" style="overflow:hidden"> | |
<g id="ground" transform="translate(0,0) scale(1)"> | |
<rect id="XMLID_4_" style="fill:#232823;" width="640" height="1024" /> | |
</g> | |
<g id="groundLine" transform="translate(0,0) scale(1)"> | |
<g id="XMLID_1_"> | |
<rect id="XMLID_41_" x="25" y="69.107" style="fill:none;stroke:#202020;stroke-width:4;stroke-miterlimit:10;" width="590" height="884" /> | |
<rect id="XMLID_40_" x="158" y="70.107" style="fill:none;stroke:#202020;stroke-width:4;stroke-miterlimit:10;" width="322" height="128" /> | |
<polyline id="XMLID_39_" style="fill:none;stroke:#202020;stroke-width:4;stroke-miterlimit:10;" points="158,953.107 | |
158,826.107 479,826.107 479,953.107 " /> | |
<polyline id="XMLID_38_" style="fill:none;stroke:#202020;stroke-width:4;stroke-miterlimit:10;" points="262,69.107 262,113.107 | |
375,113.107 375,69.107 " /> | |
<polyline id="XMLID_37_" style="fill:none;stroke:#202020;stroke-width:4;stroke-miterlimit:10;" points="262,953.107 | |
262,909.107 375,909.107 375,953.107 " /> | |
<polyline id="XMLID_36_" style="fill:none;stroke:#202020;stroke-width:4;stroke-miterlimit:10;" points="276,69.107 276,47.107 | |
362,47.107 362,69.107 " /> | |
<polyline id="XMLID_3_" style="fill:none;stroke:#202020;stroke-width:4;stroke-miterlimit:10;" points="362,954.107 362,977.107 | |
276,977.107 276,954.107 " /> | |
<path id="XMLID_35_" style="fill:none;stroke:#202020;stroke-width:4;stroke-miterlimit:10;" d="M273.665,953.242" /> | |
<path id="XMLID_34_" style="fill:none;stroke:#202020;stroke-width:4;stroke-miterlimit:10;" d="M273.665,971.55" /> | |
<line id="XMLID_32_" style="fill:none;stroke:#202020;stroke-width:4;stroke-miterlimit:10;" x1="25" y1="512.107" x2="615" y2="512.107" /> | |
<circle id="XMLID_31_" style="fill:none;stroke:#202020;stroke-width:4;stroke-miterlimit:10;" cx="320.455" cy="511.335" r="78.688" /> | |
<path id="XMLID_30_" style="fill:none;stroke:#202020;stroke-width:4;stroke-miterlimit:10;" d="M25.291,80.978 | |
c6.132-0.128,11.065-5.129,11.065-11.292" /> | |
<path id="XMLID_29_" style="fill:none;stroke:#202020;stroke-width:4;stroke-miterlimit:10;" d="M603.995,69.49 | |
c0.128,6.132,5.13,11.065,11.292,11.065" /> | |
<path id="XMLID_28_" style="fill:none;stroke:#202020;stroke-width:4;stroke-miterlimit:10;" d="M615.174,941.474 | |
c-6.132,0.128-11.065,5.13-11.065,11.292" /> | |
<path id="XMLID_27_" style="fill:none;stroke:#202020;stroke-width:4;stroke-miterlimit:10;" d="M36.16,952.652 | |
c-0.128-6.132-5.129-11.065-11.292-11.065" /> | |
<path id="XMLID_26_" style="fill:none;stroke:#202020;stroke-width:4;stroke-miterlimit:10;" d="M257.546,197.28 | |
c12.485,21.711,35.912,36.33,62.755,36.33c26.842,0,50.27-14.619,62.755-36.33" /> | |
<line id="XMLID_21_" style="fill:none;stroke:#202020;stroke-width:4;stroke-miterlimit:10;" x1="257" y1="198.107" x2="383" y2="198.107" /> | |
<path id="XMLID_19_" style="fill:none;stroke:#202020;stroke-width:4;stroke-miterlimit:10;" d="M256.758,825.339 | |
c12.269-22.484,36.124-37.739,63.542-37.739c27.418,0,51.273,15.255,63.542,37.739" /> | |
<line id="XMLID_18_" style="fill:none;stroke:#202020;stroke-width:4;stroke-miterlimit:10;" x1="257" y1="826.107" x2="384" y2="826.107" /> | |
</g> | |
</g> | |
</svg> | |
</div> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script> | |
window.onload = function () { | |
// | |
// console.log(Math.sin(Math.PI)); | |
//Input data | |
var data = [ | |
["김승규", "박주호", "장현수", "김기희", "김창수", "기성용", "이재성", "구자철", "남태희", "손흥민", "김신욱", "유효슛"], | |
[320, 80, 210, 394, 584, 323, 511, 310, 412, 164, 321, 320], //x좌표 (모바일) | |
[935, 512, 615, 640, 542, 483, 209, 354, 252, 228, 194, 85], //y좌표 (모바일) | |
[23, 6, 20, 4, 22, 16, 12, 13, 10, 7, 9, ], //등번호 | |
[11, 52, 76, 67, 46, 91, 26, 90, 51, 33, 13, 2], //노드크기 | |
[0, 0, 2, 2, 0, 1, 0, 1, 0, 0, 0, 0], | |
[0, 0, 8, 0, 1, 4, 1, 6, 2, 4, 0, 0], | |
[0, 11, 0, 6, 1, 11, 0, 6, 0, 2, 1, 0], | |
[4, 1, 12, 0, 6, 5, 0, 7, 1, 0, 0, 0], | |
[0, 0, 0, 6, 0, 6, 4, 3, 2, 1, 0, 0], | |
[0, 3, 9, 8, 10, 0, 1, 8, 6, 3, 1, 0], | |
[0, 0, 0, 0, 0, 0, 0, 2, 5, 3, 1, 0], | |
[0, 8, 5, 7, 1, 11, 1, 0, 7, 3, 2, 1], | |
[1, 1, 2, 2, 5, 1, 4, 7, 0, 2, 1, 1], | |
[0, 2, 0, 0, 0, 3, 3, 3, 0, 0, 1, 0], | |
[0, 0, 0, 0, 0, 0, 1, 1, 1, 3, 0, 0], | |
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //슛 | |
]; | |
function Data_nodes(name, x, y, number, radius, group) { | |
this.number = number; | |
this.name = name; | |
this.radius = radius; | |
this.group = group; | |
this.x = x; | |
this.y = y; | |
} | |
function Data_links(source, target, value) { | |
this.source = source; | |
this.target = target; | |
this.value = value; | |
} | |
var graph = { nodes: [], links: [] }; | |
for (var i = 0 ; i < data[0].length ; i++) { | |
graph.nodes.push(new Data_nodes(data[0][i], data[1][i], data[2][i], data[3][i], data[4][i], i)); | |
} | |
for (var i = 0 ; i < data[0].length ; i++) { | |
for (var j = 0 ; j < data[0].length ; j++) { | |
if (data[i + 5][j] != 0) graph.links.push(new Data_links(i, j, data[i + 5][j])); | |
} | |
} | |
//너비높이 | |
var width = getWidth(); | |
function getWidth() { | |
if (self.innerWidth) { | |
return self.innerWidth; | |
} | |
if (document.documentElement && document.documentElement.clientWidth) { | |
return document.documentElement.clientWidth; | |
} | |
if (document.body) { | |
return document.body.clientWidth; | |
} | |
} | |
var height = width * 1.6; | |
var svg = d3.select("#players"); | |
svg.attr("width", width) | |
.attr("height", height); | |
var scaleW = width / 640; | |
//위의 그룹별로 이 컬러 지정 | |
var color = ["#d2af7f", "#6e969b", "#bec7a8", "#89a2b5", "#ca9d66", "#c4bab6", "#7db0a4", "#75adb8", "#9d9c8d", | |
"#bccf85", "#d3c2a0", "#bfa68e", "#d6ca81", "#c4d6c9"]; | |
//초기 스케일 셋팅 | |
var radiusScale = d3.scale.pow().exponent(1); | |
var textScale = d3.scale.pow().exponent(1); | |
var lineWidthScale = d3.scale.pow().exponent(1); | |
var arrowScale = d3.scale.pow().exponent(1); | |
var OpacityScale = d3.scale.pow().exponent(1); | |
var frqScale = d3.scale.pow().exponent(1); | |
var arrowSize = 5; | |
//드래그를 위한 정의 | |
var drag = d3.behavior.drag() | |
.origin(function (d) { return d; }) | |
.on("dragstart", dragstarted) | |
.on("drag", dragged) | |
.on("dragend", dragended); | |
function dragstarted(d) { | |
d3.event.sourceEvent.stopPropagation(); | |
d.fixed |= 2; | |
force.stop(); | |
} | |
function dragged(d) { | |
var mouse = d3.mouse(svg.node()); | |
if (mouse[0] <= 0) mouse[0] = 0; | |
if (mouse[0] >= width) mouse[0] = width; | |
if (mouse[1] <= 0) mouse[1] = 0; | |
if (mouse[1] >= height) mouse[1] = height; | |
d.x = xScale.invert(mouse[0]); | |
d.y = yScale.invert(mouse[1]); | |
d.px = d.x; | |
d.py = d.y; | |
tick(); | |
} | |
function dragended(d) { | |
d.fixed &= ~6; | |
tick(); | |
} | |
//force layout 정의 | |
var force = d3.layout.force() | |
.size([width, height]); | |
//기본 데이터 링크 | |
force | |
.nodes(graph.nodes) | |
.links(graph.links) | |
.start(); | |
//스케일 정의 | |
var scaleRef = 20; //라인 두께와 화살표 연동 | |
radiusScale.domain([d3.min(graph.nodes, function (d) { return d.radius; }), d3.max(graph.nodes, function (d) { return d.radius; })]) | |
.range([10, 20]); | |
textScale.domain([d3.min(graph.nodes, function (d) { return d.radius; }), d3.max(graph.nodes, function (d) { return d.radius; })]) | |
.range([9, 14]); | |
lineWidthScale.domain([d3.min(graph.links, function (d) { return d.value; }), d3.max(graph.links, function (d) { return d.value; })]) | |
.range([1, scaleRef]); | |
arrowScale.domain([d3.min(graph.links, function (d) { return d.value; }), d3.max(graph.links, function (d) { return d.value; })]) | |
.range([0.2, scaleRef / 4]); | |
OpacityScale.domain([d3.min(graph.links, function (d) { return d.value; }), d3.max(graph.links, function (d) { return d.value; })]) | |
.range([0.2, 1]); | |
frqScale.domain([d3.min(graph.links, function (d) { return d.value; }), d3.max(graph.links, function (d) { return d.value; })]) | |
.range([20, 60]); | |
//배경 | |
svg.select("#ground").select("rect") | |
.style("fill", "#232823"); | |
svg.select("#groundLine").selectAll("*") | |
.style("stroke", "#202020"); | |
//화살표를 위한 곳 | |
var targetBuffer = 50; | |
var edge = svg.append("g") | |
.attr("class", "edge") | |
.attr("fill", "none"); | |
var arrow = svg.append("g") | |
.attr("class", "arrows"); | |
var link = edge.selectAll(".lines") | |
.data(graph.links, function (d) { return d.source.name + d.target.name + d.value; }); | |
var arrowHead = arrow.selectAll(".arrow") | |
.data(graph.links, function (d) { return d.source.name + d.target.name + d.value; }) | |
.enter() | |
.append("g") | |
.attr("class", "arrow").attr("id", function (d, i) { return "arrow" + d.source.name.replace(/[\s()]/gi, "") + d.target.name.replace(/[\s()]/gi, ""); }) | |
; | |
var frqcy = svg.append("g") | |
.attr("class", "passFrequency"); | |
var node = svg.selectAll(".node") | |
.data(graph.nodes) | |
.enter().append("g") | |
.attr("class", "node") | |
.call(drag)//여기를 주석처리하면 드래그 안되게 할 수 있음 | |
; | |
//zoom 을 위한 정의 | |
var xScale = d3.scale.linear() | |
.domain([0, width]) | |
.range([0, width]); | |
var yScale = d3.scale.linear() | |
.domain([0, height]) | |
.range([0, height]); | |
var zoomer = d3.behavior.zoom().x(xScale).y(yScale).scaleExtent([scaleW, 6]).on("zoom", zoom).translate([0, 0]).scale(scaleW);; | |
function zoom(f) { | |
var d3et; | |
var d3es; | |
if (f != null) { //초기화할때 한번만 실행되는 부분 | |
d3et = [0, 0]; | |
d3es = scaleW; | |
d3esT = d3es * 0.5 + 0.5; | |
} else { | |
d3et = d3.event.translate; | |
d3es = d3.event.scale; | |
d3esT = d3es * 0.5 + 0.5; | |
} | |
//console.log(d3et + " | " + d3es); | |
d3et[0] = Math.min(0, Math.max(width * (1 - d3es/scaleW), d3et[0])); | |
d3et[1] = Math.min(0, Math.max(height * (1- d3es/scaleW), d3et[1])); | |
zoomer.translate(d3et); | |
//zoomer.scale(d3es); | |
svg.select("#ground") | |
.attr("transform", "translate(" + d3et + ") scale(" + d3es + ")"); | |
svg.select("#groundLine") | |
.attr("transform", "translate(" + d3et + ") scale(" + d3es + ")"); | |
node.selectAll(".cir").attr("r", function (d) { | |
if (d.radius == 0) { | |
return d3esT * 2; | |
} else { | |
return d3esT * radiusScale(d.radius); | |
} | |
}); | |
node.selectAll(".name") | |
.attr("dy", (-1.5 * (1 + (d3esT - 1) * 0.1)) + "em") | |
.style("font-size", function (d) { return d3esT * (textScale(d.radius) + 3) + "px" }); | |
node.selectAll(".number") | |
.attr("dy", (0.27 * (1 + (d3esT - 1) * 0.1)) + "em") | |
.style("font-size", function (d) { return d3esT * textScale(d.radius) + "px" }); | |
link.attr("stroke-width", function (d) { return d3esT * lineWidthScale(d.value) + "px"; }) | |
svg.selectAll(".frq") | |
.style("font-size", function (d) { return (frqScale(d.__data__.value) * d3esT) + "px"; }) | |
tick(); | |
}; | |
//svg.call(zoomer); | |
link.enter().insert("path", "g") | |
.attr("class", function (d) { return "lines " + d.source.name + " off"; }) | |
.attr("id", function (d, i) { return "path" + d.source.name.replace(/[\s()]/gi, "") + d.target.name.replace(/[\s()]/gi, ""); }) | |
.attr("stroke", function (d) { return color[d.source.group]; }) | |
.attr("stroke-opacity", function (d) { return OpacityScale(d.value); }); | |
link.exit().remove(); | |
arrowHead.append("path") | |
.attr("d", "M0,-4L" + arrowSize + ",0L0,4") | |
.attr("class", function (d) { return "arrowHead " + d.source.name + " off"; }) | |
//.attr("d", "M-10,5L-10,-5L0,0") | |
.attr("fill", function (d, i) { return color[d.source.group]; }); | |
//노드 그리기 | |
node.append("circle") | |
.attr("class", "cir") | |
.attr("stroke", "#fff") | |
.attr("stroke-width", "3px") | |
.style("fill", function (d) { return color[d.group]; }) | |
.on("click", click); | |
node.append("text") | |
.attr("class", "name") | |
.attr("dx", 0) | |
.style("fill", "white") | |
.attr("text-anchor", "middle") | |
.style("opacity", function (d) { if (d.radius == 0) return 0.05; else return 1; }) | |
.text(function (d) { return (d.name); }) | |
.on("click", click); | |
node.append("text") | |
.attr("class", "number") | |
.attr("dx", 0) | |
.style("fill", "white") | |
.attr("text-anchor", "middle") | |
.style("opacity", function (d) { if (d.radius == 0) return 0.05; else return 1; }) | |
.text(function (d) { return (d.number); }) | |
.on("click", click); | |
// | |
var clicked = null; | |
var clickedPrevious = null; | |
var textDraw; | |
drawIndex(); | |
zoom(1); //위에서 정의되지 않은 성질들은 zoom 안에서 정의한다. | |
function drawIndex() { | |
var indexArea = svg.append("g") | |
.attr("class", "indexArea"); | |
var textUnit = width / 60; | |
indexArea.append("text") | |
.attr("transform", "translate (" + (width / 2) + "," + ((textUnit * 1.8)+10) + ")") | |
.attr("class", "R_button") | |
.style("fill", "#a0a0a0") | |
.attr("text-anchor", "middle") | |
.style("font-size", (textUnit*1.8)+"px") | |
.style("opacity", 1) | |
.text("[대한민국:우즈베키스탄] 후반전 패스 분포도") | |
indexArea.append("text") | |
.attr("transform", "translate (10," + (height - 30) + ")") | |
.attr("class", "description") | |
.style("fill", "#808080") | |
.attr("text-anchor", "start") | |
.style("font-size", (textUnit * 1.5) + "px") | |
.style("opacity", 1) | |
.text("선수를 클릭해보세요"); | |
indexArea.append("text") | |
.attr("transform", "translate (" + (width - 10) + "," + (height - 30) + ")") | |
.attr("class", "description") | |
.style("fill", "#e0e0e0") | |
.attr("text-anchor", "end") | |
.style("font-size", (textUnit * 2.5) + "px") | |
.style("opacity", 1) | |
.text("클릭! 전체 패스 보기") | |
.on("click", click); | |
} | |
//매 프레임 움직임 정의 | |
function tick() { | |
//console.log(d3es); | |
var easeType = "bounce"; //back, elastic, cubic | |
link.attr("d", lineDraw) | |
.attr("stroke-dasharray", function (d) { | |
var totalLength = this.getTotalLength(); | |
//console.log(totalLength); | |
return (totalLength - d3esT * (radiusScale(d.target.radius + targetBuffer) + arrowScale(d.value) * arrowSize)) + " " + (totalLength); //첫번째 수는 선의 길이, 두번째 수는 대쉬 사이의 길이 | |
}) | |
.transition() | |
.duration(2000) | |
.ease(easeType) | |
.attrTween("stroke-dashoffset", function (d) { | |
var marginalLength = this.getTotalLength() - d3esT * (radiusScale(d.target.radius + targetBuffer) + arrowScale(d.value) * arrowSize); | |
//var i = d3.interpolate(0, totalLength); | |
return function (t) { | |
return marginalLength * (1 - t); | |
} | |
}); | |
arrowHead | |
.transition() | |
.duration(2000) | |
.ease(easeType) | |
.attrTween("transform", function (d) { | |
var thisPath = svg.select("#" + "path" + d.source.name.replace(/[\s()]/gi, "") + d.target.name.replace(/[\s()]/gi, "")); | |
var marginalLength = thisPath.node().getTotalLength() - d3esT * (radiusScale(d.target.radius + targetBuffer) + arrowScale(d.value) * arrowSize); | |
var t0 = 0; | |
return function (t) { | |
var p0 = thisPath.node().getPointAtLength(t0 * marginalLength);//previous point | |
var p = thisPath.node().getPointAtLength(t * marginalLength); | |
var angle = Math.atan2(p.y - p0.y, p.x - p0.x) * 180 / Math.PI;//angle for tangent | |
if (t > t0) { | |
t0 = t; | |
return "translate(" + p.x + "," + p.y + ") scale(" + d3esT * arrowScale(d.value) + ") rotate(" + angle + ")"; | |
} else { //bounce 같은 easement의 경우 화살표가 뒤집어지지 않도록 각도에 180을 더한다. | |
t0 = t; | |
return "translate(" + p.x + "," + p.y + ") scale(" + d3esT * arrowScale(d.value) + ") rotate(" + (angle + 180) + ")"; | |
} | |
} | |
}); | |
node.attr("transform", function (d) { | |
d.fixed = true; // 이것을 주석처리하면 drag 같은 사용자 인풋이 있을때, 위치를 자동적으로 계산. 즉 고정위치가 풀어짐 | |
return "translate(" + xScale(d.x) + "," + yScale(d.y) + ")"; | |
}); | |
var list = svg.selectAll(".lines").filter(".on"); | |
//console.log(list[0]); | |
if (clicked != clickedPrevious) { | |
var showFrqcy = frqcy.selectAll(".frq") | |
.data(list[0], function (d) { return d.id; }) | |
textDraw = showFrqcy.enter().append("text") | |
.attr("class", "frq") | |
.style("text-anchor", "middle") | |
.style("font-size", function (d) { return (frqScale(d.__data__.value) * d3esT) + "px"; }) | |
.style("fill", "white") | |
// .style("stroke", "#505050") | |
//.style("stroke-width","1") | |
//.append("textPath") | |
//.attr("xlink:href", function (d) { return "#" + d.id; }) | |
.text(function (d) { return d.__data__.value }); | |
showFrqcy.exit().remove(); | |
clickedPrevious = clicked; | |
}; | |
if (textDraw != null) { //처음은 건너뛴다. | |
textDraw.attr("dy", "0em").transition() | |
.duration(2000) | |
.ease(easeType) | |
.attrTween("transform", function (d) { | |
var thisPath = svg.select("#" + "path" + d.__data__.source.name.replace(/[\s()]/gi, "") + d.__data__.target.name.replace(/[\s()]/gi, "")); | |
var marginalLength = thisPath.node().getTotalLength() - d3esT * (frqScale(d.__data__.value) + radiusScale(d.__data__.target.radius + targetBuffer) + arrowScale(d.__data__.value) * arrowSize); | |
var t0 = 0; | |
return function (t) { | |
var p0 = thisPath.node().getPointAtLength(t0 * marginalLength);//previous point | |
var p = thisPath.node().getPointAtLength(t * marginalLength); | |
var angle = Math.atan2(p.y - p0.y, p.x - p0.x) * 180 / Math.PI;//angle for tangent | |
return "translate(" + p.x + "," + p.y + ") rotate("+((t-1)*90)+")"; | |
} | |
}); | |
/* | |
.attrTween("startOffset", function (d) { | |
return function (t) { | |
return (80 * t) + "%"; | |
}; | |
}) | |
.attrTween("rotate", function (d) { | |
return function (t) { | |
return t *24; | |
}; | |
});*/ | |
} | |
function lineDraw(d) { | |
var R = Math.sqrt(lineWidthScale(d.value) * 10); | |
var sx = xScale(d.source.x); | |
var tx = xScale(d.target.x); | |
var sy = yScale(d.source.y); | |
var ty = yScale(d.target.y); | |
var xx = sx + ((tx - sx) * Math.cos(R * Math.PI / 180) - (ty - sy) * Math.sin(R * Math.PI / 180)); | |
var yy = sy + ((tx - sx) * Math.sin(R * Math.PI / 180) + (ty - sy) * Math.cos(R * Math.PI / 180)); | |
//console.log(xx + "," + yy); | |
var linkData2 = [{ x: sx, y: sy }, { x: xx, y: yy }, { x: tx, y: ty }]; | |
var linetype = ["linear", "step-before", "step-after", "basis", "basis-open", //0,1,2,3,4 | |
"basis-closed", "bundle", "cardinal", "cardinal-open", "cardinal-closed", //5,6,7,8,9 | |
"monotone"]; //10 | |
//이 부분 조정을 통해 곡선 곡률 조정 | |
var line = d3.svg.line() | |
.interpolate(linetype[3]) //bundle | |
.tension(1.6) | |
.x(function (d) { return d.x; }) | |
.y(function (d) { return d.y; }); | |
return line(linkData2); | |
} | |
}; | |
function click(d) { | |
if (d == null) d = 1; //전체패스보기를 위한 부분 | |
clicked = d.name; | |
var multiClick = false; //이부분을 true로 두면 multiClick 가능하게 됨 | |
if (!multiClick) { | |
svg.selectAll(".lines").attr("class", function (d) { | |
return "lines " + d.source.name + " off"; | |
}); | |
svg.selectAll(".arrowHead").attr("class", function (d) { | |
return "arrowHead " + d.source.name + " off"; | |
}); | |
} | |
svg.selectAll(".lines").filter("." + d.name) | |
.attr("class", function () { | |
if (d3.select(this).attr("class").indexOf("on") != -1) { | |
return "lines " + d.name + " off"; | |
} else { | |
return "lines " + d.name + " on"; | |
} | |
}); | |
svg.selectAll(".arrowHead").filter("." + d.name) | |
.attr("class", function () { | |
if (d3.select(this).attr("class").indexOf("on") != -1) { | |
return "arrowHead " + d.name + " off"; | |
} else { | |
return "arrowHead " + d.name + " on"; | |
} | |
}); | |
//console.log(svg.selectAll(".on")[0].length); | |
if (svg.selectAll(".on")[0].length == 0) { //만약 모두 off 상태이면 디폴트이므로 | |
svg.selectAll(".lines") | |
.attr("stroke", function (d) { return color[d.source.group]; }) | |
.attr("stroke-opacity", function (d) { return OpacityScale(d.value); }); | |
svg.selectAll(".arrowHead") | |
.attr("fill", function (d, i) { return color[d.source.group]; }) | |
.attr("opacity", 1) | |
} else { | |
svg.selectAll(".lines").filter(".on") | |
.attr("stroke", function (d) { return color[d.source.group]; }) | |
.attr("stroke-opacity", 1) //그리지 않음. 화살표 가이드 역할만 | |
; | |
svg.selectAll(".lines").filter(".off") | |
.attr("stroke", "black") | |
.attr("stroke-opacity", 0.3) | |
; | |
svg.selectAll(".arrowHead").filter(".off") | |
.attr("fill", "black") | |
.attr("opacity", 0.3) | |
; | |
svg.selectAll(".arrowHead").filter(".on") | |
.attr("fill", function (d, i) { return color[d.source.group]; }) | |
.attr("opacity", 1) | |
; | |
} | |
tick(); | |
} | |
}; //windows.onload | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment