Published
Edited
Mar 27, 2020
Importers
Insert cell
md`# zoom`
Insert cell
function zoomToDataDomain(args, range) {
const rawData = args.processed.rawData || args.data;

// store raw data and raw domain to in order to zoom back to the initial state
if (!('rawData' in args.processed)) {
args.processed.rawDomain = {
x: args.scales.X.domain(),
y: args.scales.Y.domain()
};
args.processed.rawData = rawData;
}

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.chartType === 'point') {
args.data = isArrayOfArrays(rawData)
? rawData.map(d => d.filter(filterInRangeData(args, range)))
: rawData.filter(filterInRangeData(args, range));
if (args.data.flat().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.rawDomain) {
createBrushingPattern(
args.processed.subplot,
convertDomainToRange(args.processed.subplot, range)
);
} else {
removeBrushingPattern(args.processed.subplot);
}
}
// new charts[args.chartType || defaults.chartType].descriptor(args)
}
Insert cell
function zoomToRawRange(args) {
if (!('rawDomain' in args.processed)) return;
zoomToDataDomain(args, args.processed.rawDomain);
delete args.processed.rawDomain;
delete args.processed.rawData;
}
Insert cell
function convertRangeToDomain(args, range) {
return ['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;
}, {});
}
Insert cell
function convertDomainToRange(args, domain) {
return ['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;
}, {});
}
Insert cell
function filterInRangeData(args, range) {
const isDataInRange = (data, range) =>
data > d3Array.min(range) && data < d3Array.max(range);

// if range without this axis return true, else judge is data in range or not.
return d =>
['x', 'y'].every(
dim =>
!(dim in range) || isDataInRange(d[args[`${dim}_accessor`]], range[dim])
);
}
Insert cell
function zoomToDataRange(args, range) {
const domain = convertRangeToDomain(args, range);
zoomToDataDomain(args, domain);
}
Insert cell
import { isArrayOfArrays } from '@neatlogic/utility'
Insert cell
d3Array = require('d3-array')
Insert cell
import { createBrushingPattern, removeBrushingPattern } from '@neatlogic/brush'
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more