Skip to content

Commit

Permalink
LLCAXCHZF-57/Implement Zoom and Pan Functionality for Chart.js
Browse files Browse the repository at this point in the history
  • Loading branch information
TomeCirun committed Jul 28, 2024
1 parent 91ea83c commit 4b22ee3
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 0 deletions.
59 changes: 59 additions & 0 deletions ckanext/charts/assets/js/charts-render-chartjs.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,67 @@ ckan.module("charts-render-chartjs", function ($, _) {
return;
}

const unsupportedTypes = ['pie', 'doughnut', 'radar'];
const isZoomSupported = !unsupportedTypes.includes(this.options.config.type);
let zoomOptions = null;

if (isZoomSupported) {
zoomOptions = this.options.config.options.plugins.zoom;

this.options.config.options.plugins.title.text = () => {
return 'Zoom: ' + this.zoomStatus(zoomOptions) + ', Pan: ' + this.panStatus(zoomOptions);
};

$('#resetZoom').show();
$('#toggleZoom').show();
$('#togglePan').show();
} else {
$('#resetZoom').hide();
$('#toggleZoom').hide();
$('#togglePan').hide();
}

var chart = new Chart(this.el[0].getContext("2d"), this.options.config);
window.charts_chartjs = chart;

$('#resetZoom').on('click', this.resetZoom);
$('#toggleZoom').on('click', (e) => this.toggleZoom(e, zoomOptions));
$('#togglePan').on('click', (e) => this.togglePan(e, zoomOptions));
},
resetZoom: function(event) {
event.preventDefault();
window.charts_chartjs.resetZoom();
},

zoomStatus: function(zoomOptions) {
return zoomOptions.zoom.drag.enabled ? 'enabled' : 'disabled';
},

panStatus: function(zoomOptions) {
return zoomOptions.pan.enabled ? 'enabled' : 'disabled';
},

toggleZoom: function (event, zoomOptions) {
event.preventDefault();

const zoomEnabled = zoomOptions.zoom.wheel.enabled;

zoomOptions.zoom.wheel.enabled = !zoomEnabled;
zoomOptions.zoom.pinch.enabled = !zoomEnabled;
zoomOptions.zoom.drag.enabled = !zoomEnabled;

// Update the chart with the new zoom options
window.charts_chartjs.update();
},

togglePan: function(event, zoomOptions) {
event.preventDefault();

const currentPanEnabled = zoomOptions.pan.enabled;
zoomOptions.pan.enabled = !currentPanEnabled;

// Update the chart with the new zoom options
window.charts_chartjs.update();
}
};
});
7 changes: 7 additions & 0 deletions ckanext/charts/assets/js/vendor/chartjs-plugin-zoom.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions ckanext/charts/assets/js/vendor/hammerjs.min.js

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions ckanext/charts/assets/webassets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ chartjs:
contents:
- js/vendor/chartjs.min.js
- js/charts-render-chartjs.js
- js/vendor/hammerjs.min.js
- js/vendor/chartjs-plugin-zoom.min.js
extra:
preload:
- base/main
Expand Down
34 changes: 34 additions & 0 deletions ckanext/charts/chart_builders/chartjs.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,36 @@ def get_supported_forms(cls) -> list[type[Any]]:
ChartJSRadarForm,
]

def create_zoom_and_title_options(self, options: str[dict, Any]) -> dict[str, Any]:
"""Add zoom and title plugin options to the provided options dictionary"""
zoom_options = {
"zoom": {
"wheel": {"enabled": True},
"pinch": {"enabled": True},
"drag": {"enabled": True},
"mode": "xy",
},
"pan": {
"enabled": True,
"modifierKey": "shift",
"mode": "xy",
},
}

if "plugins" not in options:
options["plugins"] = {}

options["plugins"].update(
{
"zoom": zoom_options,
"title": {
"display": True,
"position": "bottom",
},
}
)
return options


class ChartJSBarBuilder(ChartJsBuilder):
def _prepare_data(self) -> dict[str, Any]:
Expand Down Expand Up @@ -65,6 +95,7 @@ def _prepare_data(self) -> dict[str, Any]:
)

data["data"]["datasets"] = datasets
data["options"] = self.create_zoom_and_title_options(data["options"])

return data

Expand Down Expand Up @@ -134,6 +165,7 @@ def to_json(self) -> str:
"reverse": self.settings.get("invert_y", False),
},
}
data["options"] = self.create_zoom_and_title_options(data["options"])
return json.dumps(data)


Expand Down Expand Up @@ -254,6 +286,7 @@ def to_json(self) -> str:
"data": dataset_data,
}
]
data["options"] = self.create_zoom_and_title_options(data["options"])

return json.dumps(data)

Expand Down Expand Up @@ -312,6 +345,7 @@ def to_json(self) -> str:
data["data"]["datasets"] = [
{"label": self.settings["y"], "data": dataset_data},
]
data["options"] = self.create_zoom_and_title_options(data["options"])

return json.dumps(data)

Expand Down
5 changes: 5 additions & 0 deletions ckanext/charts/templates/charts/snippets/chartjs_chart.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

{% if chart %}
<canvas id="chart-container" data-module="charts-render-chartjs" data-module-config="{{ chart }}"></canvas>
<div>
<button class="btn btn-primary" id="resetZoom">Reset Zoom</button>
<button class="btn btn-primary" id="toggleZoom" class="btn btn-primary">Toggle Zoom</button>
<button class="btn btn-primary" id="togglePan" class="btn btn-primary">Toggle Pan</button>
</div>
{% else %}
<p class="text-muted">
{{ _("Cannot build chart with current settings") }}
Expand Down

0 comments on commit 4b22ee3

Please sign in to comment.