Files
react-native-mapbox-gl/javascript/utils/MapboxStyleSheet.js
T
Nick 284fc4a0ab Fixes SymbolLayer textOffset and iconOffset on iOS
There seem to be some styles that will be special cases to the rules used from the json spec
this PR adds the ability to add overrides, so we can be flexible in special cases. In this case
we were using a NSArray for textOffset and iconOffset when it should be a CGVector.
2017-10-23 16:41:52 -07:00

176 lines
4.7 KiB
JavaScript

import { isUndefined, isPrimitive } from './index';
import { processColor, NativeModules } from 'react-native';
import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource';
import styleMap, { StyleTypes, StyleFunctionTypes, styleExtras } from './styleMap';
const MapboxGL = NativeModules.MGLModule;
class MapStyleItem {
constructor (type, payload) {
this.type = type;
this.payload = payload;
}
toJSON () {
return { type: this.type, payload: this.payload };
}
}
class MapStyleTransitionItem extends MapStyleItem {
constructor (duration = 0, delay = 0, extras = {}) {
super(StyleTypes.Transition, {
value: {
duration: duration,
delay: delay,
},
...extras,
});
}
}
class MapStyleTranslationItem extends MapStyleItem {
constructor (x, y, extras = {}) {
super(StyleTypes.Translation, {
value: [x, y],
...extras,
});
}
}
class MapStyleConstantItem extends MapStyleItem {
constructor (value, extras = {}) {
super(StyleTypes.Constant, { value: value, ...extras });
}
}
class MapStyleColorItem extends MapStyleItem {
constructor (value, extras = {}) {
super(StyleTypes.Color, { value: value, ...extras });
}
}
class MapStyleFunctionItem extends MapStyleItem {
constructor (fn, mode = MapboxGL.InterpolationMode.Exponential, payload) {
super(StyleTypes.Function, {
fn: fn,
mode: mode,
stops: payload.stops || {},
attributeName: payload.attributeName,
});
}
processStops (prop) {
let stops = {};
const stopKeys = Object.keys(this.payload.stops);
for (let stopKey of stopKeys) {
const stopValue = this.payload.stops[stopKey];
if (Array.isArray(stopValue)) {
stops[stopKey] = makeStyleValue(prop, stopValue[1], { propertyValue: stopValue[0] });
} else {
stops[stopKey] = makeStyleValue(prop, stopValue);
}
}
this.payload.stops = stops;
}
}
function makeStyleValue (prop, value, extras = {}) {
let item;
// search for any extras
const extraData = Object.assign({}, styleExtras[prop], extras);
if (!isUndefined(value.type) && !isUndefined(value.payload)) { // function
item = value;
item.processStops(prop);
} else if (styleMap[prop] === StyleTypes.Transition) {
item = new MapStyleTransitionItem(value.duration, value.delay, extraData);
} else if (styleMap[prop] === StyleTypes.Color) {
item = new MapStyleColorItem(processColor(value), extraData);
} else if (styleMap[prop] === StyleTypes.Translation) {
item = new MapStyleTranslationItem(value.x, value.y, extraData);
} else if (styleMap[prop] === StyleTypes.Image) {
const res = resolveAssetSource(value) || {};
item = new MapStyleConstantItem(res.uri || value, { image: true, ...extraData });
} else {
item = new MapStyleConstantItem(value, extraData);
}
return item.toJSON();
}
class MapboxStyleSheet {
static create (userStyles, depth = 0) {
if (MapboxStyleSheet.isStyleSheet(userStyles)) {
return userStyles;
}
const styleProps = Object.keys(userStyles);
let style = {};
for (let styleProp of styleProps) {
const userStyle = userStyles[styleProp];
if (!styleMap[styleProp] && depth === 0 && !isPrimitive(userStyle)) {
style[styleProp] = MapboxStyleSheet.create(userStyle, depth + 1);
continue;
} else if (!styleMap[styleProp] && (depth > 0 || isPrimitive(userStyle))) {
throw new Error(`Invalid Mapbox Style ${styleProp}`);
} else if (isUndefined(userStyle) || userStyle === null) {
throw new Error(`Invalid Mapbox Style ${styleProp} cannot be undefined/null`);
}
style[styleProp] = makeStyleValue(styleProp, userStyle);
}
style.__MAPBOX_STYLESHEET__ = true;
return style;
}
static camera (stops, mode) {
return new MapStyleFunctionItem(
StyleFunctionTypes.Camera,
mode: mode,
{ stops: stops },
);
}
static source (stops, attributeName, mode) {
return new MapStyleFunctionItem(
StyleFunctionTypes.Source,
mode: mode,
{ stops: stops, attributeName: attributeName },
);
}
static composite (stops, attributeName, mode) {
return new MapStyleFunctionItem(
StyleFunctionTypes.Composite,
mode: mode,
{ stops: stops, attributeName: attributeName },
);
}
static isStyleSheet (stylesheet) {
if (!stylesheet) {
return false;
}
return stylesheet.__MAPBOX_STYLESHEET__ || false;
}
static isStyleItem (item) {
return item instanceof MapStyleItem;
}
// helpers
static identity (attrName) {
return MapboxStyleSheet.source(null, attrName, MapboxGL.InterpolationMode.Identity);
}
}
export default MapboxStyleSheet;