Highcharts Alternate unique name using tooltip - javascript

I'm trying to build a highchart that when you hover over a scatter point you will get a separate unique id for the point. I dug around for this information in the forums for a while and can't find it.
I found this: Display array values as unique tooltip in highcharts but it's a category based reference. I want each point to have it's own id.
So my data is as follows:
Sample ID Y
Samp1 115.90 179.00
Samp2 37.50 188.00
Samp3 27.80 64.00
Samp4 51.90 228.00
Samp5 27.20 863.00
Samp6 478.80 575.00
Samp7 39.10 598.00
Samp8 22.80 244.00
I want the tooltip to display the series name, sample and the values of x and y for each point.
This helps me identify a point easily by not having to look it up by the x and y values. So for each point I want the tooltip to report the sampleID (which would be samp1, 2, etc)
here is the fiddle: http://jsfiddle.net/776yN/

I advice to parse your data (in preprocessing) to avoid using array (for single point) like [10,10] but use object
{
x: 10,
y: 10
id: 'sample12'
}
Then you will have access to custom parameter by this.point.options.id in tooltip parameter

Related

Is there a way to center label in nested pie chart without using magic numbers as radius for Amchart v4?

My problem: i would like to find an automatic way to center labels in donut chart cells. In my case each cells contains an array of complex objects, what i want is to show the number of those objects.
See:
Playing with radius, allowed me to find those values:
First layer: -28
Second layer: -20
Third layer: -10
Fourth layer: -8
I applied it as a quick fix but i don't like this solution, as it's fixed for 4 layers (what if I need to add an other layer ? etc....) and using "magic numbers" is unmaintenable...
Do you have a better solution ?
You can test it here: https://jsfiddle.net/aliz/gwz7om9e/
Line 40:
pieSeries.labels.template.radius = am4core.percent(positionRadiusInPie);
Note:
Using those attributes didn't work: "horizontalCenter", "VerticalCenter", "textAlign", "align".
EDIT: response to Bhavik Kalariya
This is what I get if I force one radius for all layers.
You can at least get it down to just using one base constant of your choosing by using an adapter approach on the label's radius to calculate the value you want for each series that is added to the chart using whatever formula you choose. Here's a basic formula that gave good results for me with your setup, where BASE_INNER_LABEL_RADIUS is set to -45.
pieSeries.labels.template.adapter.add('radius', function(radius, target) {
var chart = target.baseSprite; //chart stored in baseSprite of the AxisCircularLabel
var index = chart.series.indexOf(target.dataItem.component); //corresponding series stored in the dataItem's component
return am4core.percent(BASE_INNER_LABEL_RADIUS / (index + 2)); //Uses singular constant defined elsewhere, which is used in all series
});
This will adjust itself according to the number of series you add to the chart. You can make this as robust as you want by making further tweaks if you have fewer series and want to make the labels even more centered.
Updated fiddle
Edit
If you want to be even more generic, you can get at the slice sprite directly through the target.dataItem.sprites array (typically the first element, though you can loop through and look for an object whose className is "Slice" if you want to be super safe about it) and calculate your desired radius value using any of the numeric properties it has, such as innerRadius.
pieSeries.labels.template.adapter.add('radius', function(radius, target) {
var chart = target.baseSprite; //chart stored in baseSprite of the AxisCircularLabel
var index = chart.series.indexOf(target.dataItem.component); //corresponding series stored in the dataItem's component
return -(target.dataItem.sprites[0].innerRadius) / (index + 3);
});
You'll want to adjust this accordingly, of course.
Fiddle

Not able to render a series chart using data outside the dimension object

