itowns
Version:
A JS/WebGL framework for 3D geospatial data visualization
209 lines (188 loc) • 8.22 kB
JavaScript
/* global itowns */
/**
* This module can be added to a web page or in a web application. It provides a
* simple behavior where single files can be drag and dropped onto a viewer. No
* relationship between a type of file and the way it is read, parsed and
* displayed are stored in the plugin. Use the method `register` to declare the
* way a file is read, parsed and displayed.
*
* Note: only files with the projection `EPSG:4326` can be projected correctly
* using this plugin.
*
* @module DragNDrop
*
* @example
* <script src="js/DragNDrop.js"></script>
* <script type="text/javascript">
* var view = new itowns.GlobeView(document.getElementById('viewerDiv'));
*
* DragNDrop.setView(view);
* DragNDrop.register('geojson', DragNDrop.JSON, itowns.GeoJsonParser.parse, DragNDrop.COLOR);
* DragNDrop.register('gpx', DragNDrop.XML, itowns.GpxParser.parse, DragNDrop.GEOMETRY);
* </script>
*
* @example
* require('./js/itowns.js');
* require('./plugins/DragNDrop.js');
*
* const view = new itowns.GlobeView(document.getElementById('viewerDiv'));
*
* DragNDrop.setView(view);
* DragNDrop.register('geojson', DragNDrop.JSON, itowns.GeoJsonParser.parse, DragNDrop.COLOR);
* DragNDrop.register('gpx', DragNDrop.XML, itowns.GpxParser.parse, DragNDrop.GEOMETRY);
*/
var DragNDrop = (function _() {
// TYPE
var _TEXT = 1;
var _JSON = 2;
var _BINARY = 3;
var _IMAGE = 4;
var _XML = 5;
// MODE
var _COLOR = 6;
var _GEOMETRY = 7;
var extensionsMap = {};
var fileReader = new FileReader();
var _view;
function addFiles(event, files) {
event.preventDefault();
// Read each file
for (var i = 0; i < files.length; i++) {
var file = files[i];
var extension = extensionsMap[file.name.split('.').pop().toLowerCase()];
// eslint-disable-next-line no-loop-func
fileReader.onload = function onload(e) {
var data = e.target.result;
if (extension.type == _JSON) {
data = JSON.parse(data);
} else if (extension.type == _XML) {
data = new window.DOMParser().parseFromString(data, 'text/xml');
}
extension.parser(data, {
buildExtent: true,
crsIn: 'EPSG:4326',
crsOut: (extension.mode == _GEOMETRY ? _view.referenceCrs : _view.tileLayer.extent.crs),
mergeFeatures: true,
withNormal: (extension.mode == _GEOMETRY),
withAltitude: (extension.mode == _GEOMETRY),
}).then(function _(result) {
var dimensions = result.extent.dimensions();
var source = new itowns.FileSource({
parsedData: result,
projection: 'EPSG:4326',
});
var randomColor = Math.round(Math.random() * 0xffffff);
var layer;
if (extension.mode == _COLOR) {
layer = new itowns.ColorLayer(file.name, {
transparent: true,
style: {
fill: {
color: '#' + randomColor.toString(16),
opacity: 0.7,
},
stroke: {
color: '#' + randomColor.toString(16),
},
},
source: source,
});
} else if (extension.mode == _GEOMETRY) {
layer = new itowns.GeometryLayer(file.name, new itowns.THREE.Group(), {
update: itowns.FeatureProcessing.update,
convert: itowns.Feature2Mesh.convert({
color: new itowns.THREE.Color(randomColor),
// Set the extrusion according to the size of
// the extent containing the data; this quick
// formula is totally arbitrary.
extrude: dimensions.x * dimensions.y / 1e6,
}),
source: source,
opacity: 0.7,
});
} else {
throw new Error('Mode of file not supported, please add it using DragNDrop.register');
}
_view.addLayer(layer);
// Move the camera to the first vertex
itowns.CameraUtils.animateCameraToLookAtTarget(_view, _view.camera.camera3D, {
coord: new itowns.Coordinates(result.crs, result.features[0].vertices),
range: dimensions.x * dimensions.y * 1e6,
});
});
};
switch (extension.type) {
case _TEXT:
case _JSON:
case _XML:
fileReader.readAsText(file);
break;
case _BINARY:
fileReader.readAsArrayBuffer(file);
break;
case _IMAGE:
fileReader.readAsBinaryString(file);
break;
default:
throw new Error('Type of file not supported, please add it using DragNDrop.register');
}
}
}
// Listen to drag and drop actions
document.addEventListener('dragenter', function _(e) { e.preventDefault(); }, false);
document.addEventListener('dragover', function _(e) { e.preventDefault(); }, false);
document.addEventListener('dragleave', function _(e) { e.preventDefault(); }, false);
document.addEventListener('drop', function _(e) { addFiles(e, e.dataTransfer.files); }, false);
document.addEventListener('paste', function _(e) { addFiles(e, e.clipboardData.files); }, false);
return {
TEXT: _TEXT,
JSON: _JSON,
BINARY: _BINARY,
IMAGE: _IMAGE,
XML: _XML,
COLOR: _COLOR,
GEOMETRY: _GEOMETRY,
/**
* Register a type of file to read after a drag and drop on the viewer.
* The file will be processed following its extension and instructions
* given here.
*
* @param {string} extension - The extension to register. Each file
* dropped ending with this extension will follow the instructions given
* by the others parameters of this function.
* @param {number} type - The type of file to register. Can be
* `DragNDrop.TEXT` (equivalent to `Fetcher.text`), `DragNDrop.JSON`
* (equivalent to `Fetcher.json`), `DragNDrop.BINARY` (equivalent to
* `Fetcher.arrayBuffer`), `DragNDrop.IMAGE` (equivalent to
* `Fetcher.texture`) or `DragNDrop.XML` (equivalent to `Fetcher.xml`).
* @param {Function} parser - The method to parse the content of the
* added file.
* @param {number} mode - Choose the mode the file is displayed: either
* `DragNDrop.COLOR` (equivalent to a `ColorLayer`) or
* `DragNDrop.GEOMETRY` (equivalent to a `GeometryLayer`).
*
* @memberof module:DragNDrop
*/
register: function _(extension, type, parser, mode) {
extensionsMap[extension.toLowerCase()] = {
type: type,
parser: parser,
mode: mode,
};
},
/**
* The DragNDrop plugin needs to be binded to a view. Specified it using
* this method.
*
* @param {View} view - The view to bind to the DragNDrop interface.
*
* @memberof module:DragNDrop
*/
setView: function _(view) {
_view = view;
},
};
}());
if (typeof module != 'undefined' && module.exports) {
module.exports = DragNDrop;
}