Ordiran scaleにinvertメソッドがなかったので、代価案を考えた。
Built with blockbuilder.org
license: mit |
Ordiran scaleにinvertメソッドがなかったので、代価案を考えた。
Built with blockbuilder.org
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8" /> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"/> | |
<title>D3 ver.4 - ordinal scale invert</title> | |
<style> | |
html, body { | |
position:fixed; | |
top:0;right:0;bottom:0;left:0; | |
width: 100%; | |
height: 100%; | |
padding: 0px; | |
margin: 0px; | |
} | |
svg { | |
width: 900px; | |
height:500px; | |
} | |
</style> | |
</head> | |
<body> | |
<svg id="example"></svg> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.1.1/d3.min.js"></script> | |
<script> | |
var width = document.querySelector("svg").clientWidth | |
var height = document.querySelector("svg").clientHeight | |
var margin = {top:50, left:50, bottom:50, right:50 } | |
var svg = d3.select("#example") | |
var AxisLayer = svg.append("g").attr("class", "AxisLayer") | |
var chartLayer = svg.append("g").attr("class", "chartLayer") | |
.attr("transform", "translate("+[margin.left, margin.top]+")") | |
var overLayer = svg.append("g").attr("class", "overLayer") | |
.attr("transform", "translate("+[margin.left, margin.top]+")") | |
var guideLine = overLayer.append("line") | |
.attr("class", "guideLine") | |
.attr("x1", 0) | |
.attr("y1", 0) | |
.attr("x2", 0) | |
.attr("y2", height-(margin.top+margin.bottom)) | |
.attr("stroke", "red") | |
var eventCapture = chartLayer.append("rect") | |
.attr("width", width-(margin.left+margin.right)) | |
.attr("height", height-(margin.top+margin.bottom)) | |
.attr("opacity", 0) | |
var xScale = d3.scaleBand() | |
var yScale = d3.scaleLinear() | |
var xAxis = d3.axisBottom() | |
var yAxis = d3.axisLeft() | |
xScale.domain(["A", "B", "C", "D", "E", "F", "G", "H"]).range([0, width-(margin.top+margin.bottom)]) | |
yScale.domain([0, 1000]).range([height-(margin.top+margin.bottom), 0]) | |
// custom invert function | |
xScale.invert = (function(){ | |
var domain = xScale.domain() | |
var range = xScale.range() | |
var scale = d3.scaleQuantize().domain(range).range(domain) | |
return function(x){ | |
return scale(x) | |
} | |
})() | |
xAxis.scale(xScale) | |
yAxis.scale(yScale) | |
drawAxis() | |
eventCapture | |
.on("mousemove", function(e){ | |
var xy = d3.mouse(eventCapture.node()) | |
var d = xScale.invert(xy[0]) | |
var nx = xScale(d) + (xScale.bandwidth()/2) | |
guideLine.transition().duration(100).attr("x1", nx).attr("x2", nx) | |
}) | |
function drawAxis(){ | |
var t = d3.transition() | |
.duration(500) | |
var x = AxisLayer.selectAll(".x") | |
.data(["dummy"]) | |
var newX = x.enter().append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate("+[margin.left, height-margin.top]+")") | |
x.merge(newX).transition(t).call(xAxis) | |
var y = AxisLayer.selectAll(".y") | |
.data(["dummy"]) | |
var newY = y.enter().append("g") | |
.attr("class", "y axis") | |
.attr("transform", "translate("+[margin.left, margin.top]+")") | |
y.merge(newY).transition(t).call(yAxis) | |
} | |
</script> | |
</body> | |
</html> |
Wow, this is a very good solution, thank you!