UNPKG

mapbox-gl

Version:
145 lines (120 loc) 4.83 kB
const styleSpec = require('../style-spec/reference/latest'); const util = require('../util/util'); const Evented = require('../util/evented'); const validateStyle = require('./validate_style'); const StyleDeclaration = require('./style_declaration'); const StyleTransition = require('./style_transition'); const TRANSITION_SUFFIX = '-transition'; /* * Represents the light used to light extruded features. */ class Light extends Evented { constructor(lightOptions) { super(); this.properties = ['anchor', 'color', 'position', 'intensity']; this._specifications = styleSpec.light; this.set(lightOptions); } set(lightOpts) { if (this._validate(validateStyle.light, lightOpts)) return; this._declarations = {}; this._transitions = {}; this._transitionOptions = {}; this.calculated = {}; lightOpts = util.extend({ anchor: this._specifications.anchor.default, color: this._specifications.color.default, position: this._specifications.position.default, intensity: this._specifications.intensity.default }, lightOpts); for (const prop of this.properties) { this._declarations[prop] = new StyleDeclaration(this._specifications[prop], lightOpts[prop]); } return this; } getLight() { return { anchor: this.getLightProperty('anchor'), color: this.getLightProperty('color'), position: this.getLightProperty('position'), intensity: this.getLightProperty('intensity') }; } getLightProperty(property) { if (util.endsWith(property, TRANSITION_SUFFIX)) { return ( this._transitionOptions[property] ); } else { return ( this._declarations[property] && this._declarations[property].value ); } } getLightValue(property, globalProperties) { if (property === 'position') { const calculated = this._transitions[property].calculate(globalProperties), cartesian = util.sphericalToCartesian(calculated); return { x: cartesian[0], y: cartesian[1], z: cartesian[2] }; } return this._transitions[property].calculate(globalProperties); } setLight(options) { if (this._validate(validateStyle.light, options)) return; for (const key in options) { const value = options[key]; if (util.endsWith(key, TRANSITION_SUFFIX)) { this._transitionOptions[key] = value; } else if (value === null || value === undefined) { delete this._declarations[key]; } else { this._declarations[key] = new StyleDeclaration(this._specifications[key], value); } } } recalculate(zoom) { for (const property in this._declarations) { this.calculated[property] = this.getLightValue(property, {zoom: zoom}); } } _applyLightDeclaration(property, declaration, options, globalOptions, animationLoop) { const oldTransition = options.transition ? this._transitions[property] : undefined; const spec = this._specifications[property]; if (declaration === null || declaration === undefined) { declaration = new StyleDeclaration(spec, spec.default); } if (oldTransition && oldTransition.declaration.json === declaration.json) return; const transitionOptions = util.extend({ duration: 300, delay: 0 }, globalOptions, this.getLightProperty(property + TRANSITION_SUFFIX)); const newTransition = this._transitions[property] = new StyleTransition(spec, declaration, oldTransition, transitionOptions); if (!newTransition.instant()) { newTransition.loopID = animationLoop.set(newTransition.endTime - Date.now()); } if (oldTransition) { animationLoop.cancel(oldTransition.loopID); } } updateLightTransitions(options, globalOptions, animationLoop) { let property; for (property in this._declarations) { this._applyLightDeclaration(property, this._declarations[property], options, globalOptions, animationLoop); } } _validate(validate, value) { return validateStyle.emitErrors(this, validate.call(validateStyle, util.extend({ value: value, // Workaround for https://github.com/mapbox/mapbox-gl-js/issues/2407 style: {glyphs: true, sprite: true}, styleSpec: styleSpec }))); } } module.exports = Light;