分割チャート。
Last active
February 16, 2018 13:31
-
-
Save shimizu/fed49212b162deaee6726d537b271fbb to your computer and use it in GitHub Desktop.
Clustered Column Chart
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
license: mit |
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> | |
<html lang="jp"> | |
<head> | |
<style> | |
html, body { | |
margin: 0px; | |
padding: 0px; | |
width: 100%; | |
height: 100%; | |
} | |
#chart { | |
width: 80%; | |
height: 80%; | |
border: 8px dashed gray; | |
border-left: none; | |
border-top:none; | |
cursor:all-scroll; | |
} | |
#chart svg{ | |
width: 100%; | |
height: 100%; | |
cursor: default; | |
} | |
.grid .tick line { | |
stroke-dasharray:1; | |
} | |
.topBar { | |
stroke:gray; | |
stroke-width:1; | |
fill:skyblue; | |
} | |
.bottomBar { | |
stroke:gray; | |
stroke-width:1; | |
fill:skyblue; | |
} | |
.splitLine { | |
stroke:black; | |
} | |
</style> | |
<script src="//unpkg.com/babel-standalone@6.26.0/babel.min.js"></script> | |
<script src="//unpkg.com/d3@4.12.2/build/d3.min.js"></script> | |
</head> | |
<body> | |
<div id="chart"> | |
<svg></svg> | |
</div> | |
<script ="text/babel"> | |
const data = [ | |
{title:"アメリカ", value1:86, value2:26}, | |
{title:"日本", value1:48, value2:62}, | |
{title:"中国", value1:62, value2:56}, | |
] | |
const svg = d3.select("#chart").select("svg"); | |
const grid = svg.append("g").classed("grid", true); | |
const plot = svg.append("g").classed("plot", true); | |
const axis = svg.append("g").classed("axis", true); | |
const yTopScale = d3.scaleBand().domain(data.map(d => d.title)); | |
const yBottomScale = d3.scaleBand().domain(data.map(d => d.title)); | |
const xScale = d3.scaleLinear().domain([0, 100]).nice(); | |
render(); | |
function render(){ | |
const m = {top:30, left:60, right:30, bottom:30}; | |
const w = svg.node().clientWidth || svg.node().parentNode.clientWidth; | |
const h = svg.node().clientHeight || svg.node().parentNode.clientHeight; | |
const pw = w - (m.left + m.right); | |
const ph = h - (m.top + m.bottom); | |
const hph = ph/2; | |
yTopScale.range([0, hph]).paddingInner(0.1).paddingOuter(0.25); | |
yBottomScale.range([hph, ph]).paddingInner(0.1).paddingOuter(0.25); | |
xScale.range([0, pw]); | |
//axis layer | |
axis.attr("transform", `translate(${m.left}, ${m.top})`); | |
//top y axis | |
const yTopAxisUpdate = axis.selectAll(".yTopAxis").data([null]); | |
const yTopAxisEnter = yTopAxisUpdate.enter().append("g").classed("yTopAxis", true); | |
const yTopAxis = yTopAxisUpdate.merge(yTopAxisEnter).call( d3.axisLeft().scale(yTopScale).tickSizeOuter(0) ); //ラベルを内向きにする | |
yTopAxis.selectAll(".tick line").remove(); | |
yTopAxis.selectAll(".tick text") | |
const yBottomAxisUpdate = axis.selectAll(".yBottomAxis").data([null]); | |
const yBottomAxisEnter = yBottomAxisUpdate.enter().append("g").classed("yBottomAxis", true); | |
const yBottomAxis = yBottomAxisUpdate.merge(yBottomAxisEnter).call( d3.axisLeft().scale(yBottomScale).tickSizeOuter(0) ); //ラベルを内向きにする | |
yBottomAxis.selectAll(".tick line").remove(); | |
yBottomAxis.selectAll(".tick text"); | |
const splitLineUpdata = axis.selectAll(".splitLine").data([null]); | |
const splitLineEnter = splitLineUpdata.enter().append("line").classed("splitLine", true); | |
const splitLine = splitLineUpdata.merge(splitLineEnter); | |
splitLine | |
.attr("x1", -(m.left/2)) | |
.attr("x2", pw + (m.right/2)) | |
.attr("y1", hph) | |
.attr("y2", hph) | |
//x axis | |
const xAxisUpdate = axis.selectAll(".xAxis").data([null]); | |
const xAxisEnter = xAxisUpdate.enter().append("g").classed("xAxis", true); | |
const renderAxis = d3.axisBottom().scale(xScale); | |
const xAxis = xAxisUpdate.merge(xAxisEnter).call(renderAxis) | |
.attr("transform", `translate(0, ${ph})`); | |
xAxis.select(".domain").remove(); | |
xAxis.selectAll(".tick line").remove(); | |
//grid layer | |
grid.attr("transform", `translate(${m.left}, ${m.top})`); | |
//x grid | |
const xGridUpdate = grid.selectAll(".xGrid").data([null]); | |
const xGridEnter = xGridUpdate.enter().append("g").classed("xGrid", true); | |
const xGrid = xGridUpdate.merge(xGridEnter) | |
.call( d3.axisBottom().scale(xScale).tickSizeInner(-ph).tickFormat(() => null ) ) | |
.attr("transform", `translate(0, ${ph})`); | |
xGrid.select(".domain").remove(); | |
//plot layer | |
plot.attr("transform", `translate(${m.left}, ${m.top})`); | |
//top bar | |
const topBarsUpdate = plot.selectAll(".topBar").data(data); | |
const topBarsEnter = topBarsUpdate.enter().append("rect").classed("topBar", true); | |
const topBars = topBarsUpdate.merge(topBarsEnter) | |
.attr("height", yTopScale.bandwidth()) | |
.attr("width", d => xScale(d.value1)) | |
.attr("y", d => yTopScale(d.title)) | |
.attr("x", 0.5) | |
; | |
//bottom bar | |
const bottomBarsUpdate = plot.selectAll(".bottomBar").data(data); | |
const bottomBarsEnter = bottomBarsUpdate.enter().append("rect").classed("bottomBar", true); | |
const bottomBars = bottomBarsUpdate.merge(bottomBarsEnter) | |
.attr("height", yBottomScale.bandwidth()) | |
.attr("width", d => xScale(d.value2)) | |
.attr("y", d => yBottomScale(d.title)) | |
.attr("x", 0.5) | |
; | |
} | |
//divエレメントをドラッグでリサイズできるようにする。 | |
const dispatch = d3.dispatch("resize"); | |
dispatch.on("resize", render); | |
setResizeControler(); | |
function setResizeControler(){ | |
const drag = d3.drag() | |
.on("drag", resized) | |
d3.select("#chart") | |
.call(drag); | |
function resized(e){ | |
const s = d3.event.sourceEvent; | |
const w = (s.pageX < 300) ? 300 : s.pageX; | |
const h = (s.pageY < 200) ? 200 : s.pageY; | |
console.log(h) | |
d3.select(this) | |
.style("width", `${w}px`) | |
.style("height", `${h}px`) | |
.attr("data-test", "test") | |
dispatch.call("resize"); | |
} | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment