Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for floating bar chart #55

Closed
rr22x opened this issue May 12, 2020 · 17 comments
Closed

Support for floating bar chart #55

rr22x opened this issue May 12, 2020 · 17 comments
Assignees

Comments

@rr22x
Copy link

rr22x commented May 12, 2020

Since Charts.js 2.9.0 it is possible to use floating bar charts.
So you can use data points like [yStart, yEnd]. yStart defines the start point of the bar (instead of 0) and yEnd the end point accordingly.
Is it possible to use these kind of datapoints in charba?

see chartjs/Chart.js#6056

@stockiNail stockiNail self-assigned this May 12, 2020
@stockiNail
Copy link
Contributor

@rr22x this is not implemented yet. It's in the list of implementations going to Chart.JS v3.

But let me try a workaround (even if it could not be "elegant").

@stockiNail
Copy link
Contributor

@rr22x any workaround is not possible, sorry.
It will be implemented. Thks!

@stockiNail
Copy link
Contributor

@rr22x let me share with you a first results and let me know if you see something not correct.

The floating data for Bar datasets has been implemented. We are doing the tests
The timeseries (by DataPoint and TimeSeriesItem) are still missing.

Here is the code of a sample:

BarChartWidget chart = new BarChartWidget();
chart.getOptions().setResponsive(true);
chart.getOptions().getLegend().setPosition(Position.TOP);
chart.getOptions().getTitle().setDisplay(true);
chart.getOptions().getTitle().setText("Bar chart");

BarDataset dataset1 = chart.newDataset();
dataset1.setLabel("dataset 1");

IsColor color1 = GoogleChartColor.values()[0];

dataset1.setBackgroundColor(color1.alpha(0.2));
dataset1.setBorderColor(color1.toHex());
dataset1.setBorderWidth(1);

// -------------
// creates Floating DATA
// -------------
double[] values = getRandomDigits(months);
double[] gaps = getRandomDigits(months, false);

List<FloatingData> data = new LinkedList<>();
for (int i=0; i<months; i++) {
	data.add(new FloatingData(values[i], values[i] + gaps[i]));
}
dataset1.setFloatingData(data);
// -------------

chart.getData().setLabels(getLabels());

chart.getData().setDatasets(dataset1);

bug55

More in the next days.

@rr22x
Copy link
Author

rr22x commented May 13, 2020

That looks very good! exactly what i need

@stockiNail
Copy link
Contributor

@rr22x the implementation of floating bars has been merged into master.

We are now working on timeseries. If you need it urgently, feel free to clone (or fetch) the master and compile Charba.
We decided to release new version with this feature and also with new annotation plugin, where new options has been released.

But of course we need time to release it (doc, showcases for J2CL and GWT where we are preparing some use cases with new features).

@stockiNail
Copy link
Contributor

@rr22x let me share with you that floating bars are not working on time scales, at least on examples I did.
See CHART.JS issue #7356 where I have asked more info about that.
Waiting for a feedback (I think we need Chart.JS v3), we stooped further development on time series.

@rr22x
Copy link
Author

rr22x commented May 15, 2020

@stockiNail Many thanks for the feedback. So I tested out the new feature. It works!
In my usecase the timeline feature is not mandatory as I create and set the time labels myself. However, I watch the issue with interest.

floating_bar

@stockiNail
Copy link
Contributor

@rr22x fine!
About the implementation, we have to check how Labels and DataLabels plugins are working with floating bars.
There are some callbacks where a double is passed as value but I think an array should be passed in case of floating bars.
This last case is not ready. Let me use this issue to share also this updates on plugins before closing it, if is ok for you.

@rr22x
Copy link
Author

rr22x commented May 15, 2020

@stockiNail ok. no problem. i also work with the DataLabels plugin. Maybe i can give feedback

@stockiNail
Copy link
Contributor

Would be great!
I didn't have time to test it yet (I'm gonna do later this afternoon) but I think the issue could be on DataLabels formatting callback.
First, I need to check if DataLabels works with floating bars.
Second, if the object passed in case of floating bars is an array (what I expect) or other and then to prepare an interface to implement for formatting callback.

@rr22x
Copy link
Author

rr22x commented May 15, 2020

@stockiNail ok i tested it with the formatting callback. there is no exception or something, but apparently the formatter is called twice - for the start and the end value seperately

@stockiNail
Copy link
Contributor

@rr22x Thank youuuu! I think it could be acceptable even if, from my mindset, I'd would prefer to call callback once with the array. What do you think?

@rr22x
Copy link
Author

