A blog about web mapping.

Build a cross platform module for React and React Native

May 24, 2016 #js

For SpatialConnect, we need the ability to have unified interfaces across web and native. The stack we are using is React and React Native, written in ES6 with babel and webpack.

What we want is the ability to install one module in our React web app and our React Native iOS and Android apps and have that module display the correct component based on platform.

The solution we are currently using is webpack's resolve.alias and multiple outputs. The big advantage to this is it allows us to treat the web and native versions of a component as a single component within our module.

//src/index.js
import { componentA } from './components';

//do cool things with componentA, we don't care if it's a web or native component
//src/components/index.js
import componentA from 'componentA';
import componentB from 'componentB';

export default { componentA, componentB };
//webpack.web.js
module.exports = {
  entry: {
    './web/index': './src/index.js' //create web/index.js entry
  },
  resolve: {
    alias: {
      'componentA': './componentA.web', //the important part
      'componentB': './componentB.web',
    }
  },
  externals: {
    'react': 'react'
  },
  output: {
    library: 'crossplatformmodules',
    libraryTarget: 'umd',
    filename: '[name].js'
  },
  module: {
    loaders: [
      {
        test: /\.js?$/,
        exclude: /(node_modules)/,
        loader: 'babel'
      }
    ]
  }
};
//webpack.web.js
module.exports = {
  entry: {
    './native/index': '.src/index.js'
  },
  resolve: {
    alias: {
      'componentA': './componentA.native',
      'componentB': './componentB.native',
    }
  },
  externals: {
    'react-native': 'react-native'
  }...
//package.json
"main": "web/index.js",
"scripts": {
  "build": "npm run build-web && npm run build-native",
  "build-web": "webpack --config webpack.web.js",
  "build-native": "webpack --config webpack.native.js"
}
 

You can then import the default module in your web code, and the native version in your native app.

//web.app.js
import crossplatform from 'crossplatform';

//index.ios.js
import crossplatform from 'crossplatform/native';

Using React's FixedDataTable as an Attribute Table

Mar 15, 2016 #GIS #js #opensource

I just updated iso to React 0.14.7 after not being able to work on it for a few months. Turns out, React has changed a lot in that time, including FixedDataTable, a popular React component for making better tables.

It is perfect for something like an Attribute Table in GIS, because there are an unknown number of columns/rows when displaying random data. FixedDataTable supports a fixed header row to make scrolling easier, fixed columns (good for an index column in this application), and column resizing. It also adds nice hooks for row clicking, so we can update the data model to select features on click.

Check out the code in iso that created a FixedDataTable from GeoJSON here: https://github.com/frankrowe/iso/blob/gh-pages/src/components/AttributeTable.jsx.

A new take on some QGIS icons

Mar 04, 2016 #GIS #design

I took a shot at redesigning some QGIS icons, which I am using in the web-based map editor, iso.

I wanted it to be apparent that these buttons were for layer operations, so I added the recognizable three layer stack. I also brightened colors, removed gradients, and replace plus with an up arrow for importing layers. I felt the create new layer (*) and add new layer (+) were ambiguous in the old icons. An up arrow is more recognizable as upload/import.

npm-scripts > grunt

Mar 01, 2016 #js #css #dev

"scripts": {
  "watch-css": "onchange 'style/*.less' -- npm run build-css",
  "watch-js": "watchify -t [ babelify --presets [ es2015 react ] ] js/*.jsx js/*.js -o dist/bundle.js -dv",
  "watch": "npm run watch-css & npm run watch-js",
  "build-css": "lessc --autoprefix='last 2 versions' style/main.less dist/style.css",
  "build-js": "browserify -t [ babelify --presets [ es2015 react ] ] js/*.jsx js/*.js -o dist/bundle.js",
  "build": "npm run build-css && npm run build-js"
}

Reasons: simpler, less stuff to install, fewer files in your root, simpler, no plugins, same functionality, simpler.

Not only do you not need to install/maintain/update grunt, you don't need any of the grunt plugins. Instead of installing and updating grunt-browserify, grunt-less, etc, you just install the actual browserify package. You've just cut your dependencies in half.

Above is an example of what I use for a project with React, ES2015, and Less. I use browserify with a babelify transform to package my js + jsx modules, and watchify to do the same on file changes. I use less to compile css from my main.less file, from which I import all other less files. onchange enables us to watch for changes in your less files. You can then run npm run build to build your css/js, and npm run watch to recompile on changes during development.

npm-scripts has lots of nice built in scripts and pre and post hooks that you can take advantage of. Bottom line, it's better to take advantage of your already existing package.json than add an entire new dependency to your project.

location-bar: GPS coordinates in your menu bar

Feb 09, 2016 #os x #GIS #opensource

https://github.com/frankrowe/location-bar

Discovered BitBar today and thought it would be useful to display GPS coords in the menu bar. I use them a lot when testing lat/long pairs, plus it's neat to see when you're on the road.

You need to download an executable called whereami to get your location. It's open source and uses the OS X CoreLocation framework.

Once you have that in your home directory, just put this small script in your BitBar plugin directory, chmod +x it, and you're done.

Salisbury Police Daily Calls Map

Dec 07, 2015 #js #map #opendata #opensource

Full Screen Map: http://localityhq.com/sandbox/spdcallsmap/.

The Salisbury Police Department releases daily reports on all calls for service. The report is in PDF form and includes an address. I wrote a program to download and parse these PDF reports automatically. The map has a calendar to select daily calls, and a list of selectable call types to filter the map.

This doesn't represent all calls reported, as some addresses can't be geocoded. Check the source data for all calls.

The code for the map and automatic download/parse is open source here: https://github.com/frankrowe/spdcallsmap.

The PDF reports are parsed into raw GeoJSON files, available here: https://github.com/frankrowe/spdcallsmap/tree/master/data.

More 3D Touch Experiments: Drawing a Buffer

Oct 29, 2015 #js

Drawing a buffer area is always kind of a pain, you have to either selected a radius from some predefined options in a dropdown, or use drawing tools. With 3D Touch you can just press harder on the map to select a larger area.

Tracking Mary Lee

Oct 15, 2015 #js #map #opendata #opensource

Mary Lee is a 3,456 pound Great White that is tracked by the OCEARCH team, and often approaches the shores of my hometown Ocean City, MD.

You can view her route over the last three years on ocearch.org, but I wanted to see how she traveled that path, from one ping to the next.

It's also interesting to use Esri's World Ocean Base as a base map to see when she moves into shallow and deep waters, and travels along ocean ridges.

Mary Lee's pings are always available from OCEARCH via a somewhat hidden API.

The code to download, format, and display this data is open source.

3D Touch Map Zooming

Oct 12, 2015 #js

3D Touch is exposed to JavaScript on the iPhone 6s. I thought it would be cool to add to a map to enable easy one-handed zooming.

I put a quick example together that does this. If you have a 6s or 6s Plus, just press hard on the map to zoom in one level.

http://frankrowe.org/3dtouchtest/

Code

Also, this would be really cool if implemented in a vector tiles based map, like MapBox GL. Since there are no fixed "zoom levels" in a GL rendered map, you could tie the touch pressure and zoom more closely together. A light press zooming the map a very small amount, a hard press zooming farther, etc.