I have the candle plotter example working, but when I try to add annotations to the data series, the annotation simply floats to the top left of the chart.
Clearly, the plotter's fancy footwork with the drawing is confusing the annotation setter.
I'm new to Dygraphs and my JavaScript is rusty, so I'd appreciate any pointers on getting annotations working together with a plotter.
var BAR_WIDTH = 8;
function candlePlotter(e) {
// This is the officially endorsed way to plot all the series at once.
if (e.seriesIndex !== 0) return;
var setCount = e.seriesCount;
if (setCount != 4) {
throw "You must provide exactly 4 price series: open close high low";
}
var prices = [];
var price;
var sets = e.allSeriesPoints;
for (var p = 0; p < sets[0].length; p++) {
price = {
open: sets[0][p].yval,
close: sets[1][p].yval,
high: sets[2][p].yval,
low: sets[3][p].yval,
openY: sets[0][p].y,
closeY: sets[1][p].y,
highY: sets[2][p].y,
lowY: sets[3][p].y
};
prices.push(price);
}
var area = e.plotArea;
var ctx = e.drawingContext;
ctx.strokeStyle = '#202020';
ctx.lineWidth = 0.6;
for (p = 0; p < prices.length; p++) {
ctx.beginPath();
price = prices[p];
var topY = area.h * price.highY + area.y;
var bottomY = area.h * price.lowY + area.y;
var centerX = area.x + sets[0][p].x * area.w;
ctx.moveTo(centerX, topY);
ctx.lineTo(centerX, bottomY);
ctx.closePath();
ctx.stroke();
var bodyY;
if (price.open > price.close) {
ctx.fillStyle = 'rgba(244,44,44,1.0)';
bodyY = area.h * price.openY + area.y;
} else {
ctx.fillStyle = 'rgba(44,244,44,1.0)';
bodyY = area.h * price.closeY + area.y;
}
var bodyHeight = area.h * Math.abs(price.openY - price.closeY);
ctx.fillRect(centerX - BAR_WIDTH / 2, bodyY, BAR_WIDTH, bodyHeight);
}
}
var candleData = "Date,Open,Close,High,Low\n" +
"1,392.54,390.95,394.63,389.38\n" +
"2,389.93,389.09,390.94,386.76\n" +
"3,391.45,390.66,395.50,390.23\n" +
"4,392.85,393.62,394.04,391.03\n" +
"5,391.68,391.84,393.90,389.45\n" +
"6,393.00,388.81,395.40,387.10\n" +
"7,386.70,380.19,387.38,377.68\n" +
"8,383.33,378.94,383.74,378.31\n" +
"9,380.36,381.02,384.15,379.57\n" +
"10,382.47,382.21,384.85,380.48\n" +
"11,387.76,395.95,396.10,387.26\n" +
"12,396.69,396.45,397.30,392.01\n" +
"13,397.00,398.55,399.13,396.10\n" +
"14,399.69,403.33,403.59,399.49\n" +
"15,403.10,406.53,409.09,403.02\n" +
"16,406.89,402.64,408.25,401.34\n" +
"17,403.40,405.12,405.65,400.51\n" +
"18,403.51,405.00,406.28,403.49\n" +
"19,409.50,411.23,412.50,409.00\n" +
"20,410.21,413.44,414.68,409.28\n";
g = new Dygraph(
document.getElementById("candlechart"),
candleData, {
plotter: candlePlotter,
});
g.ready(function() {
g.setAnnotations([{
series: "High",
x: "6",
shortText: "Hello",
text: "Hello world"
}]);
});
<script src="//cdnjs.cloudflare.com/ajax/libs/dygraph/2.1.0/dygraph.min.js"></script>
<link rel="stylesheet" src="//cdnjs.cloudflare.com/ajax/libs/dygraph/2.1.0/dygraph.min.css" />
<div id="candlechart"></div>
The issue is with how you source the dygraphs stylesheet. It should be <link href>
, not <link src>
. Here's a corrected code snippet.
var BAR_WIDTH = 8;
function candlePlotter(e) {
// This is the officially endorsed way to plot all the series at once.
if (e.seriesIndex !== 0) return;
var setCount = e.seriesCount;
if (setCount != 4) {
throw "You must provide exactly 4 price series: open close high low";
}
var prices = [];
var price;
var sets = e.allSeriesPoints;
for (var p = 0; p < sets[0].length; p++) {
price = {
open: sets[0][p].yval,
close: sets[1][p].yval,
high: sets[2][p].yval,
low: sets[3][p].yval,
openY: sets[0][p].y,
closeY: sets[1][p].y,
highY: sets[2][p].y,
lowY: sets[3][p].y
};
prices.push(price);
}
var area = e.plotArea;
var ctx = e.drawingContext;
ctx.strokeStyle = '#202020';
ctx.lineWidth = 0.6;
for (p = 0; p < prices.length; p++) {
ctx.beginPath();
price = prices[p];
var topY = area.h * price.highY + area.y;
var bottomY = area.h * price.lowY + area.y;
var centerX = area.x + sets[0][p].x * area.w;
ctx.moveTo(centerX, topY);
ctx.lineTo(centerX, bottomY);
ctx.closePath();
ctx.stroke();
var bodyY;
if (price.open > price.close) {
ctx.fillStyle = 'rgba(244,44,44,1.0)';
bodyY = area.h * price.openY + area.y;
} else {
ctx.fillStyle = 'rgba(44,244,44,1.0)';
bodyY = area.h * price.closeY + area.y;
}
var bodyHeight = area.h * Math.abs(price.openY - price.closeY);
ctx.fillRect(centerX - BAR_WIDTH / 2, bodyY, BAR_WIDTH, bodyHeight);
}
}
var candleData = "Date,Open,Close,High,Low\n" +
"1,392.54,390.95,394.63,389.38\n" +
"2,389.93,389.09,390.94,386.76\n" +
"3,391.45,390.66,395.50,390.23\n" +
"4,392.85,393.62,394.04,391.03\n" +
"5,391.68,391.84,393.90,389.45\n" +
"6,393.00,388.81,395.40,387.10\n" +
"7,386.70,380.19,387.38,377.68\n" +
"8,383.33,378.94,383.74,378.31\n" +
"9,380.36,381.02,384.15,379.57\n" +
"10,382.47,382.21,384.85,380.48\n" +
"11,387.76,395.95,396.10,387.26\n" +
"12,396.69,396.45,397.30,392.01\n" +
"13,397.00,398.55,399.13,396.10\n" +
"14,399.69,403.33,403.59,399.49\n" +
"15,403.10,406.53,409.09,403.02\n" +
"16,406.89,402.64,408.25,401.34\n" +
"17,403.40,405.12,405.65,400.51\n" +
"18,403.51,405.00,406.28,403.49\n" +
"19,409.50,411.23,412.50,409.00\n" +
"20,410.21,413.44,414.68,409.28\n";
g = new Dygraph(
document.getElementById("candlechart"),
candleData, {
plotter: candlePlotter,
});
g.ready(function() {
g.setAnnotations([{
series: "High",
x: '6',
shortText: "Hello",
text: "Hello world"
}]);
});
<script src="//cdnjs.cloudflare.com/ajax/libs/dygraph/2.1.0/dygraph.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/dygraph/2.1.0/dygraph.css" />
<div id="candlechart"></div>