rr22x commented May 15, 2020

@stockiNail yes i also think one callback is sufficient. Especially in my usecase i have to display both values in one label.

data_label_low_high

@stockiNail
Copy link
Contributor

@rr22x first of all, the feature on time series is already implemented in CHART.JS and it will deliver in v3.
Nevertheless it's also possible to use floating bars on time scale with version 2.9.3 by a workaround (an example will be available in showcase).

About the callback, we're gonna start thinking, designing and developing the interface for a single callback.
Thank you very much!

@stockiNail
Copy link
Contributor

@rr22x we have committed into master the floating bars implementation. We have changed also the DataLabels plugin callback for formatting in order to manage whatever data type of datasets (doubles, string and arrays of doubles).

The same has been been done for Labels Plugin, the intercafe remains the same but the RenderItem is changed in order to manage whatever data type of datasets (doubles, string and arrays of doubles).

We have also created some test/use cases for floating bars. They will be committed soon on both shocase projects.

Let us know how is going with this feature.

@stockiNail
Copy link
Contributor

@rr22x floating bars + DataLabels sample.

bug551

Code:

BarChartWidget chart = new BarChartWidget();
chart.getOptions().setResponsive(true);
chart.getOptions().getLegend().setDisplay(false);
chart.getOptions().getTooltips().setEnabled(false);
chart.getOptions().getLayout().getPadding().setTop(32);
chart.getOptions().getElements().getLine().setFill(false);

chart.getOptions().getPlugins().setEnabled(DefaultPlugin.LEGEND, false);
chart.getOptions().getPlugins().setEnabled(DefaultPlugin.TITLE, false);

BarDataset dataset1 = chart.newDataset();
dataset1.setLabel("dataset 1");

IsColor color1 = GoogleChartColor.values()[0];

dataset1.setBackgroundColor(color1.toHex());
dataset1.setBorderColor(color1.toHex());

double[] values = getRandomDigits(months);
double[] gaps = getRandomDigits(months, false);

double[][] dataToSet = new double[months][2];
for (int i=0; i<months; i++) {
	dataToSet[i] = new double[] {values[i], values[i] + Math.max(gaps[i], 20)};
}
dataset1.setFloatingData(dataToSet);

CartesianCategoryAxis axis1 = new CartesianCategoryAxis(chart);
axis1.setDisplay(true);
axis1.setOffset(true);

CartesianLinearAxis axis2 = new CartesianLinearAxis(chart);
axis2.setDisplay(true);
axis2.getTicks().setBeginAtZero(true);
axis2.getScaleLabel().setDisplay(true);
axis2.getScaleLabel().setLabelString("Value");

chart.getOptions().getScales().setXAxes(axis1);
chart.getOptions().getScales().setYAxes(axis2);

chart.getData().setLabels(getLabels());
chart.getData().setDatasets(dataset1);

DataLabelsOptions top = new DataLabelsOptions();
top.setAlign(Align.CENTER);
top.setAnchor(Anchor.END);
top.setBackgroundColor(HtmlColor.WHITE);
top.setColor(HtmlColor.GREEN);
top.setBorderColor(color1);
top.setBorderRadius(25);
top.setBorderWidth(2);
top.setDisplay(Display.AUTO);
top.getFont().setWeight(Weight.BOLD);
top.setFormatter(new FormatterCallback() {

	@Override
	public String invoke(IsChart chart, DataItem dataItem, ScriptableContext context) {
		return Utilities.applyPrecision(dataItem.getValueAsFloatingData().getEnd(), 0);
	}

});

DataLabelsOptions down = new DataLabelsOptions();
down.setAlign(Align.CENTER);
down.setAnchor(Anchor.START);
down.setBackgroundColor(HtmlColor.WHITE);
down.setColor(HtmlColor.RED);
down.setBorderColor(color1);
down.setBorderRadius(25);
down.setBorderWidth(2);
down.getFont().setWeight(Weight.BOLD);
down.setFormatter(new FormatterCallback() {

	@Override
	public String invoke(IsChart chart, DataItem dataItem, ScriptableContext context) {
		return Utilities.applyPrecision(dataItem.getValueAsFloatingData().getStart(), 0);
	}

});

DataLabelsOptions option = new DataLabelsOptions();
option.getLabels().setLabel("top", top);
option.getLabels().setLabel("down", down);

chart.getOptions().getPlugins().setOptions(DataLabelsPlugin.ID, option);

@rr22x
Copy link
Author

rr22x commented May 18, 2020

@stockiNail wow that's fantastic!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants