@mapbox/react-native-mapbox-gl
Version:
A Mapbox GL react native module for creating custom maps
193 lines (158 loc) • 5.16 kB
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 (shouldMarkAsStyle) {
return {
type: this.type,
payload: this.payload,
__MAPBOX_STYLE__: shouldMarkAsStyle ? true : undefined,
};
}
}
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] }, false);
} else {
stops[stopKey] = makeStyleValue(prop, stopValue, null, false);
}
}
this.payload.stops = stops;
}
}
function resolveImage (imageURL) {
let resolved = imageURL;
if (typeof imageURL === 'number') { // required from JS, local file resolve it's asset filepath
const res = resolveAssetSource(imageURL);
// we found a local uri
if (res.uri) {
resolved = res.uri;
}
}
return resolved;
}
function makeStyleValue (prop, value, extras = {}, shouldMarkAsStyle = true) {
let item;
// search for any extras
const extraData = Object.assign({}, styleExtras[prop], extras);
if (MapboxStyleSheet.isFunctionStyleItem(value)) {
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) {
item = new MapStyleConstantItem(resolveImage(value), { image: true, ...extraData });
} else {
item = new MapStyleConstantItem(value, extraData);
}
return item.toJSON(shouldMarkAsStyle);
}
class MapboxStyleSheet {
static create (userStyles, depth = 0) {
const styleProps = Object.keys(userStyles);
let style = {};
for (let styleProp of styleProps) {
const userStyle = userStyles[styleProp];
if (MapboxStyleSheet.isStyleItem(userStyle)) {
style[styleProp] = userStyle;
continue;
}
if (!styleMap[styleProp] && depth === 0 && !isPrimitive(userStyle)) {
style[styleProp] = MapboxStyleSheet.create(userStyle, depth + 1);
continue;
} else if (!styleMap[styleProp] || isUndefined(userStyle) || userStyle === null) {
throw new Error(`Invalid Mapbox Style ${styleProp}`);
}
style[styleProp] = makeStyleValue(styleProp, userStyle);
}
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 isStyleItem (item) {
return typeof item === 'object' && item.__MAPBOX_STYLE__ === true;
}
static isFunctionStyleItem (item) {
if (item instanceof MapStyleFunctionItem) {
return true;
}
const isStyleItem = MapboxStyleSheet.isStyleItem(item);
return isStyleItem && item.type === StyleTypes.Function;
}
// helpers
static identity (attrName) {
return MapboxStyleSheet.source(null, attrName, MapboxGL.InterpolationMode.Identity);
}
}
export default MapboxStyleSheet;