@uwdata/mosaic-plot
Version:
A Mosaic-powered plotting framework based on Observable Plot.
240 lines (237 loc) • 7.7 kB
JavaScript
export const attributeMap = new Map([
['style', 'style'],
['width', 'width'],
['height', 'height'],
['margin', 'margin'],
['marginLeft', 'marginLeft'],
['marginRight', 'marginRight'],
['marginTop', 'marginTop'],
['marginBottom', 'marginBottom'],
['align', 'align'],
['aspectRatio', 'aspectRatio'],
['axis', 'axis'],
['inset', 'inset'],
['grid', 'grid'],
['label', 'label'],
['padding', 'padding'],
['xScale', 'x.type'],
['xDomain', 'x.domain'],
['xRange', 'x.range'],
['xNice', 'x.nice'],
['xInset', 'x.inset'],
['xInsetLeft', 'x.insetLeft'],
['xInsetRight', 'x.insetRight'],
['xClamp', 'x.clamp'],
['xRound', 'x.round'],
['xAlign', 'x.align'],
['xPadding', 'x.padding'],
['xPaddingInner', 'x.paddingInner'],
['xPaddingOuter', 'x.paddingOuter'],
['xAxis', 'x.axis'],
['xTicks', 'x.ticks'],
['xTickSize', 'x.tickSize'],
['xTickSpacing', 'x.tickSpacing'],
['xTickPadding', 'x.tickPadding'],
['xTickFormat', 'x.tickFormat'],
['xTickRotate', 'x.tickRotate'],
['xGrid', 'x.grid'],
['xLine', 'x.line'],
['xLabel', 'x.label'],
['xLabelAnchor', 'x.labelAnchor'],
['xLabelArrow', 'x.labelArrow'],
['xLabelOffset', 'x.labelOffset'],
['xFontVariant', 'x.fontVariant'],
['xAriaLabel', 'x.ariaLabel'],
['xAriaDescription', 'x.ariaDescription'],
['xPercent', 'x.percent'],
['xReverse', 'x.reverse'],
['xZero', 'x.zero'],
['xBase', 'x.base'],
['xExponent', 'x.exponent'],
['xConstant', 'x.constant'],
['yScale', 'y.type'],
['yDomain', 'y.domain'],
['yRange', 'y.range'],
['yNice', 'y.nice'],
['yInset', 'y.inset'],
['yInsetTop', 'y.insetTop'],
['yInsetBottom', 'y.insetBottom'],
['yClamp', 'y.clamp'],
['yRound', 'y.round'],
['yAlign', 'y.align'],
['yPadding', 'y.padding'],
['yPaddingInner', 'y.paddingInner'],
['yPaddingOuter', 'y.paddingOuter'],
['yAxis', 'y.axis'],
['yTicks', 'y.ticks'],
['yTickSize', 'y.tickSize'],
['yTickSpacing', 'y.tickSpacing'],
['yTickPadding', 'y.tickPadding'],
['yTickFormat', 'y.tickFormat'],
['yTickRotate', 'y.tickRotate'],
['yGrid', 'y.grid'],
['yLine', 'y.line'],
['yLabel', 'y.label'],
['yLabelAnchor', 'y.labelAnchor'],
['yLabelArrow', 'y.labelArrow'],
['yLabelOffset', 'y.labelOffset'],
['yFontVariant', 'y.fontVariant'],
['yAriaLabel', 'y.ariaLabel'],
['yAriaDescription', 'y.ariaDescription'],
['yPercent', 'y.percent'],
['yReverse', 'y.reverse'],
['yZero', 'y.zero'],
['yBase', 'y.base'],
['yExponent', 'y.exponent'],
['yConstant', 'y.constant'],
['facetMargin', 'facet.margin'],
['facetMarginTop', 'facet.marginTop'],
['facetMarginBottom', 'facet.marginBottom'],
['facetMarginLeft', 'facet.marginLeft'],
['facetMarginRight', 'facet.marginRight'],
['facetGrid', 'facet.grid'],
['facetLabel', 'facet.label'],
['fxDomain', 'fx.domain'],
['fxRange', 'fx.range'],
['fxInset', 'fx.inset'],
['fxInsetLeft', 'fx.insetLeft'],
['fxInsetRight', 'fx.insetRight'],
['fxRound', 'fx.round'],
['fxAlign', 'fx.align'],
['fxPadding', 'fx.padding'],
['fxPaddingInner', 'fx.paddingInner'],
['fxPaddingOuter', 'fx.paddingOuter'],
['fxAxis', 'fx.axis'],
['fxTicks', 'fx.ticks'],
['fxTickSize', 'fx.tickSize'],
['fxTickSpacing', 'fx.tickSpacing'],
['fxTickPadding', 'fx.tickPadding'],
['fxTickFormat', 'fx.tickFormat'],
['fxTickRotate', 'fx.tickRotate'],
['fxGrid', 'fx.grid'],
['fxLine', 'fx.line'],
['fxLabel', 'fx.label'],
['fxLabelAnchor', 'fx.labelAnchor'],
['fxLabelOffset', 'fx.labelOffset'],
['fxFontVariant', 'fx.fontVariant'],
['fxAriaLabel', 'fx.ariaLabel'],
['fxAriaDescription', 'fx.ariaDescription'],
['fxReverse', 'fx.reverse'],
['fyDomain', 'fy.domain'],
['fyRange', 'fy.range'],
['fyInset', 'fy,inset'],
['fyInsetTop', 'fy.insetTop'],
['fyInsetBottom', 'fy.insetBottom'],
['fyRound', 'fy.round'],
['fyAlign', 'fy.align'],
['fyPadding', 'fy.padding'],
['fyPaddingInner', 'fy.paddingInner'],
['fyPaddingOuter', 'fy.paddingOuter'],
['fyAxis', 'fy.axis'],
['fyTicks', 'fy.ticks'],
['fyTickSize', 'fy.tickSize'],
['fyTickSpacing', 'fy.tickSpacing'],
['fyTickPadding', 'fy.tickPadding'],
['fyTickFormat', 'fy.tickFormat'],
['fyTickRotate', 'fy.tickRotate'],
['fyGrid', 'fy.grid'],
['fyLine', 'fy.line'],
['fyLabel', 'fy.label'],
['fyLabelAnchor', 'fy.labelAnchor'],
['fyLabelOffset', 'fy.labelOffset'],
['fyFontVariant', 'fy.fontVariant'],
['fyAriaLabel', 'fy.ariaLabel'],
['fyAriaDescription', 'fy.ariaDescription'],
['fyReverse', 'fy.reverse'],
['colorScale', 'color.type'],
['colorDomain', 'color.domain'],
['colorRange', 'color.range'],
['colorClamp', 'color.clamp'],
['colorN', 'color.n'],
['colorNice', 'color.nice'],
['colorScheme', 'color.scheme'],
['colorInterpolate', 'color.interpolate'],
['colorPivot', 'color.pivot'],
['colorSymmetric', 'color.symmetric'],
['colorLabel', 'color.label'],
['colorPercent', 'color.percent'],
['colorReverse', 'color.reverse'],
['colorZero', 'color.zero'],
['colorTickFormat', 'color.tickFormat'],
['colorBase', 'color.base'],
['colorExponent', 'color.exponent'],
['colorConstant', 'color.constant'],
['opacityScale', 'opacity.type'],
['opacityDomain', 'opacity.domain'],
['opacityRange', 'opacity.range'],
['opacityClamp', 'opacity.clamp'],
['opacityNice', 'opacity.nice'],
['opacityLabel', 'opacity.label'],
['opacityPercent', 'opacity.percent'],
['opacityReverse', 'opacity.reverse'],
['opacityZero', 'opacity.zero'],
['opacityTickFormat', 'opacity.tickFormat'],
['opacityBase', 'opacity.base'],
['opacityExponent', 'opacity.exponent'],
['opacityConstant', 'opacity.constant'],
['symbolScale', 'symbol.type'],
['symbolDomain', 'symbol.domain'],
['symbolRange', 'symbol.range'],
['rScale', 'r.type'],
['rDomain', 'r.domain'],
['rRange', 'r.range'],
['rClamp', 'r.clamp'],
['rNice', 'r.nice'],
['rLabel', 'r.label'],
['rPercent', 'r.percent'],
['rZero', 'r.zero'],
['rBase', 'r.base'],
['rExponent', 'r.exponent'],
['rConstant', 'r.constant'],
['lengthScale', 'length.type'],
['lengthDomain', 'length.domain'],
['lengthRange', 'length.range'],
['lengthClamp', 'length.clamp'],
['lengthNice', 'length.nice'],
['lengthPercent', 'length.percent'],
['lengthZero', 'length.zero'],
['lengthBase', 'length.base'],
['lengthExponent', 'length.exponent'],
['lengthConstant', 'length.constant'],
['projectionType', 'projection.type'],
['projectionParallels', 'projection.parallels'],
['projectionPrecision', 'projection.precision'],
['projectionRotate', 'projection.rotate'],
['projectionDomain', 'projection.domain'],
['projectionInset', 'projection.inset'],
['projectionInsetLeft', 'projection.insetLeft'],
['projectionInsetRight', 'projection.insetRight'],
['projectionInsetTop', 'projection.insetTop'],
['projectionInsetBottom', 'projection.insetBottom'],
['projectionClip', 'projection.clip']
]);
function setProperty(object, path, value) {
for (let i = 0; i < path.length; ++i) {
const key = path[i];
if (i === path.length - 1) {
object[key] = value;
} else {
object = (object[key] || (object[key] = {}));
}
}
}
export function setAttributes(attributes, spec, symbols) {
// populate top-level and scale properties
for (const key in attributes) {
const specKey = attributeMap.get(key);
if (specKey == null) {
throw new Error(`Unrecognized plot attribute: ${key}`);
}
const value = attributes[key];
if (typeof value === 'symbol') {
symbols.push(key);
} else if (value !== undefined) {
setProperty(spec, specKey.split('.'), value);
}
}
}