Customised markers/tooltips on a Dojo line chart - javascript

I'm using Dojo 1.8 to create a Line chart which I am using to plot time series data. The data consists of samples taken every 5 minutes over a 24 period giving up to 288 (12x24) data points.
In order to have tooltips on the chart, I need to enable markers on the chart (dojo requires this). The problem is that by default, dojo creates one marker for each data point and this results in far too many markers. Ideally, I would show a single marker for the latest data point and maybe markers every hour or two.
It's possible to customise the appearance of a marker but so far I haven't been able to find any way of customising the frequency with which the markers appear. Any suggestions would be very welcome.

Try using the MarkersOnly module:
require(["dojox/charting/Chart", "dojox/charting/axis2d/Default", "dojox/charting/plot2d/Lines", "dojox/charting/plot2d/MarkersOnly", "dojox/charting/Series", "dojo/ready"],
function(Chart, Default, Lines, MarkersOnly, Series, ready) {
ready(function(){
var chart = new Chart("simplechart");
chart.addPlot("plot_lines", { type: Lines });
chart.addPlot("plot_markers", { type: MarkersOnly });
chart.addAxis("x");
chart.addAxis("y", {vertical:true});
chart.addSeries("series_lines", [4, 2, 6, 4, 5, 8, 8, 1, 7, 9]);
// if you want your markers at data points 6 and 7;
chart.addSeries("series_markers", [{x:3,y:6}, {x:9,y:7}], { plot: "plot_markers" , stroke: { color: "blue" } });
chart.render();
});
});

I was really having a tough time with the documentation and I just figured it out. Here is a jsFiddle with a working example. I used Andy W's solution and worked with what I could find on DojoToolkit.org for customizing the markers.
First you need to create a MarkersOnly plot as Andy explains, then you can customize the markers. You can find all the pieces on this documentation.
//found on http://dojotoolkit.org/reference-guide/1.8/dojox/charting.html
//CIRCLE: "m-3,0 c0,-4 6,-4 6,0 m-6,0 c0,4 6,4 6,0",
//SQUARE: "m-3,-3 l0,6 6,0 0,-6 z",
//DIAMOND: "m0,-3 l3,3 -3,3 -3,-3 z",
//CROSS: "m0,-3 l0,6 m-3,-3 l6,0",
//X: "m-3,-3 l6,6 m0,-6 l-6,6",
//TRIANGLE: "m-3,3 l3,-6 3,6 z",
//TRIANGLE_INVERTED:"m-3,-3 l3,6 3,-6 z"
var customTheme = new SimpleTheme({
markers: {
DIAMOND: "m0,-3 l3,3 -3,3 -3,-3 z",
CROSS: "m0,-3 l0,6 m-3,-3 l6,0"
}
});
var chart = new Chart("chartCustomMarkers",
{
title: "Custom Markers Chart",
titlePos: "top",
titleFont: "normal normal normal 15pt Arial",
});
chart.addPlot("default", { type: MarkersOnly })
.addAxis("x")
.addAxis("y", { vertical: true })
.addSeries("Series 1", [1, 2, 2, 3, 4, 5, 5, 7])
.addSeries("Series 2", [2, 5, 4, 8, 5, 6, 6, 1])
.setTheme(customTheme)
.render();
One of my coworkers showed me how to customize the SVG path (create your own pattern). Just go here for more info.

Related

plotly js colorscale for errorbars

