Skip to content

Instantly share code, notes, and snippets.

@shimizu
Last active October 26, 2017 10:08
Show Gist options
  • Save shimizu/808e0f5cadb6a63f28bb00082dc8fe3f to your computer and use it in GitHub Desktop.
Save shimizu/808e0f5cadb6a63f28bb00082dc8fe3f to your computer and use it in GitHub Desktop.
Inversion with ordinal scale
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>
@PedroF20
Copy link

Wow, this is a very good solution, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment