Skip to content

Instantly share code, notes, and snippets.

@tom-christie
Last active March 1, 2016 21:44
Show Gist options
  • Save tom-christie/7424b0bf753367e35b42 to your computer and use it in GitHub Desktop.
Save tom-christie/7424b0bf753367e35b42 to your computer and use it in GitHub Desktop.
Tributary inlet
{"description":"Tributary inlet","endpoint":"","display":"svg","public":true,"require":[],"fileconfigs":{"inlet.js":{"default":true,"vim":false,"emacs":false,"fontSize":12},"_.md":{"default":true,"vim":false,"emacs":false,"fontSize":12},"config.json":{"default":true,"vim":false,"emacs":false,"fontSize":12},"style.css":{"default":true,"vim":false,"emacs":false,"fontSize":12}},"fullscreen":false,"play":false,"loop":false,"restart":false,"autoinit":true,"pause":true,"loop_type":"pingpong","bv":false,"nclones":15,"clone_opacity":0.4,"duration":3000,"ease":"linear","dt":0.01,"ajax-caching":true,"thumbnail":"http://i.imgur.com/ZGfBLna.png"}
debug = false;
//DATA
var data = [
{"Course":"MyCourse1",
"Standard":"MyStandard1",
values:{
"val1":5,
"val2":0.2,
"val3":100
}
},
{"Course":"MyCourse1",
"Standard":"MyStandard2",
values:{
"val1":5,
"val2":0.2,
"val3":100
}
},
{"Course":"MyCourse2",
"Standard":"MyStandard1",
values:{
"val1":5,
"val2":0.2,
"val3":100
}
},
{"Course":"MyCourse2",
"Standard":"MyStandard3",
values:{
"val1":5,
"val2":0.2,
"val3":100
}
},
{"Course":"MyCourse2",
"Standard":"MyStandard6",
values:{
"val1":5,
"val2":0.2,
"val3":100
}
},
{"Course":"MyCourse3",
"Standard":"MyStandard2",
values:{
"val1":5,
"val2":0.2,
"val3":100
}
},{"Course":"MyCourse3",
"Standard":"MyStandard4",
values:{
"val1":5,
"val2":0.2,
"val3":100
}
},
{"Course":"MyCourse4",
"Standard":"MyStandard4",
values:{
"val1":5,
"val2":0.2,
"val3":100
}
},
{"Course":"MyCourse4",
"Standard":"MyStandard4",
values:{
"val1":5,
"val2":0.2,
"val3":100
}
},
{"Course":"MyCourse4",
"Standard":"MyStandard5",
values:{
"val1":5,
"val2":0.2,
"val3":100
}
},
{"Course":"MyCourse6",
"Standard":"MyStandard6",
values:{
"val1":5,
"val2":0.2,
"val3":100
}
},
{"Course":"MyCourse6",
"Standard":"MyStandard2",
values:{
"val1":5,
"val2":0.2,
"val3":100
}
}
];
var sectionData = [
{
"Course":"MyCourse1",
"Sections":[
{
title:"SectionTitle1",
teachers:["Teacher1","Teacher2"]
},
{
title:"SectionTitle2",
teachers:["Teacher2"]
}
]
},
{
"Course":"MyCourse2",
"Sections":[
{
title:"SectionTitle1",
teachers:["Teacher2"]
},
{
title:"SectionTitle2",
teachers:["Teacher3"]
}
]
},
{
"Course":"MyCourse3",
"Sections":[
{
title:"SectionTitle1",
teachers:["Teacher1","Teacher2"]
},
{
title:"SectionTitle2",
teachers:["Teacher2"]
},
{
title:"SectionTitle3",
teachers:["Teacher2"]
}
]
},
{
"Course":"MyCourse4",
"Sections":[
{
title:"SectionTitle2",
teachers:["Teacher2"]
}
]
},
{
"Course":"MyCourse5",
"Sections":[
{
title:"SectionTitle1",
teachers:["Teacher1","Teacher2"]
},
{
title:"SectionTitle2",
teachers:["Teacher2"]
}
]
},
{
"Course":"MyCourse6",
"Sections":[
{
title:"SectionTitle1",
teachers:["Teacher1","Teacher2"]
},
{
title:"SectionTitle2",
teachers:["Teacher2"]
}
]
}
]
var courses = unique(data.map(function(d){return d.Course}))
.sort(function(a,b){return a>b?1:-1});
var standards = unique(data.map(function(d){return d.Standard}))
.sort(function(a,b){return a>b?1:-1});
// set size of chart area
var boxHeight = 43;
var boxWidth = 43;
var gap = 6;
var fontSize = 12;
var maxCourseDescriptionWidth = 100;
var margin = {top: 114, right: 20, bottom: 20, left: 181},
width = (boxWidth+gap) * standards.length,
height = (boxHeight+gap) * courses.length,
cwidth = 50;
var xScale = d3.scale.ordinal()
.domain(standards.concat(""))
.rangePoints([0,width]);
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
var courseScale = d3.scale.ordinal()
.domain(courses.concat(""))
.rangePoints([0,height]);
var courseAxis = d3.svg.axis()
.scale(courseScale)
.orient("right");
//draw chart
var svg = d3.select("svg")
var horizontalAxis = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(" + (margin.left+gap) + "," + margin.top + ")")
.call(xAxis)
horizontalAxis.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "1.547047534592em")
.attr("dy", "-3.2em")
.attr("transform", function(d) {
return "rotate(50)"
})
var courseAxisGroup = svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + margin.left + "," + (margin.top + gap) + ")")
.call(courseAxis)
courseAxisGroup.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-2em")
.attr("dy", boxHeight/2 + fontSize/2 + "px")
.attr("transform", function(d) {
return "rotate(0)"
});
///// for debug only
if(debug){
var xScaleDebug = d3.scale.ordinal()
.domain(standards.concat(""))
.rangePoints([0,width]);
var xAxisDebug = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.tickSize(height)
svg.append("g")
.attr("class", "x axis")
.style('opacity',0.1)
.attr("transform", "translate(186," + 115 + ")")
.call(xAxisDebug)
.selectAll('text').remove()
var courseScaleDebug = d3.scale.ordinal()
.domain(courses.concat(""))
.rangePoints([0,height]);
var xAxisDebug = d3.svg.axis()
.scale(courseScale)
.orient("right")
.tickSize(width)
svg.append("g")
.attr("class", "y axis")
.style('opacity',0.1)
.attr("transform", "translate(177," + 123 + ")")
.call(xAxisDebug)
.selectAll('text').remove()
}
///////
var courseRowsAll = svg.append('g').attr('class','courseRowsAll')
var courseRowsSingle = courseRowsAll.selectAll('courseRow')
.data(courses)
.enter()
.append('g')
.attr('class',function(d){return 'courseRow-' + d})
courseRowsSingle.selectAll('courseRow').append('rect')
.attr('class','courseRowRect')
.attr({
width: width + maxCourseDescriptionWidth,
height: boxHeight + gap,
x: margin.left - maxCourseDescriptionWidth + gap,
y: function(d){console.log(d);return courseScale(d) + margin.top + gap},
stroke: d3.rgb(188,188,188),
fill:d3.rgb(56,156,252),
"stroke-width":0,
opacity:0.2
})
.attr('id',function(d){return d + '-courseMouseoverBackground'})
//var courseMouseoverBackground = courseRows.selectAll('courseRow')
// .data(courses)
// .enter().append("rect")
/* .attr({
width: width + maxCourseDescriptionWidth,
height: boxHeight + gap,
x: margin.left - maxCourseDescriptionWidth + gap,
y: function(d){console.log(d);return courseScale(d) + margin.top + gap},
stroke: d3.rgb(188,188,188),
fill:d3.rgb(56,156,252),
"stroke-width":0,
opacity:0
})
.attr('id',function(d){return d + '-courseMouseoverBackground'})
*/
/*
var courseBoxes = courseRows.append("g").selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr({
width: boxWidth,
height: boxHeight,
x: function(d){return xScale(d.Standard) + margin.left+1.5*gap},
y: function(d){return courseScale(d.Course) + margin.top + 1.5*gap},
stroke: d3.rgb(188,188,188),
fill:d3.rgb(56,156,252),
"stroke-width":0,
rx:2,
ry:2
});
*/
var courseMouseoverForeground = courseRows.append('g')
.append("rect")
.attr({
width: width + maxCourseDescriptionWidth,
height: boxHeight + gap,
x: margin.left - maxCourseDescriptionWidth + gap,
y: function(d){console.log(d);return courseScale(d) + margin.top + gap},
stroke: d3.rgb(188,188,188),
fill:d3.rgb(56,156,252),
"stroke-width":0,
opacity:0.01
})
.attr('id',function(d){return d + '-courseMouseoverForeground'})
.on('mouseover',function(d){
var targetID = this.id.split('-')[0] + '-courseMouseoverBackground';
console.log(targetID)
d3.select('#' + targetID).style('opacity',0.2)
})
.on('mouseout',function(d){
var targetID = this.id.split('-')[0] + '-courseMouseoverBackground'
d3.select('#' + targetID).style('opacity',0)
})
.on('click',function(d){
drillCoursesToSections(d);
})
//// Legend
var legendBoxHeight = 13;
var legendBoxWidth = legendBoxHeight;
var legendGap = 7;
var legendMargin = 20;
var measures = unique(flatten(data.map(function(d){return Object.keys(d.values)})))
var legendColors = d3.scale.category10(measures);
var legend = svg.append('g')
.attr('class','legend')
.attr("transform", "translate(" + (margin.left + width + legendMargin) + "," + 123 + ")")
//legned title
legend.append('text').text('Values')
.style('font-size',15)
var legendMouseoverBackground = legend.selectAll('legendMouseoverBackground')
.data(measures)
.enter()
.append("rect")
.attr({
width: 100,
height: legendBoxHeight+legendGap,
x: function(d,i){return -legendGap/2},
y: function(d,i){return legendGap-1+i*(legendBoxHeight+legendGap)},
stroke: d3.rgb(188,188,188),
fill:function(d,i){return "#e0e0e0"},
"stroke-width":0,
rx:0,
ry:0,
opacity:0.01
})
.attr('id',function(d){return d + '-legendMouseoverBackground'});
var legendEntries = legend.selectAll('legendEntries')
.data(measures)
.enter();
legendEntries
.append("rect")
.attr({
width: legendBoxWidth,
height: legendBoxHeight,
x: function(d,i){return 0},
y: function(d,i){return 10+i*(legendBoxHeight+legendGap)},
stroke: d3.rgb(188,188,188),
fill:function(d,i){return legendColors(d)},
"stroke-width":0,
rx:2,
ry:2
});
legendEntries.append('text')
.text(function(d){return d})
.attr({
x:legendBoxHeight+legendGap,
y: function(d,i){return 13+legendGap+i*(legendBoxHeight+legendGap)}
})
var legendMouseoverForeground = legend.selectAll('legendMouseoverForeground')
.data(measures)
.enter()
.append("rect")
.attr({
width: 100,
height: legendBoxHeight+legendGap,
x: function(d,i){return -legendGap/2},
y: function(d,i){return legendGap-1+i*(legendBoxHeight+legendGap)},
stroke: d3.rgb(188,188,188),
fill:function(d,i){return "#e0e0e0"},
"stroke-width":0,
rx:0,
ry:0,
opacity:0.1
})
.attr('id',function(d){return d + '-legendMouseoverForeground'})
.on('mouseover',function(d){
var targetID = this.id.split('-')[0] + '-legendMouseoverBackground';
console.log(targetID)
d3.select('#' + targetID).style('opacity',0.3)
})
.on('mouseout',function(d){
var targetID = this.id.split('-')[0] + '-legendMouseoverBackground'
d3.select('#' + targetID).style('opacity',0)
});
//update based on course click
var drillCoursesToSections = function(course){
//vertical axis
//shrink current course axis and move it up.
courseScale.domain([course])
.rangePoints([0,-boxHeight*2.5])
courseAxisGroup
.transition()
.duration(1000)
.call(courseAxis);
courseAxisGroup.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-2em")
.attr("dy", boxHeight/2 + 7 + "px")
.attr("transform", function(d) {
return "rotate(0)"
});
/*var sections = sectionData.filter(function(d){return d.Course == course})[0].Sections;
var sectionTitles = sections.map(function(d){return d.title});
courseScale.domain(sectionTitles.concat(""));
courseAxis.scale(courseScale);
verticalAxis
.transition()
.duration(1000)
.call(courseAxis);
verticalAxis.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-2em")
.attr("dy", boxHeight/2 + 7 + "px")
.attr("transform", function(d) {
return "rotate(0)"
});
*/
//horizontal axis
var standards = data.filter(function(d){return d.Course == course})
.map(function(d){return d.Standard});
console.log(standards)
xScale.domain(standards.concat(""));
xAxis.scale(xScale);
horizontalAxis
.transition()
.duration(1000)
.call(xAxis);
horizontalAxis.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "1.547047534592em")
.attr("dy", "-3.2em")
.attr("transform", function(d) {
return "rotate(50)"
})
}
/// Helpers
function unique(arr) {
var u = {}, a = [];
for(var i = 0, l = arr.length; i < l; ++i){
if(!u.hasOwnProperty(arr[i])) {
a.push(arr[i]);
u[arr[i]] = 1;
}
}
return a;
}
function flatten(arrays){
return [].concat.apply([], arrays);
}
body{
background-color:white;
}
body {
font: 12px sans-serif;
}
.axis line,
.axis path {
fill: none;
stroke: #000;
stroke-width:2px;
shape-rendering: crispEdges;
}
.axis line {
stroke: #777;
stroke-width:1;
opacity:0.4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment