Files

190 lines
4.9 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 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 = {}) {
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) {
item = new MapStyleConstantItem(resolveImage(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) {
continue;
}
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;