Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Leaflet: an Open Source Success Story [Topconf 2013]

Leaflet: an Open Source Success Story [Topconf 2013]

Leaflet, a JavaScript library for mobile-friendly interactive maps, has come a long way since its inception. It started as a one-night hack, evolved over the next two years as a closed proprietary API, developed by one person, and then was finally rewritten from scratch as an open source library in 2011. Leaflet is now the most popular open source solution for publishing maps on the Web, used by the world's biggest companies, including Flickr, Foursquare, Vkontakte, IGN, Wikipedia, New York Times and the likes.

How did it became so successful despite strong competition and lack of funding? It's an amusing story of pursuing a dream, full of advice and inspiration for aspiring open source developers and anyone who is passionate about their product, told firsthand by Leaflet creator and lead developer.

Vladimir Agafonkin

November 07, 2013
Tweet

More Decks by Vladimir Agafonkin

Other Decks in Technology

Transcript

  1. February 2005 June 2006 June 2009 May 2011 Google Maps

    API OpenLayers Google Maps API v3
  2. mourner: hey guys, I was thinking of building a really

    simple, lightweight OpenLayers alternative for our API... #osmdev angry_guy: nobody gives a crap about your alternative, YOU IDIOT, just build a wrapper around OL like all others or FAIL miserably
  3. • 3 years of development • ~6900 lines of code

    • ~2700 commits from ~150 people • ~6200 stars, ~1100 forks • issues: ~160 open, ~2000 closed • pull requests: 32 open, ~750 closed
  4. number of features Images Markers Popups Vectors XYZ tiles GeoJSON

    WMS Layer groups Inertial pan Scroll zoom Dblclick zoom Box zoom Keyboard nav Pinch zoom Dbltap zoom Marker drag Pan anim Zoom anim Zoom buttons Attribution Layer switcher Scale Map rotation Fractional zoom WebGL renderer TMS WMTS TileCache MapGuide MapServer KaMap KaMapCache MultiMap Google Yahoo WorldWind Virtual Earth Bing Zoomify UTFGrid OSM ArcGIS ArcIMS GML GeoRSS KML WFS WFST ArcXML Atom CQL SLD GPX OSM XML OWS Context WKT XLS XML Drawing Editing Graticule Measure Pan control Minimap Permalink Clustering
  5. number of features Images Markers Popups Vectors XYZ tiles GeoJSON

    WMS Layer groups Inertial pan Scroll zoom Dblclick zoom Box zoom Keyboard nav Pinch zoom Dbltap zoom Marker drag Pan anim Zoom anim Zoom buttons Attribution Layer switcher Scale Map rotation Fractional zoom WebGL renderer TMS WMTS TileCache MapGuide MapServer KaMap KaMapCache MultiMap Google Yahoo WorldWind Virtual Earth Bing Zoomify UTFGrid OSM ArcGIS ArcIMS GML GeoRSS KML WFS WFST ArcXML Atom CQL SLD GPX OSM XML OWS Context WKT XLS XML Drawing Editing Graticule Measure Pan control Minimap Permalink Clustering
  6. quality of features Images Markers Popups Vectors XYZ tiles GeoJSON

    WMS Layer groups Inertial pan Scroll zoom Dblclick zoom Box zoom Keyboard nav Pinch zoom Dbltap zoom Marker drag Pan anim Zoom anim Zoom buttons Attribution Layer switcher Scale + third-party plugins
  7. var map = L.map('map') .setView([51.505, -0.09], 13); L.tileLayer( 'http://{s}.tile.osm.org/{z}/{x}/{y}.png') .addTo(map);

    L.marker([51.5, -0.09]) .addTo(map) .bindPopup('Hello World!') .openPopup(); API: as simple as possible
  8. function interPathHelper(path1, path2, justCount) {! path1 = R._path2curve(path1);! path2 =

    R._path2curve(path2);! var x1, y1, x2, y2, x1m, y1m, x2m, y2m, bez1, bez2,! res = justCount ? 0 : [];! for (var i = 0, ii = path1.length; i < ii; i++) {! var pi = path1[i];! if (pi[0] == "M") {! x1 = x1m = pi[1];! y1 = y1m = pi[2];! } else {! if (pi[0] == "C") {! bez1 = [x1, y1].concat(pi.slice(1));! x1 = bez1[6];! y1 = bez1[7];! } else {! bez1 = [x1, y1, x1, y1, x1m, y1m, x1m, y1m];! x1 = x1m;! y1 = y1m;! }! for (var j = 0, jj = path2.length; j < jj; j++) {! var pj = path2[j];! if (pj[0] == "M") {! x2 = x2m = pj[1];! y2 = y2m = pj[2];! } else {! if (pj[0] == "C") {! bez2 = [x2, y2].concat(pj.slice(1));! x2 = bez2[6];! y2 = bez2[7];! } else {! bez2 = [x2, y2, x2, y2, x2m, y2m, x2m, y2m];! x2 = x2m;! y2 = y2m;! }! var intr = interHelper(bez1, bez2, justCount);! if (justCount) {! res += intr;! } else {! for (var k = 0, kk = intr.length; k < kk; k++) {! intr[k].segment1 = i;! intr[k].segment2 = j;
  9. this code is so smart, I won't contribute — others

    would laugh at my lousy JS and I'd certainly break something „
  10. •get excited •build cool stuff •believe in yourself •pursue your

    dreams •push open source •listen to my band rain.in.ua Recap