1 | 'use strict';
|
2 |
|
3 | import { hsvToColor, RGBtoHSV, rgbaColor, processColor, red, green, blue, opacity } from "./Colors.js";
|
4 | import { makeMutable } from "./core.js";
|
5 | import { Extrapolation, interpolate } from "./interpolation.js";
|
6 | import { useSharedValue } from "./hook/useSharedValue.js";
|
7 | import { ReanimatedError } from "./errors.js";
|
8 |
|
9 |
|
10 | export const Extrapolate = Extrapolation;
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 | const interpolateColorsHSV = (value, inputRange, colors, options) => {
|
21 | 'worklet';
|
22 |
|
23 | let h = 0;
|
24 | const {
|
25 | useCorrectedHSVInterpolation = true
|
26 | } = options;
|
27 | if (useCorrectedHSVInterpolation) {
|
28 |
|
29 |
|
30 |
|
31 |
|
32 | const correctedInputRange = [inputRange[0]];
|
33 | const originalH = colors.h;
|
34 | const correctedH = [originalH[0]];
|
35 | for (let i = 1; i < originalH.length; ++i) {
|
36 | const d = originalH[i] - originalH[i - 1];
|
37 | if (originalH[i] > originalH[i - 1] && d > 0.5) {
|
38 | correctedInputRange.push(inputRange[i]);
|
39 | correctedInputRange.push(inputRange[i] + 0.00001);
|
40 | correctedH.push(originalH[i] - 1);
|
41 | correctedH.push(originalH[i]);
|
42 | } else if (originalH[i] < originalH[i - 1] && d < -0.5) {
|
43 | correctedInputRange.push(inputRange[i]);
|
44 | correctedInputRange.push(inputRange[i] + 0.00001);
|
45 | correctedH.push(originalH[i] + 1);
|
46 | correctedH.push(originalH[i]);
|
47 | } else {
|
48 | correctedInputRange.push(inputRange[i]);
|
49 | correctedH.push(originalH[i]);
|
50 | }
|
51 | }
|
52 | h = (interpolate(value, correctedInputRange, correctedH, Extrapolation.CLAMP) + 1) % 1;
|
53 | } else {
|
54 | h = interpolate(value, inputRange, colors.h, Extrapolation.CLAMP);
|
55 | }
|
56 | const s = interpolate(value, inputRange, colors.s, Extrapolation.CLAMP);
|
57 | const v = interpolate(value, inputRange, colors.v, Extrapolation.CLAMP);
|
58 | const a = interpolate(value, inputRange, colors.a, Extrapolation.CLAMP);
|
59 | return hsvToColor(h, s, v, a);
|
60 | };
|
61 | const toLinearSpace = (x, gamma) => {
|
62 | 'worklet';
|
63 |
|
64 | return x.map(v => Math.pow(v / 255, gamma));
|
65 | };
|
66 | const toGammaSpace = (x, gamma) => {
|
67 | 'worklet';
|
68 |
|
69 | return Math.round(Math.pow(x, 1 / gamma) * 255);
|
70 | };
|
71 | const interpolateColorsRGB = (value, inputRange, colors, options) => {
|
72 | 'worklet';
|
73 |
|
74 | const {
|
75 | gamma = 2.2
|
76 | } = options;
|
77 | let {
|
78 | r: outputR,
|
79 | g: outputG,
|
80 | b: outputB
|
81 | } = colors;
|
82 | if (gamma !== 1) {
|
83 | outputR = toLinearSpace(outputR, gamma);
|
84 | outputG = toLinearSpace(outputG, gamma);
|
85 | outputB = toLinearSpace(outputB, gamma);
|
86 | }
|
87 | const r = interpolate(value, inputRange, outputR, Extrapolation.CLAMP);
|
88 | const g = interpolate(value, inputRange, outputG, Extrapolation.CLAMP);
|
89 | const b = interpolate(value, inputRange, outputB, Extrapolation.CLAMP);
|
90 | const a = interpolate(value, inputRange, colors.a, Extrapolation.CLAMP);
|
91 | if (gamma === 1) {
|
92 | return rgbaColor(r, g, b, a);
|
93 | }
|
94 | return rgbaColor(toGammaSpace(r, gamma), toGammaSpace(g, gamma), toGammaSpace(b, gamma), a);
|
95 | };
|
96 | const getInterpolateRGB = colors => {
|
97 | 'worklet';
|
98 |
|
99 | const r = [];
|
100 | const g = [];
|
101 | const b = [];
|
102 | const a = [];
|
103 | for (let i = 0; i < colors.length; ++i) {
|
104 | const color = colors[i];
|
105 | const processedColor = processColor(color);
|
106 |
|
107 | if (processedColor !== null && processedColor !== undefined) {
|
108 | r.push(red(processedColor));
|
109 | g.push(green(processedColor));
|
110 | b.push(blue(processedColor));
|
111 | a.push(opacity(processedColor));
|
112 | }
|
113 | }
|
114 | return {
|
115 | r,
|
116 | g,
|
117 | b,
|
118 | a
|
119 | };
|
120 | };
|
121 | const getInterpolateHSV = colors => {
|
122 | 'worklet';
|
123 |
|
124 | const h = [];
|
125 | const s = [];
|
126 | const v = [];
|
127 | const a = [];
|
128 | for (let i = 0; i < colors.length; ++i) {
|
129 | const color = colors[i];
|
130 | const processedColor = processColor(color);
|
131 | if (typeof processedColor === 'number') {
|
132 | const processedHSVColor = RGBtoHSV(red(processedColor), green(processedColor), blue(processedColor));
|
133 | h.push(processedHSVColor.h);
|
134 | s.push(processedHSVColor.s);
|
135 | v.push(processedHSVColor.v);
|
136 | a.push(opacity(processedColor));
|
137 | }
|
138 | }
|
139 | return {
|
140 | h,
|
141 | s,
|
142 | v,
|
143 | a
|
144 | };
|
145 | };
|
146 |
|
147 |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 | export function interpolateColor(value, inputRange, outputRange, colorSpace = 'RGB', options = {}) {
|
167 | 'worklet';
|
168 |
|
169 | if (colorSpace === 'HSV') {
|
170 | return interpolateColorsHSV(value, inputRange, getInterpolateHSV(outputRange), options);
|
171 | } else if (colorSpace === 'RGB') {
|
172 | return interpolateColorsRGB(value, inputRange, getInterpolateRGB(outputRange), options);
|
173 | }
|
174 | throw new ReanimatedError(`Invalid color space provided: ${colorSpace}. Supported values are: ['RGB', 'HSV'].`);
|
175 | }
|
176 | export let ColorSpace = function (ColorSpace) {
|
177 | ColorSpace[ColorSpace["RGB"] = 0] = "RGB";
|
178 | ColorSpace[ColorSpace["HSV"] = 1] = "HSV";
|
179 | return ColorSpace;
|
180 | }({});
|
181 | export function useInterpolateConfig(inputRange, outputRange, colorSpace = ColorSpace.RGB, options = {}) {
|
182 | return useSharedValue({
|
183 | inputRange,
|
184 | outputRange,
|
185 | colorSpace,
|
186 | cache: makeMutable(null),
|
187 | options
|
188 | });
|
189 | }
|
190 |
|
\ | No newline at end of file |