Skip to content

Instantly share code, notes, and snippets.

@aholachek
Last active May 21, 2017 10:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aholachek/bfc81defddadc06e72a1c167919f755e to your computer and use it in GitHub Desktop.
Save aholachek/bfc81defddadc06e72a1c167919f755e to your computer and use it in GitHub Desktop.
Continuous Scale Exploration
var svg = d3.select('svg')
var margin = {top: 40, right: 40, bottom: 40, left: 40}
var width = svg.attr('width') - margin.left - margin.right
var height = svg.attr('height') - margin.top - margin.bottom
var g = svg.append('g').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
var data = d3.range(100000).map(function (n){
if (n % 1000 === 0){
return { x : n, y : n}
}
}).filter(function (n){ return (n && n.x); })
var x
var y = d3.scaleLinear().domain(d3.extent(data.map(function (d){ return d.y; }))).rangeRound([height, 0])
var color = d3.scaleSequential(d3.interpolateRainbow).domain(d3.extent(data.map(function (d){ return d.x; })))
var xAxis = g.append("g")
.attr("transform", "translate(0," + height + ")")
var yAxis = g.append("g")
.call(d3.axisLeft(y))
var circles = g.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('r', '3')
.attr('fill', function (d){ return color(d.x); })
function updateXScale(scale) {
if (scale.name === 'scalePow(2)'){
x = d3.scalePow().exponent(2).domain(d3.extent(data.map(function (d){ return d.x; }))).rangeRound([0, width])
} else if (scale.name === 'scaleQuantize'){
x = d3.scaleQuantize().domain(d3.extent(data.map(function (d){ return d.x; }))).range([0, width/5, 2 * width/5, 3 * width/5, 4 * width/5, width])
}
else {
x = d3[scale.name]().domain(d3.extent(data.map(function (d){ return d.x; }))).rangeRound([0, width])
}
xAxis.transition().call(d3.axisBottom(x).tickFormat(d3.format(".0s")))
circles
.attr('cy', function (d){ return y(d.y); })
.transition()
.delay(function (d,i){ return i * 5; })
.attr('cx', function (d){ return x(d.x); })
d3.select('h1').text(scale.name)
d3.select('h2').text(scale.equation)
}
var scales = [{name : 'scaleLinear', equation : 'y = mx + b'},
{name : 'scalePow(2)', equation : 'y = mx^2 + b'},
{name : 'scaleSqrt', equation : 'y = mx^0.5 + b'},
{name : 'scaleLog', equation : 'y = m log(x) + b'},
{name : 'scaleQuantize', equation : 'y = m round(x) + b'}
]
var fieldset = d3.select('fieldset.scales')
scales.forEach(function (s,i){
var label = fieldset.append('label')
var input = label.append('input')
.attr('type', 'radio')
.attr('value', s.name)
.attr('name', 'scale-type')
.on('change', function(){
updateXScale(s)
})
if (i === 0){
input.attr('checked', true)
}
label.append('span')
.text(s.name)
})
updateXScale(scales[0])

Simple exploration of d3 continuous scales.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style>
body {
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Roboto", "Helvetica Neue", Arial, sans-serif;
}
fieldset.scales label {
display: inline-block;
margin-right: 1rem;
}
fieldset {
border: 0;
}
legend {
font-weight: 800;
}
h1,
h2 {
margin: 0.5rem 0;
}
</style>
</head>
<body>
<h1></h1>
<h2></h2>
<svg width="960" height="400"></svg>
<fieldset class="scales">
<legend>Choose an x-axis scale</legend>
</fieldset>
<script src="//d3js.org/d3.v4.min.js" charset="utf-8"></script>
<!-- <script src="./../node_modules/d3/build/d3.js" charset="utf-8"></script> -->
<!-- <script src="//cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js" charset="utf-8"></script> -->
<!-- d3 code -->
<script src=".script-compiled.js" charset="utf-8"></script>
<!-- render code -->
<script>
// change frame height
d3.select(self.frameElement).style('height', '550px');
</script>
</body>
</html>
const svg = d3.select('svg')
const margin = {top: 40, right: 40, bottom: 40, left: 40}
const width = svg.attr('width') - margin.left - margin.right
const height = svg.attr('height') - margin.top - margin.bottom
const g = svg.append('g').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
const data = d3.range(100000).map((n)=> {
if (n % 1000 === 0){
return { x : n, y : n}
}
}).filter(n=>(n && n.x))
let x
const y = d3.scaleLinear().domain(d3.extent(data.map((d)=>d.y))).rangeRound([height, 0])
const color = d3.scaleSequential(d3.interpolateRainbow).domain(d3.extent(data.map(d=>d.x)))
const xAxis = g.append("g")
.attr("transform", "translate(0," + height + ")")
const yAxis = g.append("g")
.call(d3.axisLeft(y))
const circles = g.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('r', '3')
.attr('fill', (d)=> color(d.x))
function updateXScale(scale) {
if (scale.name === 'scalePow(2)'){
x = d3.scalePow().exponent(2).domain(d3.extent(data.map((d)=>d.x))).rangeRound([0, width])
} else if (scale.name === 'scaleQuantize'){
x = d3.scaleQuantize().domain(d3.extent(data.map((d)=>d.x))).range([0, width/5, 2 * width/5, 3 * width/5, 4 * width/5, width])
}
else {
x = d3[scale.name]().domain(d3.extent(data.map((d)=>d.x))).rangeRound([0, width])
}
xAxis.transition().call(d3.axisBottom(x).tickFormat(d3.format(".0s")))
circles
.attr('cy', (d)=> y(d.y))
.transition()
.delay((d,i)=> i * 5)
.attr('cx', (d)=> x(d.x))
d3.select('h1').text(scale.name)
d3.select('h2').text(scale.equation)
}
const scales = [{name : 'scaleLinear', equation : 'y = mx + b'},
{name : 'scalePow(2)', equation : 'y = mx^2 + b'},
{name : 'scaleSqrt', equation : 'y = mx^0.5 + b'},
{name : 'scaleLog', equation : 'y = m log(x) + b'},
{name : 'scaleQuantize', equation : 'y = m round(x) + b'}
]
const fieldset = d3.select('fieldset.scales')
scales.forEach((s,i)=>{
const label = fieldset.append('label')
const input = label.append('input')
.attr('type', 'radio')
.attr('value', s.name)
.attr('name', 'scale-type')
.on('change', function(){
updateXScale(s)
})
if (i === 0){
input.attr('checked', true)
}
label.append('span')
.text(s.name)
})
updateXScale(scales[0])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment