globe-ar
Version:
UI component for Globe Data Visualization in AR
706 lines (695 loc) • 20.5 kB
JavaScript
import 'aframe-globe-component';
import Kapsule from 'kapsule';
function _arrayLikeToArray(r, a) {
(null == a || a > r.length) && (a = r.length);
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
return n;
}
function _arrayWithHoles(r) {
if (Array.isArray(r)) return r;
}
function _arrayWithoutHoles(r) {
if (Array.isArray(r)) return _arrayLikeToArray(r);
}
function _defineProperty(e, r, t) {
return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
value: t,
enumerable: true,
configurable: true,
writable: true
}) : e[r] = t, e;
}
function _iterableToArray(r) {
if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
}
function _iterableToArrayLimit(r, l) {
var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
if (null != t) {
var e,
n,
i,
u,
a = [],
f = true,
o = false;
try {
if (i = (t = t.call(r)).next, 0 === l) ; else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
} catch (r) {
o = true, n = r;
} finally {
try {
if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
} finally {
if (o) throw n;
}
}
return a;
}
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function ownKeys(e, r) {
var t = Object.keys(e);
if (Object.getOwnPropertySymbols) {
var o = Object.getOwnPropertySymbols(e);
r && (o = o.filter(function (r) {
return Object.getOwnPropertyDescriptor(e, r).enumerable;
})), t.push.apply(t, o);
}
return t;
}
function _objectSpread2(e) {
for (var r = 1; r < arguments.length; r++) {
var t = null != arguments[r] ? arguments[r] : {};
r % 2 ? ownKeys(Object(t), true).forEach(function (r) {
_defineProperty(e, r, t[r]);
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
});
}
return e;
}
function _slicedToArray(r, e) {
return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
}
function _toConsumableArray(r) {
return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
}
function _toPrimitive(t, r) {
if ("object" != typeof t || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r);
if ("object" != typeof i) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == typeof i ? i : i + "";
}
function _unsupportedIterableToArray(r, a) {
if (r) {
if ("string" == typeof r) return _arrayLikeToArray(r, a);
var t = {}.toString.call(r).slice(8, -1);
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
}
}
//
var GLOBE_RADIUS = 100; // in GL units
var globeAr = Kapsule({
props: {
width: {},
height: {},
yOffset: {
"default": 1.5
},
// marker size units
globeScale: {
"default": 1
},
// globe radius units per marker width
onHover: {},
onClick: {},
globeImageUrl: {},
bumpImageUrl: {},
showGlobe: {
"default": true
},
showGraticules: {
"default": false
},
showAtmosphere: {
"default": true
},
atmosphereColor: {
"default": 'lightskyblue'
},
atmosphereAltitude: {
"default": 0.15
},
onGlobeReady: {},
pointsData: {
"default": []
},
pointLat: {
"default": 'lat'
},
pointLng: {
"default": 'lng'
},
pointColor: {
"default": function _default() {
return '#ffffaa';
}
},
pointAltitude: {
"default": 0.1
},
// in units of globe radius
pointRadius: {
"default": 0.25
},
// in deg
pointResolution: {
"default": 12
},
// how many slice segments in the cylinder's circumference
pointsMerge: {
"default": false
},
// boolean. Whether to merge all points into a single mesh for rendering performance
pointsTransitionDuration: {
"default": 1000
},
// ms
arcsData: {
"default": []
},
arcStartLat: {
"default": 'startLat'
},
arcStartLng: {
"default": 'startLng'
},
arcEndLat: {
"default": 'endLat'
},
arcEndLng: {
"default": 'endLng'
},
arcColor: {
"default": function _default() {
return '#ffffaa';
}
},
arcAltitude: {},
// in units of globe radius
arcAltitudeAutoScale: {
"default": 0.5
},
// scale altitude proportional to great-arc distance between the two points
arcStroke: {},
// in deg
arcCurveResolution: {
"default": 64
},
// how many straight segments in the curve
arcCircularResolution: {
"default": 6
},
// how many slice segments in the tube's circumference
arcDashLength: {
"default": 1
},
// in units of line length
arcDashGap: {
"default": 0
},
arcDashInitialGap: {
"default": 0
},
arcDashAnimateTime: {
"default": 0
},
// ms
arcsTransitionDuration: {
"default": 1000
},
// ms
polygonsData: {
"default": []
},
polygonGeoJsonGeometry: {
"default": 'geometry'
},
polygonSideColor: {
"default": function _default() {
return '#ffffaa';
}
},
polygonSideMaterial: {},
polygonCapColor: {
"default": function _default() {
return '#ffffaa';
}
},
polygonCapMaterial: {},
polygonStrokeColor: {},
polygonAltitude: {
"default": 0.01
},
// in units of globe radius
polygonCapCurvatureResolution: {
"default": 5
},
polygonsTransitionDuration: {
"default": 1000
},
// ms
pathsData: {
"default": []
},
pathPoints: {
"default": function _default(pnts) {
return pnts;
}
},
pathPointLat: {
"default": function _default(arr) {
return arr[0];
}
},
pathPointLng: {
"default": function _default(arr) {
return arr[1];
}
},
pathPointAlt: {
"default": 1e-3
},
pathResolution: {
"default": 2
},
// in deg
pathColor: {
"default": function _default() {
return '#ffffaa';
}
},
pathStroke: {},
// in deg
pathDashLength: {
"default": 1
},
// in units of line length
pathDashGap: {
"default": 0
},
pathDashInitialGap: {
"default": 0
},
pathDashAnimateTime: {
"default": 0
},
// ms
pathTransitionDuration: {
"default": 1000
},
// ms
heatmapsData: {
"default": []
},
heatmapPoints: {
"default": function _default(pnts) {
return pnts;
}
},
heatmapPointLat: {
"default": function _default(d) {
return d[0];
}
},
heatmapPointLng: {
"default": function _default(d) {
return d[1];
}
},
heatmapPointWeight: {
"default": 1
},
heatmapBandwidth: {
"default": 2.5
},
// Gaussian kernel bandwidth, in angular degrees
heatmapColorFn: {
"default": undefined
},
heatmapColorSaturation: {
"default": 1.5
},
// multiplier for color scale max
heatmapBaseAltitude: {
"default": 0.01
},
// in units of globe radius
heatmapTopAltitude: {},
// in units of globe radius
heatmapsTransitionDuration: {
"default": 0,
triggerUpdate: false
},
// ms
hexBinPointsData: {
"default": []
},
hexBinPointLat: {
"default": 'lat'
},
hexBinPointLng: {
"default": 'lng'
},
hexBinPointWeight: {
"default": 1
},
hexBinResolution: {
"default": 4
},
// 0-15. Level 0 partitions the earth in 122 (mostly) hexagonal cells. Each subsequent level sub-divides the previous in roughly 7 hexagons.
hexMargin: {
"default": 0.2
},
// in fraction of diameter
hexTopColor: {
"default": function _default() {
return '#ffffaa';
}
},
hexSideColor: {
"default": function _default() {
return '#ffffaa';
}
},
hexAltitude: {
"default": function _default(_ref) {
var sumWeight = _ref.sumWeight;
return sumWeight * 0.01;
}
},
// in units of globe radius
hexTopCurvatureResolution: {
"default": 5
},
hexBinMerge: {
"default": false
},
// boolean. Whether to merge all hex geometries into a single mesh for rendering performance
hexTransitionDuration: {
"default": 1000
},
// ms
hexPolygonsData: {
"default": []
},
hexPolygonGeoJsonGeometry: {
"default": 'geometry'
},
hexPolygonColor: {
"default": function _default() {
return '#ffffaa';
}
},
hexPolygonAltitude: {
"default": 0.001
},
// in units of globe radius
hexPolygonResolution: {
"default": 3
},
// 0-15. Level 0 partitions the earth in 122 (mostly) hexagonal cells. Each subsequent level sub-divides the previous in roughly 7 hexagons.
hexPolygonMargin: {
"default": 0.2
},
// in fraction of hex diameter
hexPolygonUseDots: {
"default": false
},
hexPolygonCurvatureResolution: {
"default": 5
},
hexPolygonDotResolution: {
"default": 12
},
hexPolygonsTransitionDuration: {
"default": 0
},
// ms
tilesData: {
"default": []
},
tileLat: {
"default": 'lat'
},
// tile centroid
tileLng: {
"default": 'lng'
},
tileAltitude: {
"default": 0.01
},
// in units of globe radius
tileWidth: {
"default": 1
},
// in lng degrees
tileHeight: {
"default": 1
},
// in lat degrees
tileUseGlobeProjection: {
"default": true
},
// whether to size tiles relative to the globe coordinate system, or independently
tileMaterial: {},
tileCurvatureResolution: {
"default": 5
},
// in angular degrees
tilesTransitionDuration: {
"default": 1000
},
// ms
particlesData: {
"default": []
},
particlesList: {
"default": function _default(d) {
return d;
}
},
// arrays of arrays
particleLat: {
"default": 'lat'
},
particleLng: {
"default": 'lng'
},
particleAltitude: {
"default": 0.01
},
// in units of globe radius
particlesSize: {
"default": 0.01
},
particlesSizeAttenuation: {
"default": true
},
particlesColor: {
"default": function _default() {
return 'white';
}
},
particlesTexture: {},
ringsData: {
"default": []
},
ringLat: {
"default": 'lat'
},
ringLng: {
"default": 'lng'
},
ringAltitude: {
"default": 1.5e-3
},
ringColor: {
"default": function _default() {
return '#ffffaa';
}
},
// single color, array of colors or color interpolation fn
ringResolution: {
"default": 64
},
// how many slice segments in each circle's circumference
ringMaxRadius: {
"default": 2
},
// degrees
ringPropagationSpeed: {
"default": 1
},
// degrees/s
ringRepeatPeriod: {
"default": 700
},
// ms
labelsData: {
"default": []
},
labelLat: {
"default": 'lat'
},
labelLng: {
"default": 'lng'
},
labelAltitude: {
"default": 0.002
},
// in units of globe radius
labelText: {
"default": 'text'
},
labelSize: {
"default": 0.5
},
// text height in deg
labelTypeFace: {},
labelColor: {
"default": function _default() {
return 'lightgrey';
}
},
labelRotation: {
"default": 0
},
// clockwise degrees, relative to the latitute parallel plane
labelResolution: {
"default": 3
},
// how many segments in the text's curves
labelIncludeDot: {
"default": true
},
labelDotRadius: {
"default": 0.1
},
// in deg
labelDotOrientation: {
"default": function _default() {
return 'bottom';
}
},
// right, top, bottom
labelsTransitionDuration: {
"default": 1000
},
// ms
objectsData: {
"default": []
},
objectLat: {
"default": 'lat'
},
objectLng: {
"default": 'lng'
},
objectAltitude: {
"default": 0.01
},
// in units of globe radius
objectRotation: {},
objectFacesSurface: {
"default": true
},
objectThreeObject: {},
customLayerData: {
"default": []
},
customThreeObject: {},
customThreeObjectUpdate: {}
},
methods: _objectSpread2(_objectSpread2({}, Object.assign.apply(Object, [{}].concat(_toConsumableArray(['globeMaterial', 'getGlobeRadius', 'getCoords', 'toGeoCoords'].map(function (method) {
return _defineProperty({}, method, function (state) {
var aframeComp = state.globe.components.globe;
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
var returnVal = aframeComp[method].apply(aframeComp, args);
return returnVal === aframeComp ? this // chain based on this object, not the inner aframe component
: returnVal;
});
}))))), {}, {
_destructor: function _destructor() {
this.pointsData([]);
this.arcsData([]);
this.polygonsData([]);
this.pathsData([]);
this.heatmapsData([]);
this.hexBinPointsData([]);
this.hexPolygonsData([]);
this.tilesData([]);
this.particlesData([]);
this.labelsData([]);
this.objectsData([]);
this.customLayerData([]);
}
}),
init: function init(domNode, state) {
var _ref3 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
_ref3$markerAttrs = _ref3.markerAttrs,
markerAttrs = _ref3$markerAttrs === void 0 ? {
preset: 'hiro'
} : _ref3$markerAttrs;
// Wipe DOM
domNode.innerHTML = '';
state.container = document.createElement('div');
domNode.appendChild(state.container);
// Create scene
var scene = document.createElement('a-scene');
scene.setAttribute('embedded', '');
scene.setAttribute('vr-mode-ui', 'enabled: false');
scene.setAttribute('arjs', 'debugUIEnabled: false;');
var arMarker = document.createElement('a-marker');
// add marker attributes
Object.entries(markerAttrs).forEach(function (_ref4) {
var _ref5 = _slicedToArray(_ref4, 2),
attr = _ref5[0],
val = _ref5[1];
return arMarker.setAttribute(attr, val);
});
scene.appendChild(arMarker);
// Setup raycaster cursor
var mouseCursor;
scene.appendChild(mouseCursor = document.createElement('a-entity'));
mouseCursor.setAttribute('cursor' /*, 'rayOrigin: mouse'*/); // mouse raycaster has accuracy issues in ar.js: https://github.com/AR-js-org/AR.js/issues/40
mouseCursor.setAttribute('raycaster', 'objects: [globe]; interval: 100');
// Add globe entity
state.globe = document.createElement('a-entity');
state.globe.setAttribute('globe', null);
arMarker.appendChild(state.globe);
var cameraEntity = document.createElement('a-entity');
cameraEntity.setAttribute('camera', '');
scene.appendChild(cameraEntity);
// attach scene
state.container.appendChild(scene);
//domNode.appendChild(scene);
},
update: function update(state, changedProps) {
changedProps.hasOwnProperty('width') && state.width && (state.container.style.width = "".concat(state.width, "px"));
changedProps.hasOwnProperty('height') && state.height && (state.container.style.height = "".concat(state.height, "px"));
changedProps.hasOwnProperty('globeScale') && state.globe.setAttribute('scale', _toConsumableArray(new Array(3)).map(function () {
return 1 / (state.globeScale * GLOBE_RADIUS);
}).join(' '));
changedProps.hasOwnProperty('yOffset') && state.globe.setAttribute('position', "0 ".concat(state.yOffset, " 0"));
var passThroughProps = ['onHover', 'onClick', 'globeImageUrl', 'bumpImageUrl', 'showGlobe', 'showGraticules', 'showAtmosphere', 'atmosphereColor', 'atmosphereAltitude', 'onGlobeReady', 'pointsData', 'pointLat', 'pointLng', 'pointColor', 'pointAltitude', 'pointRadius', 'pointResolution', 'pointsMerge', 'pointsTransitionDuration', 'arcsData', 'arcStartLat', 'arcStartLng', 'arcEndLat', 'arcEndLng', 'arcColor', 'arcAltitude', 'arcAltitudeAutoScale', 'arcStroke', 'arcCurveResolution', 'arcCircularResolution', 'arcDashLength', 'arcDashGap', 'arcDashInitialGap', 'arcDashAnimateTime', 'arcsTransitionDuration', 'polygonsData', 'polygonGeoJsonGeometry', 'polygonCapColor', 'polygonCapMaterial', 'polygonSideColor', 'polygonSideMaterial', 'polygonStrokeColor', 'polygonAltitude', 'polygonCapCurvatureResolution', 'polygonsTransitionDuration', 'pathsData', 'pathPoints', 'pathPointLat', 'pathPointLng', 'pathPointAlt', 'pathResolution', 'pathColor', 'pathStroke', 'pathDashLength', 'pathDashGap', 'pathDashInitialGap', 'pathDashAnimateTime', 'pathTransitionDuration', 'heatmapsData', 'heatmapPoints', 'heatmapPointLat', 'heatmapPointLng', 'heatmapPointWeight', 'heatmapBandwidth', 'heatmapColorFn', 'heatmapColorSaturation', 'heatmapBaseAltitude', 'heatmapTopAltitude', 'heatmapsTransitionDuration', 'hexBinPointsData', 'hexBinPointLat', 'hexBinPointLng', 'hexBinPointWeight', 'hexBinResolution', 'hexMargin', 'hexTopCurvatureResolution', 'hexTopColor', 'hexSideColor', 'hexAltitude', 'hexBinMerge', 'hexTransitionDuration', 'hexPolygonsData', 'hexPolygonGeoJsonGeometry', 'hexPolygonColor', 'hexPolygonAltitude', 'hexPolygonResolution', 'hexPolygonMargin', 'hexPolygonUseDots', 'hexPolygonCurvatureResolution', 'hexPolygonDotResolution', 'hexPolygonsTransitionDuration', 'tilesData', 'tileLat', 'tileLng', 'tileAltitude', 'tileWidth', 'tileHeight', 'tileUseGlobeProjection', 'tileMaterial', 'tileCurvatureResolution', 'tilesTransitionDuration', 'particlesData', 'particlesList', 'particleLat', 'particleLng', 'particleAltitude', 'particlesSize', 'particlesSizeAttenuation', 'particlesColor', 'particlesTexture', 'ringsData', 'ringLat', 'ringLng', 'ringAltitude', 'ringColor', 'ringResolution', 'ringMaxRadius', 'ringPropagationSpeed', 'ringRepeatPeriod', 'labelsData', 'labelLat', 'labelLng', 'labelAltitude', 'labelRotation', 'labelText', 'labelSize', 'labelTypeFace', 'labelColor', 'labelResolution', 'labelIncludeDot', 'labelDotRadius', 'labelDotOrientation', 'labelsTransitionDuration', 'objectsData', 'objectLat', 'objectLng', 'objectAltitude', 'objectRotation', 'objectFacesSurface', 'objectThreeObject', 'customLayerData', 'customThreeObject', 'customThreeObjectUpdate'];
var newProps = Object.assign.apply(Object, [{}].concat(_toConsumableArray(Object.entries(state).filter(function (_ref6) {
var _ref7 = _slicedToArray(_ref6, 2),
prop = _ref7[0],
val = _ref7[1];
return changedProps.hasOwnProperty(prop) && passThroughProps.indexOf(prop) !== -1 && val !== undefined && val !== null;
}).map(function (_ref8) {
var _ref9 = _slicedToArray(_ref8, 2),
key = _ref9[0],
val = _ref9[1];
return _defineProperty({}, key, val);
}))));
state.globe.setAttribute('globe', newProps);
}
});
export { globeAr as default };