Skip to content

Instantly share code, notes, and snippets.

@shimizu
Last active February 16, 2018 02:32
Show Gist options
  • Save shimizu/8fe074286cb4348609170d979895b1f5 to your computer and use it in GitHub Desktop.
Save shimizu/8fe074286cb4348609170d979895b1f5 to your computer and use it in GitHub Desktop.
D3 Axis Tips#2" - Custom Tick Label
license: mit

Axis Tips #2

軸(Axis)のtick(ラベル)をカスタマイズして表示する。

青枠はドラッグしてサイズを変更することができます。

<!DOCTYPE html>
<html lang="jp">
<meta name="viewport" content="width=device-width, initial-scale=1">
<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;
}
</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 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 yScale = d3.scaleLinear().domain([100, 0]);
const xScale = d3.scaleTime().domain([new Date(2016,1,1), new Date(2018,1,1)])
const yearFormat = d3.timeFormat("%Y年");
const monthFormat = d3.timeFormat("%m月");
render();
function render(){
const m = {top:40, left:80, right:40, bottom:40};
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 breakpoint = 480; //スマートフォン用のブレイクポイント
yScale.range([0, ph]);
xScale.range([0, pw]);
//axis layer
axis.attr("transform", `translate(${m.left}, ${m.top})`);
//y axis
const yAxisUpdate = axis.selectAll(".yAxis").data([null]);
const yAxisEnter = yAxisUpdate.enter().append("g").classed("yAxis", true);
const renderYAxis = d3.axisLeft().scale(yScale)
.tickFormat( (d,i) => {
if(i === 0) return `${d} (千万円)`;
return d;
});
const yAxis = yAxisUpdate.merge(yAxisEnter).call(renderYAxis);
yAxis.select(".domain").remove();
yAxis.selectAll(".tick line").remove();
//x axis
const xAxisUpdate = axis.selectAll(".xAxis").data([null]);
const xAxisEnter = xAxisUpdate.enter().append("g").classed("xAxis", true);
const renderXAxis = d3.axisBottom().scale(xScale)
.tickFormat(d => { //tick custom
const year = yearFormat(d);
const month = monthFormat(d).replace(/^0/, "");
return (d.getMonth() == 0 && w > breakpoint) ? year + month: month; //1月の軸だけ年をつけて表示する
});
const xAxis = xAxisUpdate.merge(xAxisEnter).call(renderXAxis)
.attr("transform", `translate(0, ${ph})`);
xAxis.select(".domain").remove();
xAxis.selectAll(".tick line").remove();
//grid layer
grid.attr("transform", "translate("+[m.left, m.top]+")");
//y grid
const yGridUpdate = grid.selectAll(".yGrid").data([null]);
const yGridEnter = yGridUpdate.enter().append("g").classed("yGrid", true);
const yGrid = yGridUpdate.merge(yGridEnter).call( d3.axisLeft().scale(yScale).tickSizeInner(-pw).tickFormat(()=>null) )
yGrid.select(".domain").remove();
}
//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;
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