// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫ // ┃ Copyright (c) 2017, the Perspective Authors. ┃ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃ // ┃ This file is part of the Perspective library, distributed under the terms ┃ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ import * as d3 from "d3"; import { domain } from "../axis/linearAxis"; import { Settings, ValueName } from "../types"; export function seriesLinearRange( _settings, data, valueName, customExtent?: any, ) { return d3.scaleLinear().domain(getExtent(data, valueName, customExtent)); } export function seriesColorRange( settings: Settings, data: any[], valueName: ValueName, customExtent = null, ): d3.ScaleSequential { let extent = getExtent(data, valueName, customExtent); let gradient = settings.colorStyles.gradient.full; if (extent[0] >= 0) { gradient = settings.colorStyles.gradient.pos; } else if (extent[1] <= 0) { gradient = settings.colorStyles.gradient.neg; } else { const maxVal = Math.max(-extent[0], extent[1]); extent = [-maxVal, maxVal]; } const interpolator = multiInterpolator(gradient); return d3.scaleSequential(interpolator).domain(extent); } const getExtent = (data: any[], valueName: ValueName, customExtent?: any) => { return customExtent || domain().valueName(valueName).pad([0, 0])(data); }; const multiInterpolator = (gradientPairs) => { // A new interpolator that calls through to a set of // interpolators between each value/color pair const interpolators = gradientPairs .slice(1) .map((p, i) => d3.interpolate(gradientPairs[i][1], p[1])); return (value) => { const index = gradientPairs.findIndex( (p, i) => i < gradientPairs.length - 1 && value <= gradientPairs[i + 1][0] && value > p[0], ); if (index === -1) { if (value <= gradientPairs[0][0]) { return gradientPairs[0][1]; } return gradientPairs[gradientPairs.length - 1][1]; } const interpolator = interpolators[index]; const [value1] = gradientPairs[index]; const [value2] = gradientPairs[index + 1]; return interpolator((value - value1) / (value2 - value1)); }; };