Can I modify the logic for value redistribution in pie chart? - javascript

In LightningchartJS Pie chart can we change the logic for value redistribution. For example, consider the chart in image 1. If I hide a certain region say Planning, then the percentage of values is equally distributed in all the other regions see image 2. Is there a way in which I can customise this distribution of values?

You can customize the labels by using the .setLabelFormatter() method.
You can check the Slice LabelFormatter from the LightningChart JS API documentation for an example on how to use a custom implementation.
Distributing values of hidden slices
If you want to instead redistribute the value of a hidden slice, it is possible but trickier as Pie Chart does not have this feature natively.
This can be done by adding the desired functionality to the legendBox's buttons instead.
After creating the legendBox, you can add specific slices instead of adding the whole PieChart, then modify the behavior when clicking on each entry.
// Add a legendBox UI element
const legendBox = chart.addLegendBox()
// Add the slices to the legendBox separately, so we can use custom behavior when clicking on the entries
const entry = legendBox.add( slice1 )
entry.onSwitch((_, state) => {
// If the entry's state is true after clicking, restore everything to normal
if(state) {
slice1.restore()
slice2.setValue(120)
// Else, hide the slice the entry is linked to, and distribute its value to another slice
} else {
slice1.dispose()
slice2.setValue(160)
}
}

Related

How to undo the dots on this grid?

Refering to a live javascript playground at https://codepen.io/Maximusssssu/pen/MWrzpav?editors=1011 .When you click on the grid, it will put a triangle or a square depending on your liking using the buttons (triangle & square below the grid). However, I am trying to build an Undo function for both triangle and square. Can anyone offer me some guidance on this? Thank you for reading and have a nice day :) I use the code below to put square or triangle on the grid.
newDot.style.top = y + 'px';
newDot.style.left = x + 'px';
// Add the new element to the end of the body:
document.body.appendChild(newDot);
I would use Memento pattern to implement the undo functionality with the classes listed below.
Basically, the client (main function in my example) invokes const s = Grid.snapshot() method to take a snapshot of the current state of the Grid, and invokes History.push(s) to save the snapshot. When the client needs to undo the change, it retrieves the previous grid state, i.e. snapshot, by invoking const pre = History.pop(), and then feed the previous snapshot to the grid by Grid.restore(pre). The Grid.restore() method can internally invoke Grid.render() method to render the previous state of the grid, i.e. draw the previous set of dots.
Grid Class
Grid holds information about the grid, i.e. all the coordinates of the dots, shapes of the dots, etc.
Snapshot Class
Snapshot captures the state of the grid at some point in the past. Grid is responsible for producing an instance of Snapshot.
History Class
History saves all the previous states of the Grid by storing Snapshot objects. It it essentially a "stack", so it can push or pop a snapshot in a LIFO manner.
main
main function handle all the above objects to realize the required functionalities of the app.
UML Diagram
In order to implement the undo functionality separately for the square and triangle dots, I would tweak this design in such a way that it keeps track of two sets of previous states, one being the triangles and the other being squares. This would result in having two History objects, one recording previous states of square dots and the other recording those of triangle dots, as well as the Grid object producing separate snapshots for squares and triangles.

Conditional hover effect on the selected data using Chart.js

I want to disable the hover effect on certain data points of a dataset under certain conditions using Chart.js.
I basically need to modify the dataset before drawing the line graph so it looks in the way i want. (e.g extending the line along x axis) And i don't want the hover effect to take place on some of those data points.
After implementing the business logic, I've looked for a scriptable option
so i can use the context regarding the data point the user is on. I've came across solutions for basically cancelling all the hover effects on a single graph but not conditionally just like I've mentioned.
I've tried to use onHover with the context and set the hoverRadius conditionally and it looks as i expected but it gives me an error saying "Cannot assign to read only property 'hoverRadius' of object".
// in the options object
onHover: function (event, context) {
if (!isEmpty(context)) {
context[0]._options.hoverRadius = 0;
}
}
Most probably, the regarding object has been made immutable intentionally.
So what's the correct way of implementing this behavior in Chart.js?

Adding dynamic mean to time series chart

I will try to explain my problem as much accurate as possible. I am looking for a javascript chart library filling the two following conditions:
From an ajax request retrieving time series,
display dynamically data when changing the time window.
such as it is perfectly done on highstocks: http://www.highcharts.com/stock/demo/basic-line
And
plot an horizontal line corresponding to the mean,
changing when the user update the time window on the chart.
Actually it is possible to display an horizontal line. But they are fixed on the whole data and do not change accordingly when the time window is modified:
http://www.highcharts.com/stock/demo/yaxis-plotlines
I am quite new to the topic and would like to know if it'sp ossible to modify Highstock classes to have such a result. Or maybe some other js libraries exists?
Using a combination of the answer here:
Highchart, get total of visible series data after setExtremes
And an example of dynamic average using all visible series that I made for a previous question, here:
http://jsfiddle.net/jlbriggs/gweuLegq/
I put together this example, using the afterSetExtremes event, like this:
xAxis : {
events:{
afterSetExtremes:function() {
var ext = this.getExtremes();
getAverage(this.chart, ext.min, ext.max, show, width, avgColor, dashStyle);
}
}
},
Working example here:
http://jsfiddle.net/jlbriggs/c93543yL/
The idea is:
1) capture the afterSetExtremes event
2) get the resulting axis min and max
3) loop through the series data
4) if a point is between the min and max, increment the count, and add the
point's y value to the sum
5) calculate the average accordingly, check for existence of average series, if exists, update, if not, add
It could as easily use a plot line that you add/remove as needed instead of a series, but I like having it as a series so that it has a legend entry.

