plotly.js
Version:
The open source javascript graphing library that powers plotly
263 lines (239 loc) • 9.09 kB
JavaScript
'use strict';
var colorbarAttrs = require('../colorbar/attributes');
var counterRegex = require('../../lib/regex').counter;
var sortObjectKeys = require('../../lib/sort_object_keys').default;
var palettes = require('./scales.js').scales;
var paletteStr = sortObjectKeys(palettes);
function code(s) {
return '`' + s + '`';
}
/**
* Make colorscale attribute declarations for
*
* - colorscale,
* - (c|z)auto, (c|z)min, (c|z)max,
* - autocolorscale, reversescale,
* - showscale (optionally)
* - color (optionally)
*
* @param {string} context (dflt: '', i.e. from trace root):
* the container this is in ('', *marker*, *marker.line* etc)
*
* @param {object} opts:
* - cLetter {string} (dflt: 'c'):
* leading letter for 'min', 'max and 'auto' attribute (either 'z' or 'c')
*
* - colorAttr {string} (dflt: 'z' if `cLetter: 'z'`, 'color' if `cLetter: 'c'`):
* (for descriptions) sets the name of the color attribute that maps to the colorscale.
*
* N.B. if `colorAttr: 'color'`, we include the `color` declaration here.
*
* - onlyIfNumerical {string} (dflt: false' if `cLetter: 'z'`, true if `cLetter: 'c'`):
* (for descriptions) set to true if colorscale attribute only
*
* - colorscaleDflt {string}:
* overrides the colorscale dflt
*
* - autoColorDflt {boolean} (dflt true):
* normally autocolorscale.dflt is `true`, but pass `false` to override
*
* - noScale {boolean} (dflt: true if `context: 'marker.line'`, false otherwise):
* set to `false` to not include showscale attribute (e.g. for 'marker.line')
*
* - showScaleDflt {boolean} (dflt: true if `cLetter: 'z'`, false otherwise)
*
* - editTypeOverride {boolean} (dflt: ''):
* most of these attributes already require a recalc, but the ones that do not
* have editType *style* or *plot* unless you override (presumably with *calc*)
*
* - anim {boolean) (dflt: undefined): is 'color' animatable?
*
* @return {object}
*/
module.exports = function colorScaleAttrs(context, opts) {
context = context || '';
opts = opts || {};
var cLetter = opts.cLetter || 'c';
var onlyIfNumerical = 'onlyIfNumerical' in opts ? opts.onlyIfNumerical : Boolean(context);
var noScale = 'noScale' in opts ? opts.noScale : context === 'marker.line';
var showScaleDflt = 'showScaleDflt' in opts ? opts.showScaleDflt : cLetter === 'z';
var colorscaleDflt = typeof opts.colorscaleDflt === 'string' ? palettes[opts.colorscaleDflt] : null;
var editTypeOverride = opts.editTypeOverride || '';
var contextHead = context ? context + '.' : '';
var colorAttr, colorAttrFull;
if ('colorAttr' in opts) {
colorAttr = opts.colorAttr;
colorAttrFull = opts.colorAttr;
} else {
colorAttr = { z: 'z', c: 'color' }[cLetter];
colorAttrFull = 'in ' + code(contextHead + colorAttr);
}
var effectDesc = onlyIfNumerical ? ' Has an effect only if ' + colorAttrFull + ' is set to a numerical array.' : '';
var auto = cLetter + 'auto';
var min = cLetter + 'min';
var max = cLetter + 'max';
var mid = cLetter + 'mid';
var autoFull = code(contextHead + auto);
var minFull = code(contextHead + min);
var maxFull = code(contextHead + max);
var minmaxFull = minFull + ' and ' + maxFull;
var autoImpliedEdits = {};
autoImpliedEdits[min] = autoImpliedEdits[max] = undefined;
var minmaxImpliedEdits = {};
minmaxImpliedEdits[auto] = false;
var attrs = {};
if (colorAttr === 'color') {
attrs.color = {
valType: 'color',
arrayOk: true,
editType: editTypeOverride || 'style',
description: [
'Sets the',
context,
'color.',
'It accepts either a specific color',
'or an array of numbers that are mapped to the colorscale',
'relative to the max and min values of the array or relative to',
minmaxFull,
'if set.'
].join(' ')
};
if (opts.anim) {
attrs.color.anim = true;
}
}
attrs[auto] = {
valType: 'boolean',
dflt: true,
editType: 'calc',
impliedEdits: autoImpliedEdits,
description: [
'Determines whether or not the color domain is computed',
'with respect to the input data (here ' + colorAttrFull + ') or the bounds set in',
minmaxFull + effectDesc,
'Defaults to `false` when',
minmaxFull,
'are set by the user.'
].join(' ')
};
attrs[min] = {
valType: 'number',
dflt: null,
editType: editTypeOverride || 'plot',
impliedEdits: minmaxImpliedEdits,
description: [
'Sets the lower bound of the color domain.' + effectDesc,
'Value should have the same units as',
colorAttrFull,
'and if set,',
maxFull,
'must be set as well.'
].join(' ')
};
attrs[max] = {
valType: 'number',
dflt: null,
editType: editTypeOverride || 'plot',
impliedEdits: minmaxImpliedEdits,
description: [
'Sets the upper bound of the color domain.' + effectDesc,
'Value should have the same units as',
colorAttrFull,
'and if set,',
minFull,
'must be set as well.'
].join(' ')
};
attrs[mid] = {
valType: 'number',
dflt: null,
editType: 'calc',
impliedEdits: autoImpliedEdits,
description: [
'Sets the mid-point of the color domain by scaling',
minFull,
'and/or',
maxFull,
'to be equidistant to this point.' + effectDesc,
'Value should have the same units as',
colorAttrFull + '.',
'Has no effect when',
autoFull,
'is `false`.'
].join(' ')
};
attrs.colorscale = {
valType: 'colorscale',
editType: 'calc',
dflt: colorscaleDflt,
impliedEdits: { autocolorscale: false },
description: [
'Sets the colorscale.' + effectDesc,
'The colorscale must be an array containing',
'arrays mapping a normalized value to an',
'rgb, rgba, hex, hsl, hsla, hwb, or named color string.',
'At minimum, a mapping for the lowest (0) and highest (1)',
'values are required. For example,',
"`[[0, 'rgb(0,0,255)'], [1, 'rgb(255,0,0)']]`.",
'To control the bounds of the colorscale in color space,',
'use',
minmaxFull + '.',
'Alternatively, `colorscale` may be a palette name string',
'of the following list: ' + paletteStr + '.'
].join(' ')
};
attrs.autocolorscale = {
valType: 'boolean',
// gets overrode in 'heatmap' & 'surface' for backwards comp.
dflt: opts.autoColorDflt === false ? false : true,
editType: 'calc',
impliedEdits: { colorscale: undefined },
description: [
'Determines whether the colorscale is a default palette (`autocolorscale: true`)',
'or the palette determined by',
code(contextHead + 'colorscale') + '.' + effectDesc,
'In case `colorscale` is unspecified or `autocolorscale` is true, the default',
'palette will be chosen according to whether numbers in the `color` array are',
'all positive, all negative or mixed.'
].join(' ')
};
attrs.reversescale = {
valType: 'boolean',
dflt: false,
editType: 'plot',
description: [
'Reverses the color mapping if true.' + effectDesc,
'If true,',
minFull,
'will correspond to the last color',
'in the array and',
maxFull,
'will correspond to the first color.'
].join(' ')
};
if (!noScale) {
attrs.showscale = {
valType: 'boolean',
dflt: showScaleDflt,
editType: 'calc',
description: ['Determines whether or not a colorbar is displayed for this trace.' + effectDesc].join(' ')
};
attrs.colorbar = colorbarAttrs;
}
if (!opts.noColorAxis) {
attrs.coloraxis = {
valType: 'subplotid',
regex: counterRegex('coloraxis'),
dflt: null,
editType: 'calc',
description: [
'Sets a reference to a shared color axis.',
'References to these shared color axes are *coloraxis*, *coloraxis2*, *coloraxis3*, etc.',
'Settings for these shared color axes are set in the layout, under',
'`layout.coloraxis`, `layout.coloraxis2`, etc.',
'Note that multiple color scales can be linked to the same color axis.'
].join(' ')
};
}
return attrs;
};