Skip to content

Instantly share code, notes, and snippets.

@fdnklg
Created January 13, 2019 12:42
Show Gist options
  • Save fdnklg/131b1bd5d107d457897c7b3c4b6645ed to your computer and use it in GitHub Desktop.
Save fdnklg/131b1bd5d107d457897c7b3c4b6645ed to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<style>
svg {
display: block;
margin: 0 auto;
}
.axis .domain {
display: none;
}
.axis--x text {
fill: #999;
}
.axis--x line {
stroke: #aaa;
}
.axis--activity .tick line {
display: none;
}
.axis--activity text {
font-size: 12px;
fill: #777;
}
.chart_grp-count-relative {
padding-left: 5px;
}
path {
opacity: 0.3
}
</style>
</head>
<body>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
var numHorizons = 4;
var margin = { top: 30, right: 10, bottom: 30, left: 0 },
width = 300 - margin.left - margin.right,
height = 85 - margin.top - margin.bottom,
bisectDate = d3.bisector(function(d) { return d.time; }).left;
var formatTime = d3.timeFormat('%Y');
var wrapper = d3.select('body').append('div')
.classed('charts', true)
var x = function(d) { return d.time; },
xScale = d3.scaleTime().range([0, width]),
xValue = function(d) { return xScale(x(d)); },
xAxis = d3.axisBottom(xScale).tickFormat(formatTime).ticks(6);
var y = function(d) { return d.value; },
yScale = d3.scaleLinear().clamp(true),
y0Value = function(d) { return yScale(0); }
y1Value = function(d) { return yScale(y(d)); };
var activity = function(d) { return d.key; },
activityScale = d3.scaleBand().range([0, height]).padding(0.05),
activityValue = function(d) { return activityScale(activity(d)); },
activityAxis = d3.axisLeft(activityScale);
var horizonScale = d3.scaleQuantize()
.range(d3.range(numHorizons));
var fill = function(d) { return d.yExtent[0]; },
fillScale = d3.scaleLinear().range(['lavender', 'purple']).interpolate(d3.interpolateHcl),
fillValue = function(d) {
return fillScale(fill(d));
};
var area = d3.area()
.x(xValue)
.y0(y0Value)
.y1(y1Value);
function peakTime(d) {
var i = d3.scan(d.values, function(a, b) { return y(b) - y(a); });
console.log(i)
return d.values[i].value;
};
// take into account for future coding projects
// function row(d) {
// return {
// activity: d.activity,
// time: parseTime(d.time),
// value: +d.p_smooth
// };
// }
function mouseover() {
console.log('mouse over')
}
function mouseout() {
console.log('mouse out')
}
// d3.tsv('data.tsv', row).then((dataFlat) => {
d3.json('grps_over_time_restructured.json'). then(data => {
data.forEach(category => {
category.values.forEach(value => {
value.time = new Date(value.time);
})
})
data.forEach((category,catIndex) => {
function mousemove() {
let data = category.values
var x0 = xScale.invert(d3.mouse(this)[0]),
i = bisectDate(data, x0, 1)
d0 = data[i - 1],
d1 = data[i],
dNew = x0 - d0.date > d1.date - x0 ? d1 : d0;
grp_count.text(dNew.value)
console.log(dNew.value)
focus.attr("transform", "translate(" + xScale(dNew.time) + ")");
focus.select("text").text((d.close));
}
let d = category;
let grp_count_total = category.values[category.values.length - 1].value;
const chart_wrapper = wrapper.append('div')
.classed('chart_wrapper', true)
const chart_text_wrapper = wrapper.append('div')
.classed('chart_text_wrapper', true)
const title = chart_text_wrapper.append('span')
.classed('chart_title', true)
.text(category.key)
const grp_count = chart_text_wrapper.append('span')
.classed('chart_grp-count', true)
.text(grp_count_total)
const grp_count_relative = chart_text_wrapper.append('span')
.classed('chart_grp-count-relative', true)
.text(Math.round((grp_count_total / 3300) * 100) + '%')
var svg = chart_wrapper.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
const focus = svg.append("g")
.attr("class", "focus")
.style("display", "none");
focus.append("rect")
.attr("width", 1)
.attr("height", 60)
.attr('fill', 'black');
// console.log(d3.extent(dataFlat, y))
// Sort by time
// dataFlat.sort(function(a, b) { return a.time - b.time; });
// var data = d3.nest()
// .key(function(d) { return d.activity; })
// .entries(dataFlat);
// console.log(data);
// Sort activities by growth
data.sort(function(a, b) { return peakTime(b) - peakTime(a); });
xScale.domain([new Date('2008-01-01'),new Date('2019-02-01')]);
// activityScale.domain(data.map(function(d) { return d.key; }));
yScale.range([activityScale.bandwidth(), 0]);
// horizonScale.domain(d3.extent(dataFlat, y));
horizonScale.domain([0,50]);
svg.append('g').attr('class', 'axis axis--x')
.attr('transform', 'translate(0,' + height + ')')
.call(xAxis)
svg.append('g').attr('class', 'axis axis--activity')
.call(activityAxis);
var gActivity = svg
.append('g')
.attr('class', 'activity activity--' + d.key)
.attr('transform', function() {
var ty = activityValue(d);
return 'translate(0,' + ty + ')';
})
.on("mousemove", mousemove)
.on("mouseover", function() { focus.style("display", null); })
.on("mouseout", function() {
grp_count.text(grp_count_total)
focus.style("display", "none");
})
function horizonData(d) {
return horizonScale.range()
.map(function(i) {
return {
yExtent: horizonScale.invertExtent(i),
key: d.key,
values: d.values
};
});
}
var gHorizon = gActivity.selectAll('.horizon').data(horizonData(d))
.enter().append('path')
.attr('class', 'horizon')
.each(function(d,i) {
// TODO: create separate y-scales using d3.local()
yScale.domain(d.yExtent);
d3.select(this)
.attr('d', area(d.values));
})
.style('fill', fillValue);
})
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment