diff options
author | href <href@random.sh> | 2021-09-01 10:30:18 +0200 |
---|---|---|
committer | href <href@random.sh> | 2021-09-01 10:30:18 +0200 |
commit | 75687711f35355bc30e4829439384aab28fcac6d (patch) | |
tree | 8f3256f472893c39720a684d390e890a152f7303 /priv/static/js/metricsgraphics/common/zoom.js | |
parent | link: 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.js | 85 |
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; + +} |