UNPKG

4.4 kBPlain TextView Raw
1import styleSpec from '../style-spec/reference/latest';
2
3import {extend, sphericalToCartesian} from '../util/util';
4import {Evented} from '../util/evented';
5import {
6 validateStyle,
7 validateLight,
8 emitValidationErrors
9} from './validate_style';
10import Color from '../style-spec/util/color';
11import {number as interpolate} from '../style-spec/util/interpolate';
12
13import type {StylePropertySpecification} from '../style-spec/style-spec';
14import type EvaluationParameters from './evaluation_parameters';
15import type {StyleSetterOptions} from '../style/style';
16import {Properties, Transitionable, Transitioning, PossiblyEvaluated, DataConstantProperty} from './properties';
17
18import type {
19 Property,
20 PropertyValue,
21 TransitionParameters
22} from './properties';
23
24import type {LightSpecification} from '../style-spec/types.g';
25
26type LightPosition = {
27 x: number;
28 y: number;
29 z: number;
30};
31
32class LightPositionProperty implements Property<[number, number, number], LightPosition> {
33 specification: StylePropertySpecification;
34
35 constructor() {
36 this.specification = styleSpec.light.position as StylePropertySpecification;
37 }
38
39 possiblyEvaluate(
40 value: PropertyValue<[number, number, number], LightPosition>,
41 parameters: EvaluationParameters
42 ): LightPosition {
43 return sphericalToCartesian(value.expression.evaluate(parameters));
44 }
45
46 interpolate(a: LightPosition, b: LightPosition, t: number): LightPosition {
47 return {
48 x: interpolate(a.x, b.x, t),
49 y: interpolate(a.y, b.y, t),
50 z: interpolate(a.z, b.z, t),
51 };
52 }
53}
54
55type Props = {
56 'anchor': DataConstantProperty<'map' | 'viewport'>;
57 'position': LightPositionProperty;
58 'color': DataConstantProperty<Color>;
59 'intensity': DataConstantProperty<number>;
60};
61
62type PropsPossiblyEvaluated = {
63 'anchor': 'map' | 'viewport';
64 'position': LightPosition;
65 'color': Color;
66 'intensity': number;
67};
68
69const properties: Properties<Props> = new Properties({
70 'anchor': new DataConstantProperty(styleSpec.light.anchor as StylePropertySpecification),
71 'position': new LightPositionProperty(),
72 'color': new DataConstantProperty(styleSpec.light.color as StylePropertySpecification),
73 'intensity': new DataConstantProperty(styleSpec.light.intensity as StylePropertySpecification),
74});
75
76const TRANSITION_SUFFIX = '-transition';
77
78/*
79 * Represents the light used to light extruded features.
80 */
81class Light extends Evented {
82 _transitionable: Transitionable<Props>;
83 _transitioning: Transitioning<Props>;
84 properties: PossiblyEvaluated<Props, PropsPossiblyEvaluated>;
85
86 constructor(lightOptions?: LightSpecification) {
87 super();
88 this._transitionable = new Transitionable(properties);
89 this.setLight(lightOptions);
90 this._transitioning = this._transitionable.untransitioned();
91 }
92
93 getLight() {
94 return this._transitionable.serialize();
95 }
96
97 setLight(light?: LightSpecification, options: StyleSetterOptions = {}) {
98 if (this._validate(validateLight, light, options)) {
99 return;
100 }
101
102 for (const name in light) {
103 const value = light[name];
104 if (name.endsWith(TRANSITION_SUFFIX)) {
105 this._transitionable.setTransition(name.slice(0, -TRANSITION_SUFFIX.length) as keyof Props, value);
106 } else {
107 this._transitionable.setValue(name as keyof Props, value);
108 }
109 }
110 }
111
112 updateTransitions(parameters: TransitionParameters) {
113 this._transitioning = this._transitionable.transitioned(parameters, this._transitioning);
114 }
115
116 hasTransition() {
117 return this._transitioning.hasTransition();
118 }
119
120 recalculate(parameters: EvaluationParameters) {
121 this.properties = this._transitioning.possiblyEvaluate(parameters);
122 }
123
124 _validate(validate: Function, value: unknown, options?: {
125 validate?: boolean;
126 }) {
127 if (options && options.validate === false) {
128 return false;
129 }
130
131 return emitValidationErrors(this, validate.call(validateStyle, extend({
132 value,
133 // Workaround for https://github.com/mapbox/mapbox-gl-js/issues/2407
134 style: {glyphs: true, sprite: true},
135 styleSpec
136 })));
137 }
138}
139
140export default Light;