-
Notifications
You must be signed in to change notification settings - Fork 6
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
Trying to integrate chartjs-plugin-crosshair #88
Comments
@Speykious if the plugin is registered, you don't have to enable it, because it's enabled by default. chartOptions.getPlugins().setEnabled("crosshair", true); Maybe you can log the chart options in order to see the JS structure of the config: Console.log(chart.getOptions().toJSON()); |
Yeah, I didn't set the chart options at first because I thought it would work without, but it didn't so that's why I tried it that way. I'll remove it. Ok, I'll try logging the options. |
1 similar comment
Yeah, I didn't set the chart options at first because I thought it would work without, but it didn't so that's why I tried it that way. I'll remove it. Ok, I'll try logging the options. |
"plugins": {
"legend": {
"display": true
},
"title": {
"display": true,
"text": "test"
},
"tooltip": {
"enabled": true
},
"decimation": {
"enabled": true,
"algorithm": "min-max"
},
"crosshair": {
"charbaOptionsId": "crosshair-1",
"line": {
"color": "#F66",
"width": 1
},
"sync": {
"enabled": true,
"group": 1,
"suppressTooltips": false
},
"zoom": {
"enabled": true,
"zoomboxBackgroundColor": "rgba(66,133,244,0.2)",
"zoomboxBorderColor": "#48F",
"zoomButtonText": "Reset Zoom",
"zoomButtonClass": "reset-zoom"
}
}
}, It seems that I laid out my options correctly, and the plugin is at the right place... |
Yes, that's correct. In this case, it seems something went wrong in the registration/injection of the plugin. Could you also check the HEAD element if it is really injected? |
@Speykious using your code, I was able to get the following (see red line of crosshair): Below the code (base on showcase): package org.pepstock.charba.showcase.client.cases.extensions;
import java.util.List;
import org.pepstock.charba.client.Injector;
import org.pepstock.charba.client.colors.GoogleChartColor;
import org.pepstock.charba.client.colors.IsColor;
import org.pepstock.charba.client.commons.Key;
import org.pepstock.charba.client.commons.NativeObject;
import org.pepstock.charba.client.commons.NativeObjectContainer;
import org.pepstock.charba.client.data.BarDataset;
import org.pepstock.charba.client.data.Dataset;
import org.pepstock.charba.client.enums.Position;
import org.pepstock.charba.client.gwt.widgets.BarChartWidget;
import org.pepstock.charba.client.plugins.AbstractPluginOptions;
import org.pepstock.charba.client.resources.InjectableTextResource;
import org.pepstock.charba.showcase.client.cases.commons.BaseComposite;
import org.pepstock.charba.showcase.client.resources.MyResources;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Widget;
public class ImportingPluginCase extends BaseComposite {
static {
Injector.ensureInjected(new InjectableTextResource(MyResources.INSTANCE.chartJsCrosshairSource()));
}
private static ViewUiBinder uiBinder = GWT.create(ViewUiBinder.class);
interface ViewUiBinder extends UiBinder<Widget, ImportingPluginCase> {
}
@UiField
BarChartWidget chart;
private static final String PLUGIN_NAME = "crosshair";
public ImportingPluginCase() {
initWidget(uiBinder.createAndBindUi(this));
chart.getOptions().setResponsive(true);
chart.getOptions().getLegend().setPosition(Position.TOP);
chart.getOptions().getTitle().setDisplay(true);
chart.getOptions().getTitle().setText("Importing Stacked100 plugin on bar chart");
BarDataset dataset1 = chart.newDataset();
dataset1.setLabel("dataset 1");
IsColor color1 = GoogleChartColor.values()[0];
dataset1.setBackgroundColor(color1.alpha(0.2D));
dataset1.setData(getRandomDigits(months, false));
BarDataset dataset2 = chart.newDataset();
dataset2.setLabel("dataset 2");
IsColor color2 = GoogleChartColor.values()[1];
dataset2.setBackgroundColor(color2.alpha(0.2D));
dataset2.setData(getRandomDigits(months, false));
BarDataset dataset3 = chart.newDataset();
dataset3.setLabel("dataset 3");
IsColor color3 = GoogleChartColor.values()[2];
dataset3.setBackgroundColor(color3.alpha(0.2D));
dataset3.setData(getRandomDigits(months, false));
chart.getData().setLabels(getLabels());
chart.getData().setDatasets(dataset1, dataset2, dataset3);
CharbaCrosshairOptions crosshairOptions = new CharbaCrosshairOptions();
crosshairOptions.setLine(LineOptions.getDefault());
crosshairOptions.store(chart);
}
@UiHandler("randomize")
protected void handleRandomize(ClickEvent event) {
for (Dataset dataset : chart.getData().getDatasets()) {
dataset.setData(getRandomDigits(months, false));
}
chart.update();
}
@UiHandler("add_dataset")
protected void handleAddDataset(ClickEvent event) {
List<Dataset> datasets = chart.getData().getDatasets();
BarDataset dataset = chart.newDataset();
dataset.setLabel("dataset " + (datasets.size() + 1));
IsColor color = GoogleChartColor.values()[datasets.size()];
dataset.setBackgroundColor(color.alpha(0.2));
dataset.setData(getRandomDigits(months, false));
datasets.add(dataset);
chart.update();
}
@UiHandler("remove_dataset")
protected void handleRemoveDataset(ClickEvent event) {
removeDataset(chart);
}
@UiHandler("add_data")
protected void handleAddData(ClickEvent event) {
addData(chart);
}
@UiHandler("remove_data")
protected void handleRemoveData(ClickEvent event) {
removeData(chart);
}
@UiHandler("source")
protected void handleViewSource(ClickEvent event) {
Window.open(getUrl(), "_blank", "");
}
public static class CharbaCrosshairOptions extends AbstractPluginOptions {
private enum Property implements Key {
line,
sync,
zoom;
@Override
public String value() {
return this.toString();
}
}
public CharbaCrosshairOptions() {
super(PLUGIN_NAME, null);
}
public void setLine(LineOptions lineOptions) {
setValue(Property.line, lineOptions);
}
}
public static final class LineOptions extends NativeObjectContainer {
private enum Property implements Key {
color,
width;
@Override
public String value() {
return this.toString();
}
}
public static LineOptions getDefault() {
LineOptions lineOptions = new LineOptions();
lineOptions.setColor("#F66");
lineOptions.setWidth(1);
return lineOptions;
}
public LineOptions() {
this(null);
}
LineOptions(NativeObject nativeObject) {
super(nativeObject);
}
public void setColor(String color) {
setValue(Property.color, color);
}
public void setWidth(double width) {
setValue(Property.width, width);
}
}
} |
I do see After further investigation, it actually seems to fail to inject the script despite that, getting an error like this:
It fails at the line |
This is regardless of where I put the |
The error seems to be related to the fact that
|
This is just for reproducing the error. |
@Speykious I was able to reproduce the bug. let me take time to have a look. |
I have found the issue but I need to change a bit the ResourcesType.getResources().inject(); In the meanwhile I'll work to fix it. |
The bug here is that when the injection is not deferred (GWT code splitting) the wrong assumption was that the injection of CHART.JS, datetime lib and datetime adapter would be done bythe first object which needs them. |
Fix has been commit in a parallel brach: 147d1ef |
We decided to revert that above commit to maintain the feature to inject CHART.JS and other mandatory items only when requested. // enables Charba
Charba.enable();
// injects crosshair plugin wihich automatically registers itself as global plugin
// you can invoke wherever you want and how many times you want, the plugin will be added only the first time
Defaults.get().getPlugins().register(new InjectableTextResource(MyResources.INSTANCE.chartJsCrosshairSource())); The documentation will be changed accordingly. This will be available in version 6.2. We are going to publish it end of next week or beginning of March. @Speykious let me thank you for this issue. No many users are importing extensions on Charba and with this use case we could discover this bug! I would like to ask you if:
|
@Speykious we have implemented also in crosshair plugin available ootb in Charba. Thank you for hint! Charba.showcase.GWT.-.Google.Chrome.2023-02-18.16-48-49.mp4 |
You always respond so fast! It's amazing to see projects with maintainers that are this active. Thank you for all the time you've spent on this. Anyways, I have tried the following workaround: Charba.enable();
ResourcesType.getResources().inject();
Injector.ensureInjected(new InjectableTextResource(MyResources.INSTANCE.chartjsPluginCrosshair())); Unfortunately, instead of working, I got a type error because it can't read
If the bug is not present with the new version, farewell! But as of now I am still blocked on this issue. :( |
As for your OOTB implementation of chart synchronization with the builtin crosshair plugin, since you seem to be interested in providing a solution, let me tell you what we use Charba for currently. We need to show several time series line charts, and be able to horizontally pan, wheel-zoom and drag-zoom on them such that they are all synchronized on the X axis and all update at the same time. If you try to drag-zoom on the Linked Charts section of the chartjs-plugin-crosshair demo page, you'll see what I mean. Ideally it would have the same API as what we can do with the currently existing // this works perfectly well for us on one chart, but we need charts that are synchronized on this behavior
ZoomOptions zoomOptions = new ZoomOptions();
zoomOptions.getPan().setEnabled(true);
zoomOptions.getPan().setModifierKey(ModifierKey.CTRL);
zoomOptions.getPan().setMode(Mode.X);
zoomOptions.getZoom().setMode(Mode.X);
zoomOptions.getZoom().getDrag().setEnabled(true);
zoomOptions.getZoom().getWheel().setEnabled(true);
zoomOptions.getZoom().getWheel().setSpeed(0.3);
zoomOptions.getZoom().getWheel().setModifierKey(ModifierKey.CTRL);
zoomOptions.getZoom().getPinch().setEnabled(true);
zoomOptions.store(chart); |
Uhm... testing locally, without new patch, the workaround sounds working. Let me check more in deep. Maybe you have a simple example where the code is failing, in your app, so I can try it locally. |
Before developing the Charba crosshair plugin, I had a look to CHART.JS crosshair plugin. It seems to me a bit unmaintained (see issues and PRs still pending) therefore we decided to create a simple plugin for that, without all options. But you gave us a good idea to provide that features, therefore we did ;).
This is possible even if I didn't create any show case for that. But I did for a discussion in Let me take time to address the issue you above reported and then I'm going to give some instructions how to sync the zoom, by zoom plugin. chartjs-plugin.crosshair has got another feature, the "tracing" on line datasets (and only line dataset), where moving on chart dataset you see the tooltip with the values. Unfortunately this is working only for line datasets and has got the requirement that the data points of the line dataset must be ordered by X value (not always is true). In Charba, we tried to avoid specific implementation for specific chart type but we have already started to add additional feature in order to easily reach also that feature. The first feedback for you is to stay on |
I see... Sorry, I currently don't have a local example, since I tried it by integrating it directly into our project. I might create one today but I'm not sure, I'll have a meeting before that to see what we can do in any case. |
@Speykious no problem. I have created a simple project and the workaround sounds working... |
< Ideally it would have the same API as what we can do with the currently existing ZoomPlugin of Charba, but with a way to synchronize charts. @Speykious I forgot to mention that if you need the zooming, you could use the OOTB plugin of Charba DatasetItemsSelector, that we developed.
|
Charba.showcase.GWT.-.Google.Chrome.2023-02-20.13-17-03.mp4 |
This is awesome! Is panning synchronized with this as well? |
The sample is setting the same min/max dates to the time axis on all charts, therefore I would say yes. |
Perfect. In the mean time I tried to replicate what you did in JS on codepen in Charba, and I got a weird behavior: // zoom options
ZoomOptions zoomOptions = new ZoomOptions();
zoomOptions.getPan().setEnabled(true);
zoomOptions.getPan().setModifierKey(ModifierKey.ALT);
zoomOptions.getPan().setMode(Mode.X);
zoomOptions.getZoom().setMode(Mode.X);
zoomOptions.getZoom().getDrag().setEnabled(true);
zoomOptions.getZoom().getWheel().setEnabled(true);
zoomOptions.getZoom().getWheel().setSpeed(0.3);
zoomOptions.getZoom().getWheel().setModifierKey(ModifierKey.ALT);
zoomOptions.getZoom().getPinch().setEnabled(true);
zoomOptions.store(chart);
zoomOptions.getZoom().setCompletedCallback((ZoomContext context) -> {
CartesianTimeSeriesAxis timeAxis = chart.getOptions().getScales().getTimeAxis();
_logger.info("minmax: " + timeAxis.getMin() + " -> " + timeAxis.getMax());
for (TimeSeriesLineChartWidget rawChart : _rawCharts) {
if (rawChart == chart)
continue;
CartesianTimeSeriesAxis rawTimeAxis = rawChart.getOptions().getScales().getTimeAxis();
rawTimeAxis.setMin(timeAxis.getMin());
rawTimeAxis.setMax(timeAxis.getMax());
rawChart.update();
}
}); |
@Speykious in chartjs there is a difference between configuration and options. What you doing is changing the "configuration" but the zoom plugin is changing the options. The onComplete callback should be the following: // gets axis from config
CartesianTimeSeriesAxis timeAxis = chart.getOptions().getScales().getTimeAxis();
// gets scale from options
ScaleItem scaleAxis = chart.getNode().getScales().getItems().get(timeAxis.getId().value());
_logger.info("minmax: " + scaleAxis.getMinAsDate() + " -> " + scaleAxis.getMaxAsDate());
for (TimeSeriesLineChartWidget rawChart : _rawCharts) {
if (rawChart == chart)
continue;
CartesianTimeSeriesAxis rawTimeAxis = rawChart.getOptions().getScales().getTimeAxis();
rawTimeAxis.setMin(scaleAxis.getMinAsDate());
rawTimeAxis.setMax(scaleAxis.getMaxAsDate());
// reload chart with new configuration
rawChart.reconfigure();
} |
FYI, the better solution is the following:
private Date minDate = null;
private Date maxDate = null;
axis.setMin(new MinMaxCallback<Date>() {
@Override
public Date invoke(ScaleContext context) {
return minDate;
}
});
axis.setMax(new MinMaxCallback<Date>() {
@Override
public Date invoke(ScaleContext context) {
return maxDate;
}
});
zoomOptions.getZoom().setCompletedCallback((ZoomContext context) -> {
// gets axis from config
CartesianTimeSeriesAxis timeAxis = chart.getOptions().getScales().getTimeAxis();
// gets scale from options
ScaleItem scaleAxis = chart.getNode().getScales().getItems().get(timeAxis.getId().value());
minDate = scaleAxis.getMinAsDate();
maxDate = scaleAxis.getMaxAsDate();
for (TimeSeriesLineChartWidget rawChart : _rawCharts) {
if (rawChart == chart)
continue;
rawChart.update();
}
}); |
I'm going to create a separate issue for chart synchronization using OOTB plugins. |
Do you mean for Zoom? For Crosshair, it's already committed.
Yes, in my test case, that I did yesterday, it works. I have created a GWT project where onModule creates a chart and adds to the root panel (nothing in the middle). |
Indeed, I mean for zoom and panning. The only reason I looked at a way to integrate chartjs-plugin-crosshair is because it had the linked chart feature. |
Fixed in version 6.2 |
@stockiNail I found a point where your OOTB crosshair plugin is different from the javascript one link. As shown in the two screenshots, the javascript one shows tooltips in all linked charts, but the OOTB one only shows tooltip in the chart under the mouse. ![]() ![]()
|
I'm trying to integrate the chartjs-plugin-crosshair plugin, but I couldn't make it work.
There is a crosshair plugin already integrated into Charba, but it's not this one, and the other features of chartjs-plugin-crosshair (linked charts specifically) are very important. I'm not sure what I can do to make it work properly?
Here's what I did so far:
chartjs-plugin-crosshair.min.js
and register it as a resource in a GWTClientBundle
Injector.ensureInjected(...... .chartjsPluginCrosshair())
And then enable the plugin on the chart with the default options I set up:
But nothing happens. Nothing crashes, but nothing works either. I'm unsure what I'm missing. What's going on?
The text was updated successfully, but these errors were encountered: