UNPKG

tile-stencil

Version:

Load a MapLibre style document and parse it into Javascript functions

71 lines (53 loc) 2.08 kB
import { color, rgb } from "d3-color"; export function buildInterpolator(stops, base = 1) { if (!stops || stops.length < 2 || stops[0].length !== 2) return; // Confirm stops are all the same type, and convert colors to arrays const type = getType(stops[0][1]); if (!stops.every(s => getType(s[1]) === type)) return; stops = stops.map(([x, y]) => [x, convertIfColor(y)]); const izm = stops.length - 1; const scale = getScale(base); const interpolate = getInterpolator(type); return function(x) { const iz = stops.findIndex(stop => stop[0] > x); if (iz === 0) return stops[0][1]; // x is below first stop if (iz < 0) return stops[izm][1]; // x is above last stop const [x0, y0] = stops[iz - 1]; const [x1, y1] = stops[iz]; return interpolate(y0, scale(x0, x, x1), y1); }; } function getType(v) { return color(v) ? "color" : typeof v; } export function convertIfColor(val) { // Convert CSS color strings to clamped RGBA arrays for WebGL if (!color(val)) return val; const c = rgb(val); return [c.r / 255, c.g / 255, c.b / 255, c.opacity]; } function getScale(base) { // Return a function to find the relative position of x between a and b // Exponential scale follows mapbox-gl-js, style-spec/function/index.js // NOTE: https://github.com/mapbox/mapbox-gl-js/issues/2698 not addressed! const scale = (base === 1) ? (a, x, b) => (x - a) / (b - a) // Linear scale : (a, x, b) => (Math.pow(base, x - a) - 1) / (Math.pow(base, b - a) - 1); // Add check for zero range return (a, x, b) => (a === b) ? 0 : scale(a, x, b); } function getInterpolator(type) { // Return a function to find an interpolated value between end values v1, v2, // given relative position t between the two end positions switch (type) { case "number": // Linear interpolator return (v1, t, v2) => v1 + t * (v2 - v1); case "color": // Interpolate RGBA return (v1, t, v2) => v1.map((v, i) => v + t * (v2[i] - v)); default: // Assume step function return (v1) => v1; } }