I have a dataset with the following schema:
{
"time": Date,
"foo": Number,
"bar": Number,
"change": Number
"place1": String,
"description": String,
"place2": String
}
And I want plot a series-chart grouping the place1 and place2 together, display time as x data, foo as y data and the other fields inside the tooltip.
Taking a look at this example the first thing I have done is to create a dimension and grouping the dataset using place1 and place2.
const placeDimension = ndx.dimension((d) => [d.place1, d.place2]);
After that I've created a group, since I want display data without aggregation I've only used the group function:
const placeGroup = placeDimension.group();
And from this point on I'm confused on how to use the two object created before for plotting the series-chart.
How can I select the property to plot in the X and Y-Axis? (In this case time for X and foo for Y?) .
How can I display the other properties inside the tooltip? (I know how to use the tooltip but I don't know how to use data that are not inside the dimension).
In dc.js and crossfilter, the X axis is usually the "keys" of your grouped data, and the Y axis is the counts (or other aggregations).
If each of your keys are unique and you do
const placeGroup = placeDimension.group().reduceSum(d => d.foo)
then it will sum up the one value and return it to you. So your keys (X) will be place1,place2 and your values will be foo.
Then you can use the seriesAccessor and keyAccessor to pull the keys back apart, as in the example you linked.
Tooltips are called "titles" in dc.js, after the HTML/SVG element which implements them. You can format your text however you want in the accessor, including line breaks. The annotated stock example shows this in action.
Caveat
All this said, there aren't very many good reasons for using dc.js with unaggregated data. The library only shines when there are interactions by filtering the charts, and filtering will only work if the data is aggregated with crossfilter.
It will probably be easier to learn another charting library, since you aren't using any of the functionality that makes dc.js special.

Creating datapoints on mouseclick Chart.js

I am new to Chart.js and JavaScript. Currently working with a line chart, and now I want to add custom data points to a mouse click event (when I press somewhere on the data set, it takes the current value of the Y axis and using that value it creates a data point in that place). I took the code from http://www.chartjs.org/samples/latest/charts/line/basic.html and trying to modify it. Here is a link to my current chart:
https://i.stack.imgur.com/M9MF1.jpg
I am using the basic chart.bundle.js library, and used D3.js libraries for making data points draggable.
Trying to implement the creation of points per mouse click using the following code, but it seems that it's not good so far.
document.getElementById('canvas').onclick = function(e){
//getting value by pressing on dataset
value = chartInstance.scales[scale].getValueForPixel(e.clientY)
//trying to create dataPoint
myLineChart.points.push(new this.PointClass({
y: value;
strokeColor: this.datasets[datasetIndex].pointStrokeColor,
fillColor: this.datasets[datasetIndex].pointColor
}));
//after all updating my chart
chartInstance.Update(0)
};
Maybe anyone could explain more about this library and how it creates data points?
Every new point in the chart is data, so you need to add that point in the data (chartData.data.dataset[]) array. Instead of adding to the, myLineChart.points which i'm not sure why you have used you should add the data-point in the data array and the UI decorations such as colors are supposed to be specified in the chartOptions.scales.yAxes[] array. Therefore in order to add the point in the chart use:
// here i is the corresponding parameter for which you want to add the new point
chartInstance.data.datasets[i].push(value);
chartInstance.update();

rickshaw.js displaying additional data in tooltips

I have a richshaw plot with tooltips enabled (Rickshaw.Graph.HoverDetail). I need to display more information in it, not just series y values. Can it be accomplished with Richshaw or do I have to use the underlying d3 functions.
Sorry for the late response. Yes you can actually render whatever you want inside rickshaw tooltips with Rickshaw.Graph.HoverDetail .
Lets say for example that you have a function that requires as inputs series, x and y and lets assume that we have another array with the same length as x array called dates:
var hoverDetail = new Rickshaw.Graph.HoverDetail({
graph: graph,
formatter: function(series, x, y) {
var content = '<span class="graph-dates">'+dates[x]+'</span><br><span class="graph-price">'+series.name+": "+currency+parseInt(y) +'</span>';
return content;
}
});
The code renders on the hover details a date for the chosen x point and the price for that date.
In the documentation of rickshaw graph you can find further information.
Here is the actual example by rickshaw.

d3.v3 scatterplot with all circles the same radius

Every example I have found shows all of the scatter plot points to be of random radii. Is it possible to have them all the same size? If I try to statically set the radius all of the circles will be very small (I'm assuming the default radius). However, if I use Math.random() as in most examples there are circles large and small. I want all the circles to be large. Is there a way to do that? Here's the code snippet forming the graph data using Math.random() (this works fine for some reason):
function scatterData(xData, yData)
{
var data = [];
for (var i = 0; i < seismoNames.length; i++)
{
data.push({
key: seismoNames[i],
values: []
});
var xVals=""+xData[i];
xVals=xVals.split(",");
var yVals=""+yData[i];
yVals=yVals.split(",");
for (var j = 0; j < xVals.length; j++)
{
data[i].values.push({
x: xVals[j],
y: yVals[j],
size: Math.random()
});
}
}
return data;
}
Math.random() spits out values between 0 and 1 such as 0.164259538891095 and 0.9842195005008699. I have tried putting these as static values in the 'size' attribute, but no matter what the circles are always really small. Is there something I'm missing?
Update: The NVD3 API has changed, and now uses pointSize, pointSizeDomain, etc. instead of just size. The rest of the logic for exploring the current API without complete documentation still applies.
For NVD3 charts, the idea is that all adjustments you make can be done by calling methods on the chart function itself (or its public components) before calling that function to draw the chart in a specific container element.
For example, in the example you linked too, the chart function was initialized like this:
var chart = nv.models.scatterChart()
.showDistX(true)
.showDistY(true)
.color(d3.scale.category10().range());
chart.xAxis.tickFormat(d3.format('.02f'));
chart.yAxis.tickFormat(d3.format('.02f'));
The .showDistX() and .showDistY() turn on the tick-mark distribution in the axes; .color() sets the series of colours you want to use for the different categories. The next too lines access the default axis objects within the chart and set the number format to be a two-digit decimal. You can play around with these options by clicking on the scatterplot option from the "Live Code" page.
Unfortunately, the makers of the NVD3 charts don't have a complete documentation available yet describing all the other options you can set for each chart. However, you can use the javascript itself to let you find out what methods are available.
Inspecting a NVD3.js chart object to determine options
Open up a web page that loads the d3 and nvd3 library. The live code page on their website works fine. Then open up your developer's console command line (this will depend on your browser, search your help pages if you don't know how yet). Now, create a new nvd3 scatter chart function in memory:
var testChart = nv.models.scatterChart();
On my (Chrome) console, the console will then print out the entire contents of the function you just created. It is interesting, but very long and difficult to interpret at a glance. And most of the code is encapsulated so you can't change it easily. You want to know which properties you can change. So run this code in the next line of your console:
for (keyname in testChart){console.log(keyname + " (" + typeof(testChart[keyname]) + ")");}
The console should now print out neatly the names of all the methods and objects that you can access from that chart function. Some of these will have their own methods and objects you can access; discover what they are by running the same routine, but replacing the testChart with testChart.propertyName, like this:
for (keyname in testChart.xAxis){console.log(keyname + " (" + typeof(testChart.xAxis[keyname]) + ")");}
Back to your problem. The little routine I suggested above doesn't sort the property names in any order, but skimming through the list you should see three options that relate to size (which was the data variable that the examples were using to set radius)
size (function)
sizeDomain (function)
sizeRange (function)
Domain and range are terms used by D3 scales, so that gives me a hint about what they do. Since you don't want to scale the dots, let's start by looking at just the size property. If you type the following in the console:
testChart.size
It should print back the code for that function. It's not terribly informative for what we're interested in, but it does show me that NVD3 follows D3's getter/setter format: if you call .property(value) you set the property to that value, but if you call .property() without any parameters, it will return back the current value of that property.
So to find out what the size property is by default, call the size() method with no parameters:
testChart.size()
It should print out function (d) { return d.size || 1}, which tells us that the default value is a function that looks for a size property in the data, and if it doesn't exist returns the constant 1. More generally, it tells us that the value set by the size method determines how the chart gets the size value from the data. The default should give a constant size if your data has no d.size property, but for good measure you should call chart.size(1); in your initialization code to tell the chart function not to bother trying to determine size from the data and just use a constant value.
Going back to the live code scatterplot can test that out. Edit the code to add in the size call, like this:
var chart = nv.models.scatterChart()
.showDistX(true)
.showDistY(true)
.color(d3.scale.category10().range())
.size(1);
chart.xAxis.tickFormat(d3.format('.02f'));
chart.yAxis.tickFormat(d3.format('.02f'));
Adding that extra call successfully sets all the dots to the same size -- but that size is definitely not 1 pixel, so clearly there is some scaling going on.
First guess for getting bigger dots would be to change chart.size(1) to chart.size(100). Nothing changes, however. The default scale is clearly calculating it's domain based on the data and then outputting to a standard range of sizes. This is why you couldn't get big circles by setting the size value of every data element to 0.99, even if that would create a big circle when some of the data was 0.01 and some was 0.99. Clearly, if you want to change the output size, you're going to have to set the .sizeRange() property on the chart, too.
Calling testChart.sizeRange() in the console to find out the default isn't very informative: the default value is null (nonexistent). So I just made a guess that, same as the D3 linear scale .range() function, the expected input is a two-element array consisting of the max and min values. Since we want a constant, the max and min will be the same. So in the live code I change:
.size(1);
to
.size(1).sizeRange([50,50]);
Now something's happening! But the dots are still pretty small: definitely not 50 pixels in radius, it looks closer to 50 square pixels in area. Having size computed based on the area makes sense when sizing from the data, but that means that to set a constant size you'll need to figure out the approximate area you want: values up to 200 look alright on the example, but the value you choose will depend on the size of your graph and how close your data points are to each other.
--ABR
P.S. I added the NVD3.js tag to your question; be sure to use it as your main tag in the future when asking questions about the NVD3 chart functions.
The radius is measured in pixels. If you set it to a value less than one, yes, you will have a very small circle. Most of the examples that use random numbers also use a scaling factor.
If you want all the circles to have a constant radius you don't need to set the value in the data, just set it when you add the radius attribute.
Not sure which tutorials you were looking at, but start here: https://github.com/mbostock/d3/wiki/Tutorials
The example "Three little circles" does a good step-by-step of the different things you can do with circles:
http://mbostock.github.io/d3/tutorial/circle.html

Categories

Resources