Skip to content

Instantly share code, notes, and snippets.

@DeBraid
Created December 21, 2013 22:07
Show Gist options
  • Save DeBraid/8075741 to your computer and use it in GitHub Desktop.
Save DeBraid/8075741 to your computer and use it in GitHub Desktop.
Stock chart: gradient + tooltip (27 Jan)
{"description":"Stock chart: gradient + tooltip (27 Jan)","endpoint":"","display":"svg","public":true,"require":[],"fileconfigs":{"inlet.js":{"default":true,"vim":false,"emacs":false,"fontSize":12},"quote.json":{"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},"sample.js":{"default":true,"vim":false,"emacs":false,"fontSize":12},"sample.json":{"default":true,"vim":false,"emacs":false,"fontSize":12},"style.css":{"default":true,"vim":false,"emacs":false,"fontSize":12},"buttons,js":{"default":true,"vim":false,"emacs":false,"fontSize":12},"buttons.js":{"default":true,"vim":false,"emacs":false,"fontSize":12},"dropdown.js":{"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,"thumbnail":"http://i.imgur.com/W3cqIY2.png"}
// loading sample.json
var sample2 = tributary.sample.sample2;
// date manipulation to format
sample2.forEach(function(d) { d.time = new Date(d.time * 1000); });
// helpers and constants
var margin = {"top": 50, "right": 83, "bottom": 56, "left": 50};
var width = 676 + margin.right + margin.left;
var height = 390 + margin.top + margin.bottom;
var timeFormat = d3.time.format("%c");
var X = width/sample2.length*0.25;
var bisectDate = d3.bisector(function(d) { return d.time; }).left;
// drop down menu
var chartOptions = ["candle", "line", "area"];
d3.select(".tributary_svg")
.append("foreignObject")
.attr("height", 100)
.attr("width", 300)
.attr("transform", "translate(" + (width*0.7 - margin.right) + "," + margin.top + ")")
.append("xhtml:select")
.attr("id", "drop-down")
.selectAll("option")
.data(chartOptions)
.enter()
.append("option")
.text(function(d) {return d;})
.attr("value", function(d){ return d; });
d3.select("#drop-down").on("change", function () {
selected = this.value;
console.log(selected);
});
// set up chart
var svg = d3.select("svg").attr("width", width).attr("height", height).style("position", "relative");
var chart = d3.select("svg");
// find data range
var xDomain = d3.extent(sample2, function (d, i){ return d.time; });
var yMin = d3.min(sample2, function(d){ return Math.min(d.low); });
var yMax = d3.max(sample2, function(d){ return Math.max(d.high); });
// scale using ranges, add 10pc padding to x-domain
var xScale = d3.time.scale()
.domain(xDomain);
xScale.domain([-0.1,1.1].map(xScale.invert))
.range([margin.left, width - margin.right]);
var yScale = d3.scale.linear()
.domain([yMin, yMax])
.range([height - margin.top, margin.bottom]);
// set up axes
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(10)
.tickPadding(10);
// .tickFormat(timeFormat)
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("right")
.tickValues(yScale.domain());
// draw chart by type
var chartDraw = {
candle: function(){
chart.selectAll("line.candle")
.data(sample2)
.enter()
.append("svg:line")
.attr({
"x1": function(d,i) { return xScale(d.time) - X*0.5; },
"x2": function(d,i) { return xScale(d.time) - X*0.5; },
"y1": function(d,i) { return yScale(d.high); },
"y2": function(d,i) { return yScale(d.low); },
"stroke": "black"
});
chart.selectAll("rect.candle")
.data(sample2)
.enter()
.append("svg:rect")
.attr({
"width": function(d){ return X},
"x": function(d,i) { return xScale(d.time) - X; },
"y": function(d,i) { return yScale(Math.max(d.open, d.close)); },
"height": function(d,i) { return yScale(Math.min(d.open, d.close)) - yScale(Math.max(d.open, d.close)); },
"fill": function (d) { return d.open > d.close ? "#dc432c" : "#0CD1AA" },
"stroke": "black"
});
},
line: function(){
var line = d3.svg.line()
.x(function(d){ return xScale(d.time); })
.y(function(d){ return yScale(d.close); });
chart.append("path")
.datum(sample2)
.attr("class", "line")
.attr("d", line);
},
area: function (){
var area = d3.svg.area()
.x(function(d){ return xScale(d.time); })
.y0(height- margin.bottom)
.y1(function(d){ return yScale(d.close); })
chart.append("linearGradient")
.attr("id", "temperature-gradient")
.attr("gradientUnits", "userSpaceOnUse")
.attr("x1", 0).attr("y1", yScale(yMin))
.attr("x2", 0).attr("y2", yScale(yMax))
.selectAll("stop")
.data([
{offset: "10%", color: "red"},
{offset: "33%", color: "green"},
{offset: "66%", color: "lime"}
])
.enter().append("stop")
.attr("offset", function(d) { return d.offset; })
.attr("stop-color", function(d) { return d.color; });
chart.append("path")
.datum(sample2)
.attr("class", "area")
.attr("d", area);
}
};
// draw axes
chart.append('g').call(xAxis)
.attr('transform', 'translate(0, ' + (height - margin.bottom) + ')');
chart.append('g').call(yAxis)
.attr('transform', 'translate(' + (width - margin.right) + ', 0)');
/*
* CHOOSE CHART TYPE
*/
// chartDraw.area();
chartDraw.line();
// chartDraw.candle();
// add cross hairs and floating value on axis
var focus = chart.append("g")
.attr("class","focus")
.style("display", "none");
focus.append("text").attr({"x": 9, "dy": "0.35em"});
// horizontal crosshair
focus.append("line")
.attr({
"x1": 0,
"y1": 0,
"x2": -width + margin.left*3 ,
"y2": 0
});
// vertical crosshair
/*
focus.append("line")
.attr({
"x1": d3.mouse(this)[0],
"y1": -height + margin.top*4,
"x2": d3.mouse(this)[0],
"y2": height
});
*/
focus.append("line")
.attr({
"x1": 310,
"y1": -height,
"x2": 300,
"y2": height
})
chart.append("rect")
.attr({"class": "overlay" , "width": width , "height": height})
.on({
"mouseover": function() { focus.style("display", null); },
"mouseout": function() { focus.style("display", "none"); },
"mousemove": mousemove
});
function mousemove() {
var x0 = xScale.invert(d3.mouse(this)[0]),
i = bisectDate(sample2, x0, 1),
d0 = sample2[i-1],
d1 = sample2[i],
d = x0 - d0.date > d1.date - x0 ? d1 : d0;
focus.attr("transform", "translate(" + (width - margin.right) + "," + yScale(d.close) + ")");
focus.select("text").text("$" + d.close);
}
{"sample2": [
{"time": 1387212120, "open": 368, "close": 275, "high": 380, "low": 158},
{"time": 1387212130, "open": 330, "close": 350, "high": 389, "low": 310},
{"time": 1387212140, "open": 213, "close": 253, "high": 289, "low": 213},
{"time": 1387212150, "open": 180, "close": 150, "high": 189, "low": 110},
{"time": 1387212160, "open": 310, "close": 350, "high": 389, "low": 310},
{"time": 1387212170, "open": 213, "close": 253, "high": 289, "low": 213},
{"time": 1387212180, "open": 190, "close": 150, "high": 189, "low": 110},
{"time": 1387212190, "open": 362, "close": 530, "high": 589, "low": 510},
{"time": 1387212200, "open": 409, "close": 356, "high": 300, "low": 510},
{"time": 1387212210, "open": 334, "close": 275, "high": 369, "low": 185},
{"time": 1387212220, "open": 304, "close": 389, "high": 389, "low": 310},
{"time": 1387212230, "open": 395, "close": 235, "high": 289, "low": 213},
{"time": 1387212240, "open": 339, "close": 148, "high": 189, "low": 110},
{"time": 1387212250, "open": 310, "close": 350, "high": 389, "low": 310},
{"time": 1387212260, "open": 283, "close": 253, "high": 289, "low": 213},
{"time": 1387212270, "open": 290, "close": 350, "high": 189, "low": 110},
{"time": 1387212280, "open": 448, "close": 550, "high": 624, "low": 510},
{"time": 1387212290, "open": 419, "close": 299, "high": 194, "low": 510},
{"time": 1387212300, "open": 150, "close": 163, "high": 189, "low": 145},
{"time": 1387212310, "open": 330, "close": 350, "high": 356, "low": 310},
{"time": 1387212320, "open": 213, "close": 253, "high": 289, "low": 213},
{"time": 1387212330, "open": 180, "close": 150, "high": 189, "low": 110},
{"time": 1387212340, "open": 310, "close": 350, "high": 389, "low": 310},
{"time": 1387212350, "open": 213, "close": 253, "high": 289, "low": 213},
{"time": 1387212360, "open": 190, "close": 150, "high": 230, "low": 110},
{"time": 1387212370, "open": 408, "close": 301, "high": 382, "low": 245},
{"time": 1387212380, "open": 330, "close": 356, "high": 404, "low": 230},
{"time": 1387212390, "open": 183, "close": 143, "high": 190, "low": 31},
{"time": 1387212400, "open": 183, "close": 265, "high": 271, "low": 165},
{"time": 1387212410, "open": 395, "close": 253, "high": 424, "low": 213},
{"time": 1387212420, "open": 339, "close": 379, "high": 446, "low": 275},
{"time": 1387212430, "open": 310, "close": 350, "high": 389, "low": 310},
{"time": 1387212440, "open": 283, "close": 253, "high": 289, "low": 213},
{"time": 1387212450, "open": 162, "close": 350, "high": 189, "low": 122},
{"time": 1387212460, "open": 452, "close": 361, "high": 525, "low": 329},
{"time": 1387212470, "open": 173, "close": 281, "high": 312, "low": 141},
{"time": 1387212480, "open": 183, "close": 265, "high": 271, "low": 165},
{"time": 1387212490, "open": 395, "close": 253, "high": 424, "low": 213},
{"time": 1387212500, "open": 339, "close": 379, "high": 446, "low": 275},
{"time": 1387212510, "open": 310, "close": 350, "high": 389, "low": 310},
{"time": 1387212520, "open": 283, "close": 253, "high": 289, "low": 213},
{"time": 1387212530, "open": 162, "close": 350, "high": 189, "low": 122},
{"time": 1387212540, "open": 452, "close": 361, "high": 542, "low": 329},
{"time": 1387212550, "open": 173, "close": 281, "high": 312, "low": 91},
{"time": 1387212560, "open": 183, "close": 265, "high": 271, "low": 165},
{"time": 1387212570, "open": 395, "close": 253, "high": 424, "low": 213}
]}
.line {
fill: none;
stroke: green;
stroke-width: 3px;
}
.area {
fill: url(#temperature-gradient);
}
.overlay {
fill: none;
pointer-events: all;
}
.focus line {
fill: none;
stroke: gray;
}
.focus text, line {
opacity: 0.5;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment