summaryrefslogtreecommitdiff
path: root/priv/static/js/metricsgraphics/common/zoom.js
diff options
context:
space:
mode:
authorhref <href@random.sh>2021-09-01 10:30:18 +0200
committerhref <href@random.sh>2021-09-01 10:30:18 +0200
commit75687711f35355bc30e4829439384aab28fcac6d (patch)
tree8f3256f472893c39720a684d390e890a152f7303 /priv/static/js/metricsgraphics/common/zoom.js
parentlink: post_* callbacks; html & pdftitle. (diff)
Commit all the changes that hasn't been committed + updates.
Diffstat (limited to '')
-rw-r--r--priv/static/js/metricsgraphics/common/zoom.js85
1 files changed, 85 insertions, 0 deletions
diff --git a/priv/static/js/metricsgraphics/common/zoom.js b/priv/static/js/metricsgraphics/common/zoom.js
new file mode 100644
index 0000000..eb877f2
--- /dev/null
+++ b/priv/static/js/metricsgraphics/common/zoom.js
@@ -0,0 +1,85 @@
+{
+
+const filter_in_range_data = (args, range) => {
+ const is_data_in_range = (data, range) => {
+ return data > Math.min(range[0], range[1]) && data < Math.max(range[0], range[1]);
+ };
+ // if range without this axis return true, else judge is data in range or not.
+ return d => ['x', 'y'].every(dim => !(dim in range) || is_data_in_range(d[args[`${dim}_accessor`]], range[dim]));
+};
+
+// the range here is the range of data
+// range is an object with two optional attributes of x,y, respectively represent ranges on two axes
+const zoom_to_data_domain = (args, range) => {
+ const raw_data = args.processed.raw_data || args.data;
+ // store raw data and raw domain to in order to zoom back to the initial state
+ if (!('raw_data' in args.processed)) {
+ args.processed.raw_domain = {
+ x: args.scales.X.domain(),
+ y: args.scales.Y.domain()
+ };
+ args.processed.raw_data = raw_data;
+ }
+ if (['x', 'y'].some(dim => range[dim][0] === range[dim][1])) return;
+ // to avoid drawing outside the chart in the point chart, unnecessary in line chart.
+ if (args.chart_type === 'point') {
+ if (is_array_of_arrays(raw_data)) {
+ args.data = raw_data.map(function(d) {
+ return d.filter(filter_in_range_data(args, range));
+ });
+ } else {
+ args.data = raw_data.filter(filter_in_range_data(args, range));
+ }
+ if (mg_flatten_array(args.data).length === 0) return;
+ }
+ ['x', 'y'].forEach(dim => {
+ if (dim in range) args.processed[`zoom_${dim}`] = range[dim];
+ else delete args.processed[`zoom_${dim}`];
+ });
+ if (args.processed.subplot) {
+ if (range !== args.processed.raw_domain) {
+ MG.create_brushing_pattern(args.processed.subplot, convert_domain_to_range(args.processed.subplot, range));
+ } else {
+ MG.remove_brushing_pattern(args.processed.subplot);
+ }
+ }
+ new MG.charts[args.chart_type || defaults.chart_type].descriptor(args);
+};
+
+const zoom_to_raw_range = args => {
+ if (!('raw_domain' in args.processed)) return;
+ zoom_to_data_domain(args, args.processed.raw_domain);
+ delete args.processed.raw_domain;
+ delete args.processed.raw_data;
+};
+
+// converts the range of selection into the range of data that we can use to
+// zoom the chart to a particular region
+const convert_range_to_domain = (args, range) =>
+ ['x', 'y'].reduce((domain, dim) => {
+ if (!(dim in range)) return domain;
+ domain[dim] = range[dim].map(v => +args.scales[dim.toUpperCase()].invert(v));
+ if (dim === 'y') domain[dim].reverse();
+ return domain;
+ }, {});
+
+const convert_domain_to_range = (args, domain) =>
+ ['x', 'y'].reduce((range, dim) => {
+ if (!(dim in domain)) return range;
+ range[dim] = domain[dim].map(v => +args.scales[dim.toUpperCase()](v));
+ if (dim === 'y') range[dim].reverse();
+ return range;
+ }, {});
+
+// the range here is the range of selection
+const zoom_to_data_range = (args, range) => {
+ const domain = convert_range_to_domain(args, range);
+ zoom_to_data_domain(args, domain);
+};
+
+MG.convert_range_to_domain = convert_range_to_domain;
+MG.zoom_to_data_domain = zoom_to_data_domain;
+MG.zoom_to_data_range = zoom_to_data_range;
+MG.zoom_to_raw_range = zoom_to_raw_range;
+
+}