I want to plot the scattered data with a colorscale and the errorbars should have the same colorscale.
I found answers for plotly R (How do you make plotly error bars follow a colorscale?), but I can't translate it to js. Also using the name attribute for this seems strange to me.
Here is a minimal example (https://jsfiddle.net/ztqoemkd/1)
var trace1 = {
type: 'scatter',
mode: 'markers',
y: [2, 1, 3],
marker: {
size: 20,
color: [1, 2, 3],
showscale: true
},
error_y: {
type:'data',
array: [0.5, 0.7, 0.5],
color: [1, 2, 3]
}
}
Plotly.newPlot('myDiv', [trace1])
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id="myDiv"></div>
I still don't know, if can be done self consistently with plotly itself.
At least, I could now develop this work around with d3:
// get colors from data points
rgbs = Plotly.d3.selectAll('.points .point').data().map(d => d.mcc)
// apply colors to errorbars
Plotly.d3.selectAll('.yerror').style('stroke', (d,i) => rgbs[i])
Here is the full demo:
https://jsfiddle.net/vor6e9wj
and the output is
Note 1: After zooming, the errorbars are again black.
Note 2: It does not work for scattergl.
Edit 1: To keep the colors while zooming, the work around can be attached to plotly_relayout (see https://jsfiddle.net/9s64y5cv).

c3js bar chart, align data to x tick start position (not centered)

If you take a normal bar chart from c3js, the bars will be centered at the x-tick position. I have a chart which goes hourly, so any timespan between 00-24 (usually like 8-16). If I have a line-chart or scatter plot it will align it self exactly on the x-tick nicely, but not as a step-chart or a bar chart.
var chart = c3.generate({
data: {
x: 'x',
columns: [
['x', 8, 9, 10, 11, 12, 13, 14, 15, 16],
['data1', 1, 1, 0, 1, 0, 0, 1, 1, 1],
],
type: "bar"
},
axis: {
x: {
type: "category",
categories: [],
}
}
});
See this fiddle: https://jsfiddle.net/jvcarphe/1/
I've been trying with all sorts of culling / tick values / time series etc. but I can't for the love of god figure out how to do it. If the type in the fiddle is changed to "line" it does exactly what I want, beside it's not a bar.
I've had to do this before and there doesn't seem to be a simple setting that does it, but a bit of d3 manipulation works. I came to the conclusion it's easier to move the ticks than the bars:
If you know the width of your bar, you can set a css rule to offset the ticks, just change the -10px to whatever is necessary -->
.c3-axis-x .tick line, .c3-axis-x .tick text {
transform: translate(-10px,0);
}
(can't just apply the rule to .tick as c3 overrides its transform style)
If you don't know the width then you need to find it out by querying one of the bars and applying the same style rule dynamically in c3's onrendered callback:
onrendered: function () {
var thisChart = d3.select(this.config.bindto);
var barWidth = thisChart.select(".c3-bar-0").node().getBoundingClientRect().width / 2;
thisChart.selectAll(".c3-axis-x .tick line,.c3-axis-x .tick text").style("transform", "translate(-"+barWidth+"px,0)");
}
Fiddle edited as newer version of c3 didn't work in the fiddle:
https://jsfiddle.net/15w50f06/4/

Anychart chart.animation breaks pie3d chart type

I'm running 7.12.0.1229, where according to Anychart : How to add animation in Pie or funnel chart of AnyChart7.1 several animation issues were fixed.
When trying to use a chart type of pie3d in combination with chart.animation(true, 800);, chart.animation(true); or chart.animation({enabled: true, duration: duration}) the chart won't render.
Working example http://jsfiddle.net/RainerAtSpirit/c2wye9m9/3/
anychart.onDocumentReady(function() {
//dataset
var data = anychart.data.set([
["$0-$50,000", 68],
["$50,000-$100,000", 13],
["$100,000-$150,000", 6],
["$150,000-$250,000", 6],
["$250,000 - plus", 7]
])
var chart = anychart.pie3d(data);
//adjust legend
var legend = chart.legend();
legend.enabled(true);
legend.position("left");
legend.align("center");
legend.itemsLayout("vertical");
//create title
var title = chart.title();
title.text("Pop Out");
title.enabled(true);
//inner radius makes this a doughnut chart instead of pie
chart.innerRadius("30%");
//define the container
chart.container("container");
// chart.animiation breaks pie3d chart type
// chart.animation(true, 800);
//set delay to recall draw ch art to
chart.draw();
});
Broken example http://jsfiddle.net/RainerAtSpirit/c2wye9m9/2/
anychart.onDocumentReady(function() {
//dataset
var data = anychart.data.set([
["$0-$50,000", 68],
["$50,000-$100,000", 13],
["$100,000-$150,000", 6],
["$150,000-$250,000", 6],
["$250,000 - plus", 7]
])
var chart = anychart.pie3d(data);
//adjust legend
var legend = chart.legend();
legend.enabled(true);
legend.position("left");
legend.align("center");
legend.itemsLayout("vertical");
//create title
var title = chart.title();
title.text("Pop Out");
title.enabled(true);
//inner radius makes this a doughnut chart instead of pie
chart.innerRadius("30%");
//define the container
chart.container("container");
// chart.animiation breaks pie3d chart type
chart.animation(true, 800);
//set delay to recall draw ch art to
chart.draw();
});
Indeed, it doesn't look nice, thank you for the report! We transfered this case to our bug tracking system, so we will dig deep into it and get back to you as soon as possible. As for animation feature in common, 3d charts support animation:
chart = anychart.bar3d([2, 8, 3, 4, 9]);
chart.animation({enabled: true, duration: 3000});
JSFIDDLE
But in case of 3d pie it doesn't work, we'll investigate it shortly.
It seems that animation is not yet supported for 3D charts. So either make the chart a 2d pie chart with animation or a 3D chart without.

Customizing Chart.js troubleshoot

Have some trouble with Chart.js
1) is it possible to move bottom labels on top of the chart?
2) is it possible to hide left labels with first grey line?
3) is it possible to set up permanent tooltips(to show temperature) on every point instead of hover tooltips?
Here is my chart http://jsfiddle.net/JohnnyJuarez/ojc09hv4/:
<canvas id="weeksChart" width="651" height="335"></canvas>
var dayTemperatureArray = [-5, 14, 15, 15, 17, 18, 19, 21, 22, 25, 24, 20, 19, 16];
var nightTemperatureArray = [-10, 4, 5, 6, 8, 11, 12, 15, 17, 15, 13, 12, 11, 9];
var dataWeeks = {
labels: ["16.02", "17.02", "18.02", "19.02", "20.02", "21.02", "22.02", "23.02", "24.02", "25.02", "26.02", "27.02", "28.02", "01.03"],
datasets: [
{
label: "Days temperature chart",
fillColor: "transparent",
strokeColor: "rgba(244, 6, 6, 1)",
data: dayTemperatureArray
},
{
label: "Nights temperature chart",
strokeColor: "#3f6bf5",
data: nightTemperatureArray
}
]
};
var ctx = document.getElementById("weeksChart").getContext("2d");
window.weeksChart = new Chart(ctx).Line(dataWeeks, {
responsive: true,
pointDot: true,
datasetStrokeWidth: 0.5,
scaleSteps: 2,
scaleLabel: "<%=value + '°'%>",
tooltipTemplate: "<%= value %>",
showTooltips: true
});
Thanx a lot in advance!
p.s. please avoid jquery, if it's possible :-)
Let's start with the easiest one first
2) is it possible to hide left labels with first grey line?
I assume you meant the y axis labels. You can set the scaleShowLabels option to false in the chart options to hide the y axis labels
window.weeksChart = new Chart(ctx).Line(dataWeeks, {
scaleShowLabels: false,
...
1) is it possible to move bottom labels on top of the chart?
I assume you mean the x axis labels. Chart.js doesn't have a direct option to do this. However you can hide the actual x axis labels and draw the x axis labels at the top of the chart by yourself.
Again, Chart.js doesn't have an option to hide x axis labels, but luckily there is an option to control the scale font color. Just set it to transparent and your original x axis labels are now hidden!
window.weeksChart = new Chart(ctx).Line(dataWeeks, {
scaleFontColor: "transparent",
...
Now the drawing of the x axis labels at the top of the chart. To save us the trouble of extending the chart, we can add a post animation event handler and do this in that, like so
window.weeksChart = new Chart(ctx).Line(dataWeeks, {
onAnimationComplete: function () {
animationComplete.apply(this)
}
...
with
var animationComplete = function () {
var self = this;
Chart.helpers.each(self.datasets[0].points, function (point, index) {
self.chart.ctx.font = Chart.helpers.fontString(self.fontSize, self.fontStyle, self.fontFamily)
self.chart.ctx.textAlign = 'center';
self.chart.ctx.textBaseline = "middle";
self.chart.ctx.fillStyle = "#666";
self.chart.ctx.fillText(point.label, point.x, self.scale.startPoint);
});
};
We just loop through all points in one of the dataset and add the labels (scale.startPoint is the top edge of the chart area)
Note - why do we set the font, alignment, etc. every iteration? That's for when we add the tooltips.
3) is it possible to set up permanent tooltips(to show temperature) on every point instead of hover tooltips?
The first step would be to actually show the tooltips. This is fairly simple, though a bit tedious. We loop through all the x axis point, build the label (by going through each dataset) and then construct a tooltip (fortunately, we can use Chart.MultiTooltip function for this.
We add it into the same loop we used to construct the new x axis labels. Since we need to color our tooltips, we need to get and store the set of colors in an array (which we pass on to the MultiTooltip function - we need to do this only once, so we take it out of the loop.
The modified animationComplete function is now this
var animationComplete = function () {
var self = this;
var tooltipColors = []
Chart.helpers.each(self.datasets, function (dataset) {
tooltipColors.push({
fill: dataset.strokeColor,
stroke: dataset.strokeColor
})
});
Chart.helpers.each(self.datasets[0].points, function (point, index) {
var labels = []
var total = 0;
Chart.helpers.each(self.datasets, function (dataset) {
labels.push(dataset.points[index].value)
total += Number(dataset.points[index].y);
});
new Chart.MultiTooltip({
x: point.x,
y: total / 2,
xPadding: self.options.tooltipXPadding,
yPadding: self.options.tooltipYPadding,
xOffset: self.options.tooltipXOffset,
fillColor: self.options.tooltipFillColor,
textColor: self.options.tooltipFontColor,
fontFamily: self.options.tooltipFontFamily,
fontStyle: self.options.tooltipFontStyle,
fontSize: self.options.tooltipFontSize,
titleTextColor: self.options.tooltipTitleFontColor,
titleFontFamily: self.options.tooltipTitleFontFamily,
titleFontStyle: self.options.tooltipTitleFontStyle,
titleFontSize: self.options.tooltipTitleFontSize,
cornerRadius: self.options.tooltipCornerRadius,
labels: labels,
legendColors: tooltipColors,
legendColorBackground: self.options.multiTooltipKeyBackground,
title: point.label,
chart: self.chart,
ctx: self.chart.ctx,
custom: self.options.customTooltips
}).draw()
self.chart.ctx.font = Chart.helpers.fontString(self.fontSize, self.fontStyle, self.fontFamily)
self.chart.ctx.textAlign = 'center';
self.chart.ctx.textBaseline = "middle";
self.chart.ctx.fillStyle = "#666";
self.chart.ctx.fillText(point.label, point.x, self.scale.startPoint);
});
};
It looks complex, but all we are doing is passing a options that we copy from the chart instance options to the MultiTooltip function.
The tooltips all show up when the animation is complete. HOWEVER, once you move your mouse over the chart they all up and disappear! That's because the chart instance listens for multiple events to decide whether to start checking if tooltips should be shown - one of these is mousemove (and that causes it to redraw the chart, wiping out all our hard drawn tooltips and, if we are lucky, it draws a tooltip based on the point our mouse is hovering over)
This is a configurable option. So, all we have to do is remove all such events.
window.weeksChart = new Chart(ctx).Line(dataWeeks, {
tooltipEvents: []
...
Working fiddle - http://jsfiddle.net/fuodxsfv/
Unless your chart is wide enough, you will have tooltips (mostly the middle 2 ones) overlap (of course you could incorporate logic into the above loop to handle that), but anyhoo, those were actually meant to be tooltips!

Issues with dojox.charting and xDomain reference to dojo/dojox library

I have a web HTML page with some client-side JS codes based on dojox.charting. I don't have dojo library in my local web site (actually no web server). I use dojos' xDomain reference feature with src to google's hosting site like this:
<head>
...
<script type="text/javascript"
djConfig1="isDebug:true"
src="http://ajax.googleapis.com/ajax/libs/dojo/1.2.0/dojo/dojo.xd.js">
</script>
<script type="text/javascript"
dojo.require("dojox.gfx");
dojo.require("dojox.gfx.move");
dojo.require("dojo.html");
dojo.require("dojox.charting.Chart2D");
dojo.require("dojox.charting.themes.PlotKit.green");
dojo.require("dojox.charting.action2d.Highlight");
dojo.require("dojox.charting.action2d.Magnify");
dojo.require("dojox.charting.action2d.MoveSlice");
dojo.require("dojox.charting.action2d.Shake");
dojo.require("dojox.charting.action2d.Tooltip");
dojo.require("dojox.charting.themes.MiamiNice");
dojo.require("dojox.charting.widget.Legend");
</script>
....
</head>
Here is the function to create curve chart, based on the codes in Dojo: Now With Drawing Tools.
function drawCurve(nodeChart, nodeLegend) {
var chart1 = new dc.Chart2D(nodeChart)
.setTheme(dc.themes.PlotKit.green)
.addPlot("default", {
type: "Default",
lines: true,
markers: true,
tension: 2
})
.addAxis("x", {
min: 0,
max: 6,
majorTick: { stroke: "black", length: 3 },
minorTick: { stroke: "gray", length: 3 }
})
.addAxis("y", {
vertical: true,
min: 0,
max: 10,
fixLower: "major",
fixUpper: "major",
majorTick: { stroke: "black", length: 3 },
minorTick: { stroke: "gray", length: 3 }
})
.addSeries("Series A", [
{ x: 0.5, y: 5 },
{ x: 1.5, y: 1.5 },
{ x: 2, y: 9 },
{ x: 5, y: 0.3 }
])
.addSeries("Series B", [
{ x: 0.3, y: 8 },
{ x: 4, y: 6, tooltip: "Custom tooltip"},
{ x: 5.5, y: 2 }
]);
var series = chart1.series;
var anim_a = new dc.action2d.Tooltip(chart1, "default");
var anim_c = new dc.action2d.Magnify(chart1, "default"); // not working
chart1.render();
var legendChart = new dc.widget.Legend(
{chart: chart1, horizontal: false}, nodeLegend.id);
}
My first question is that for the curve chart, the numbers along the y axis only displays 0 and 10. All the middle numbers 1 to 9 are not displayed. The values for x axis from 1 to 6 are visible. The original chart snapshot in the article does show y axis values as well, but the one on DojoToolKit Demos does show values along y axis. I am not sure what I missed in my codes. How can I enable displaying y axis values?
The next question is about the Magnify(). The DojoToolKit demo site's curve chart works fine but my chart's magnify feature does not work. I think this may be caused by xDomain reference. I may need to specify some specified js file from xDomain's dojox library. I am not sure which one I have to specify.
One thing I noticed is that my FireBug displays following errors after curve chart is drawn:
_4.fx.combine is not a function http://ajax.googleapis.com/ajax/libs/dojo/1.2.0/dojox/charting/action2d/Magnify.xd.js Line 8
_11.action is undefined http://ajax.googleapis.com/ajax/libs/dojo/1.2.0/dojox/charting/action2d/Magnify.xd.js Line 8
I think those undefined errors may indicate I miss loading some dojox library files in my head section.
By the way, I dont' have a web server and I prefer to use dojo's xDomain reference option. In this way, I can edit a html file in any place and send it to other people. No need to download and install dojo source library.
I think I got the missing part:
dojo.require("dojo.fx");
When I added this line to my HTML's head setction see above, the animation part set by Mangify() is working. This is only for the case you set xDomain reference to dojox for dojox.charting library.
What I found this is by using Firebug to look at DojoToolKit's Event 2D web page. In the head section there is code:
<script src="http://../action2/Magnify.js" type="text/javascript"></script>
That page has debug enabled. As a result, in FireBug window, you will see the source codes of js in a nice layout. I saw three requirements, and one is for "dojo.fx". I tried to add this one in. Then no more errors and I can see animation of magnify effect when I move mouse over points in the curve of the chart.
One thing interesting about <script src=".."> is that if the js is xDomain referenced, the js source codes are displayed partially in one long long time. If you hav the dojo library installed on your web page, ie same domain, the dojo's source codes are displayed nicely.
Regarding the y axis values, I also find out easy way to display them (0 to 9):
.addAxis("y", {
vertical: true,
//min: 0
//max: 10
....
You can also comment out min only and leave max with 10 (0, 1, ... to 10). See DojoCampus.org for more detail information about axis settings.

Categories