Pie chart keeps adjusting itself when updating - D3

I'm having a bit of a problem.
I'm using D3 to make a pie chart for an application I'm building. I basically it have it working, but I'm annoyed by one aspect of the chart. I've adapted the chart from here: http://jsfiddle.net/vfkSs/1/ to work with my application.
The data is passed in here:
data = data ? data : { "slice1": Math.floor((Math.random()*10)+1),
"slice2": Math.floor((Math.random()*10)+1),
"slice3": Math.floor((Math.random()*10)+1),
"slice4": Math.floor((Math.random()*10)+1) };
But somewhere in this file these slices are being ordered by value, which is not what I want.
The issue with this chart is that when it updates it adjusts all pieces of the chart to keep them in ascending order. For example the largest portion of the pie is always on the right, and smallest on the left. I would like these to remain in the order they are when the data is passed in.
This is buried a bit in the documentation.
pie.sort([comparator])
If comparator is specified, sets the sort order of data for the layout
using the specified comparator function. Pass null to disable sorting.
(bolding mine)
So, modify your .pie call to:
var cv_pie = d3.layout.pie().sort(null).value(function (d) { return d.value });
Updated fiddle.

Flot charts: How do you alter styling options after the chart's been rendered (e.g. by means of code injection)?

Is it possible to change the styling of a Flot chart's components on the fly – either via the console or a script – after the fact that the chart has been rendered? I.e from somewhere outside the Flot chart's internal configs (which initially defined the styling of the chart).
To put my question into a simple use case: I have a page containing a Flot chart which has the wrong color on the bars. Using Web Inspector's JS console, I want to alter the bars (lines?) color from blue to, say, brown. (And I don't have any means to edit the configs in jquery.flot.js.) Now I wish to inject code from the console, that might change the color of the bars.
I only wish to be hinted of a basic code structure as I'm stuck (nope, I'm not a particularly intermediate or advanced user).
Screenshot 1 – the rendered chart, unaffected (arrow indicates what I want to change):
… Flot's API says:
$.plot(placeholder, data, options)
But I don't want to set/change the data (which has already been plotted out), I just want to change its color representation from blue to, say, brown. The only effect of changing something, that I managed to achieve, was this (terribly clueless) piece of code:
$.plot("#chart", { series: {color: "#6C564C"} });
Which turned the chart into (Screenshot 2):
I don't know why the chart disappeared, and we don't necessarily need to troubleshoot that. All I'm looking for is the simple structure for altering a Flot chart's options by means of code injection.
You can change the colour of an already-drawn series by changing the data object and using setData(). This is faster than calling $.plot() again but it won't recalculate the grid and ticks. If your actual data points don't change, this isn't an issue.
var data = [
{
label: "Your series",
data: rawData,
color: "#f00"
}
]
// Initial draw:
var flotObject = $.plot("#chart", data, options);
// ...
// Change the colour:
data[0].color = "yellow"; // Change only the colour of the original data object
flotObject.setData(data);
flotObject.draw();

Categories