Application Development With OpenLayers 3
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 95 | |
Author | ||
License | CC Attribution - NonCommercial - ShareAlike 3.0 Unported: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this | |
Identifiers | 10.5446/15511 (DOI) | |
Publisher | ||
Release Date | ||
Language | ||
Production Place | Nottingham |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
FOSS4G Nottingham 201311 / 95
17
25
29
31
32
34
48
50
56
58
68
69
70
82
89
91
00:00
Software developerCartesian coordinate systemLibrary (computing)Row (database)Control flowOpen setQuicksortDemo (music)BitCollaborationismTurtle graphicsWebsiteComputer animation
01:00
Coma BerenicesOpen setBitGeometrySoftware developerNumberChemical equationComputer animation
01:43
Multiplication signDemo (music)Product (business)BitQuicksortGraph (mathematics)Projective planeOpen setDrawing
02:05
Level (video gaming)Web pageView (database)VarianceZoom lensLevel (video gaming)CodeDemo (music)Web pageDefault (computer science)SphereZoom lensSoftware developerView (database)Cartesian coordinate systemLibrary (computing)TesselationMomentumConstructor (object-oriented programming)QuicksortObject (grammar)RotationOpen setConnected spaceComplex (psychology)Flow separationImage resolutionSelf-organizationCASE <Informatik>BitBuildingMatching (graph theory)CodeWhiteboardXML
04:14
Maxima and minimaConvex hullLevel (video gaming)View (database)Division (mathematics)IdentifiabilityElectronic mailing listString (computer science)Limit (category theory)Point (geometry)WhiteboardLibrary (computing)Default (computer science)MappingQuicksortOpen setZoom lensDrag (physics)Doubling the cubeGame controllerJSON
04:53
VarianceView (database)Level (video gaming)Zoom lensDifferent (Kate Ryan album)Source codeArmSummierbarkeitDiscrete element methodSpecial unitary groupVector spaceSource codeTesselationKey (cryptography)Configuration spaceBitFlow separationDifferent (Kate Ryan album)Multiplication signCASE <Informatik>Internet service providerCommunications protocolData storage deviceOrder (biology)Type theoryNumbering schemeMappingLevel (video gaming)View (database)JSON
06:37
Metropolitan area networkScalable Coherent InterfaceDiscrete element methodMaxima and minimaExecution unitAddressing modeField (computer science)SimulationMach's principleLevel (video gaming)Special unitary groupArtistic renderingTesselationInternet service providerStatement (computer science)Image resolutionMereologyDemosceneConnected spaceZoom lensOpen setLattice (group)BitInformationCommunications protocolCartesian coordinate systemMatrix (mathematics)Software developerConfiguration spaceSocial classLevel (video gaming)Source codeProcess (computing)MetadataCuboidWhiteboardCASE <Informatik>Structural load
09:01
BitLevel (video gaming)TesselationStructural loadDemosceneImage resolutionFree variables and bound variablesComputer iconService (economics)Computer animation
09:26
SummierbarkeitTesselationQueue (abstract data type)Focus (optics)Roundness (object)Image resolutionStandard deviationPhysical lawPhysical systemServer (computing)Client (computing)Level (video gaming)Electronic visual displayZoom lensRaster graphicsSource codeQuicksort
10:40
Source codeVarianceRing (mathematics)Drag (physics)RotationPersonal area networkKeyboard shortcutTouch typingZoom lensControl flowPosition operatorSource codeRaster graphicsBitKeyboard shortcutInteractive televisionZoom lensMultiplicationNumberRepresentation (politics)Touch typingComputer architectureDrag (physics)Level (video gaming)Game controllerScaling (geometry)Personal area networkContrast (vision)Key (cryptography)Group actionEvent horizonDifferent (Kate Ryan album)Software testingDivision (mathematics)Line (geometry)QuicksortElectronic visual displayForceDirection (geometry)Focus (optics)Default (computer science)SequenceJSONComputer animation
12:40
HTTP cookie1 (number)Game controllerDefault (computer science)Line (geometry)Scaling (geometry)Touch typing
13:02
EmailSummierbarkeitPhysical lawArithmetic meanMetropolitan area networkScaling (geometry)Image resolutionLine (geometry)Multiplication signMatching (graph theory)Zoom lensLevel (video gaming)Game controllerCASE <Informatik>MathematicsComputer animation
13:31
Artificial neural networkQuantumArmVarianceMultiplication signGame controllerDefault (computer science)BitUniform resource locatorNumber
13:54
SummierbarkeitMaxima and minimaEmulationConditional-access moduleUniform resource nameMetropolitan area networkRotationWeb browserRange (statistics)Shift operatorInteractive televisionoutputType theoryMathematicsLevel (video gaming)Drag (physics)HypothesisRight anglePhysical systemSelectivity (electronic)Direction (geometry)Force
14:53
Maxima and minimaEmulationRothe-VerfahrenComa BerenicesE-learningWide area networkMetropolitan area networkPersonal area networkWindowLevel (video gaming)Element (mathematics)Keyboard shortcutQuicksortDefault (computer science)outputTouchscreenRotationDrag (physics)Library (computing)View (database)Game controllerCartesian coordinate systemRow (database)Multiplication signExtension (kinesiology)Group actionMatching (graph theory)Cache (computing)
15:41
Control flowZoom lensPosition operatorVector spaceSource codeVarianceUniform resource locatorParsingComputer fileVariety (linguistics)Term (mathematics)Vector spacePosition operatorParity (mathematics)Multiplication signSource codeLibrary (computing)File formatRaster graphicsFocus (optics)Open setTesselationJSONXML
16:48
CAN busExecution unitUniform resource nameInformation managementReading (process)RAIDArtistic renderingVector space
17:11
Special unitary groupRankingArmValue-added networkUniform resource namePointer (computer programming)TesselationRing (mathematics)VolumenvisualisierungCache (computing)Vector spaceGroup action
17:30
Uniform resource nameDrum memoryMetropolitan area networkSource codeVector spaceVarianceUniform resource locatorParsingGenetic programmingClique-widthRule of inferenceDigital filterStrategy gameMathematicsGroup actionImage resolutionSymbol tableDifferent (Kate Ryan album)Rule of inferenceQuicksortSet (mathematics)Point (geometry)Computer fontDeclarative programmingInteractive televisionVolumenvisualisierungExpressionLine (geometry)PixelPolygonCivil engineeringService (economics)WhiteboardGenetic programmingJSON
19:15
Maxima and minimaCountingWide area networkArmSubject indexingCASE <Informatik>Category of beingPixelView (database)Service (economics)Genetic programmingTerm (mathematics)Variety (linguistics)Overlay-NetzSet (mathematics)SurfaceLine (geometry)Attribute grammar
20:15
Level (video gaming)VarianceOverlay-NetzElement (mathematics)Social classInformation managementMetropolitan area networkPosition operatorPlug-in (computing)Social classUniform resource locatorLevel (video gaming)Bootstrap aggregatingMappingInteractive televisionMultiplication sign
21:06
Level (video gaming)VarianceOverlay-NetzElement (mathematics)Social classPoint (geometry)Interactive televisionClient (computing)Vector spaceCASE <Informatik>Point (geometry)BitIdentifiabilityFunctional (mathematics)QuicksortMassDependent and independent variablesGroup actionComputer animation
21:53
Metropolitan area networkPoint (geometry)VarianceFunction (mathematics)Vector spaceZoom lensPoint (geometry)Interactive televisionGame controllerBranch (computer science)IterationGroup actionJSONXMLUML
22:29
Uniform resource nameGame theoryComputer wormTwin primeInformation managementClient (computing)State of matterInteractive televisionDoubling the cubeGroup action
22:48
Drum memorySpecial unitary groupUniform resource nameSinePoint (geometry)QuicksortVector spaceNetwork topologyVertex (graph theory)Rule of inferenceNumberShift operatorDifferent (Kate Ryan album)PolygonInteractive televisionFunctional (mathematics)Data structureVideo gameBuildingGroup actionDistanceDrag (physics)
24:20
Library (computing)Repository (publishing)Self-organizationCodeWebsiteEmailComputer animation
24:46
SpacetimeSlide ruleUniform resource locatorWebsiteMultiplication sign
Transcript: English(auto-generated)
00:00
All right. Thanks everybody for coming. I appreciate the opportunity to talk here at the conference. I hope some people caught Eric's session earlier. We've got a bit of a triathlon or a quadrathlon of open layers talks going on. Eric spoke just before the break and gave a really good introduction to open layers. I'm talking now and I'm going to basically just
00:23
give you a lot of demos of what the library can do and show you what the API looks like. And following me, Tom will talk about some of the internals and give you a look under the hood of open layers. And finally Cedric will follow up and discuss a little bit about how we launched this fundraising campaign and how that really
00:41
helped us tackle this development effort. So I previously had titled my talk Application Development with Open Layers. It's now called Working with Open Layers. We've sort of reshuffled to accommodate having these four talks in a row. There's going to be some redundant material for those that were here at Eric's talk, but I hope it's not too much overlap.
01:02
I work for Boundless Geo. This is formerly Open Geo. And I just wanted to thank my employer for allowing me to participate in open layers development for the past six years. The open layers three development effort has really been a collaborative effort. And I'll leave you to come to Cedric's talk
01:22
to hear a little bit more about that. But it's mainly, it's an effort that we fundraised for and we have developers participating from a number of companies, primarily Camp2Camp and Boundless, also Terrestris. And we encourage developers from all different places.
01:42
So I typically start open layers talks with a bit on the history of open layers. And I find myself actually going pretty long and talking about how we've been around for seven years and I show graphs of how the project has grown and how we've brought on new contributors and added new features. And I always find myself too short
02:01
at the end on time for showing demos. So I wanted to sort of flip that around and say, okay, forget the history, let's dispense with that and go straight to the demos. And I don't mean that we're forgetting about our history or I don't think that's important. It actually is very significant that we have taken seven years of experience with working with open layers
02:21
too and though we have thrown away all the code and started over, we've really learned a lot from that experience and embedded that knowledge in the development of this new library. So it's a bit of a risk, I think to have an entirely demo driven talk, but it seems like the connection is working out and kudos to the conference organizers
02:42
for making that possible. The way I'll drive this is just by setting up a simple goal. So we'll look at an objective, pretending you're sitting down to develop an application is something you might wanna do, just put a simple map on a page. Then I'm gonna show you what it looks like in open layers code. So this is your first introduction
03:00
to the open layers three API. One thing to notice is we have this separation of a map and a view. A map is the primary object that you interact with when working with an open layers application. But it's very important to know about the view. This example shows the construction of a 2D view. And all the examples I'll show you use that same view.
03:23
We've designed open layers to be able to, open layers three to be able to accommodate different views. So we will have a 3D view eventually. And a lot of the initial impetus for developing open layers three was to be able to provide 3D views, to be able to provide kind of limited two and a half D
03:40
views, oblique views with extruded buildings or extruded terrain, but also potentially to deal with more complex 3D views. So in this example, I've given a view center. It's just an array of values, two values in this case and a zoom. A view in general takes resolution
04:00
and rotation values as well. And zoom is sort of a shorthand convenience for indicating which resolution, assuming the default tile levels for a spherical Mercator tile set. Then I construct a map and I point it to some viewport in the DOM. This map string is the identifier
04:22
of a div element, let's say in the DOM. And I give it a list of layers and I give it that view. And let's see what that looks like. So there we have your basic hello world from open layers. I can double click to zoom in here, drag to pan.
04:42
I've got the expected sort of default controls, a zoom button here to do the same thing. So pretty basic, something you'd expect to accomplish with any mapping library. And that's how we do it in open layers three. So moving on from there, the next thing you want is to use different sources. That example I showed you used an OSM data source
05:04
and that I didn't show how it was created in that previous example, but this is how you would do that. You'd use a tile layer and then you give that layer a source. So again, this is an example of the separation of concerns. Eric mentioned in the previous talk, and I think Tom will be giving
05:21
a little bit more justification for in his talk. But my quick explanation of it is that a layer represents the view, how you want the data source to be rendered in the map. And the source represents how to fetch that data. So I'll be talking in a few examples about vector data.
05:42
In these examples, it's using tiled raster data. So this source knows about the URL for those tiles, the URL scheme, it knows how to get them. And those tiles might come from different tile providers, it could come from local storage, or you could be using an entirely different protocol,
06:01
not HTTP to gather those tiles. But that's what the source does. You can use that same layer. So this is again using the tile layer, but in this case, it's using a Bing Maps source. So the OSM source doesn't take any special configuration. This Bing Maps source requires that you provide a key,
06:20
you go register for an API key for Bing Maps, and then you have to choose which style. And here's the aerial imagery layer with labels. So I'll show an example demonstrating a couple of different tile sources. In the first example, we saw OSM. Here's MapQuest rendering of OSM, Bing's aerials.
06:45
You can use tiles from other providers. Stamen is a nice design company that provides nice tiles available for use. People probably know of Mapbox, this is their geography class layer. This is a tile JSON layer. So it uses this tile JSON protocol,
07:03
kind of community protocol to go out and fetch information about the metadata, the origin of the tiles and what the tile lattice is, and then it configures the source for you. So this is an interesting example. It's actually something that was a bit awkward in Open Layers 2 to do, but these sources can be asynchronously configured.
07:22
So in this case, the application developer doesn't know everything about the configuration of this tile grid or the tile matrix set, but you just specify how you can get that information. This source goes out, fetches the capabilities, and then it configures that source. And when it's available, it will be rendered in your map.
07:41
So a lot going on behind the scenes there, but the important part for you is it's just easy to use. And of course, you can just use any general XYZ layers. So I wanna play around with the map and show off a couple other features here. I already showed you this animated zooming. When I click, I shouldn't be centering in my home over here.
08:01
You guys helped me find where we are now. One thing that you should be able to see, as I zoom in, we have, pardon? Oh, okay. I'd rather just fly around the map and not really care where I end up, I guess, but so I'm gonna zoom in here,
08:22
and because of the latency here, you can watch the tiles load. I've given talks and tried to demonstrate this before, and then you have a very fast connection. Of course, you can't see that it's not as pronounced, but it does demonstrate something that I wanna show you. So I've zoomed in here over Birmingham,
08:42
and now I'm gonna pan over to the side. And you can see, instead of going off the map and seeing what's beyond the edge of the world, you see these lower resolution tiles. And then, as I sit and wait, the tiles at my target resolution are loaded. So this provides a really nice effect,
09:01
particularly with imagery. So I will push this map out a little bit and look at tiles that are, I've probably already got lower, or loaded. But you can see, as I pan over here, I get these lower resolution tiles that are shown sort of as a placeholder, and then the tiles at the appropriate resolution come in. And there's some really sophisticated tile handling
09:22
going on behind the scenes here as well. There's a tile queue that determines the priority of the tiles that are fetched. And it is prioritized around the focus of my mouse. So as I zoom in to this location, tiles where my mouse is over on that side
09:41
will be prioritized. So those will be loaded first, and then these other tiles come in after that. So some really nice tile handling. I hope I haven't stolen too much of Tom's thunder. It's largely kudos to him, but I think that's really great. And it provides a really nice experience for the user. I also, I'm not gonna demonstrate it in this example,
10:02
but it's important to note as well that we're using these standard resolutions, standard zoom levels for these XYZ tiles that are available here. But OpenLayers 3 has the capability to fetch tiles at a resolution that is available on the server, and then display them at any resolution on the client.
10:20
And that's sort of what you're seeing when you're seeing these lower resolution tiles displayed in the background. But you don't have to just restrict your map to the standard zoom levels that are available on your server. You can zoom to any resolution, and we will scale those raster data sources at the display that you've chosen on the client.
10:42
So that's a little bit about layers and sources, working with raster sources in particular. In the previous examples, I've talked about some of the interaction that you wanna do, and shown the controls that are on the map. You might want to provide more control to your user
11:01
than we provide by default. So it's important to know about these two concepts, the interaction and control. In OpenLayers 3, interactions are things that have no visible representation or no representation in the DOM. And they literally just take browser events and compose them into higher level events,
11:21
or take some action and let's say move your map. So the drag interaction is just a very basic thing that takes browser events and composes them into a drag sequence, drag start, drag, drag end. And that can be used to do things like drag rotate the map. I'll show you that in a second. You've seen drag panning as I go through.
11:41
There are also touch related interactions. So touch zoom works on mobile devices, and then keyboard interactions that can make your map accessible. So you can allow the user to focus your map with a tab key or something, and then use the keyboard to interact with the map.
12:00
Controls by contrast are things that do have a representation in the DOM. So the zoom control provides those buttons where I was zooming in and out on the map. The scale line control, I'll show you in just a second, displays a scale line on your map, et cetera. So we're trying to maintain that distinction and we're sort of testing this division
12:20
in the architecture as we go. Maybe that we have, and our idea is to have interactions that are reusable. So you can have a control that orchestrates a number of different interactions and turns them on and off and takes advantage, reuses these interactions in multiple controls. So this example has a couple non-default controls built in.
12:46
The first example I showed you, I didn't touch controls when I created a map. In this example, I have extended the default controls with custom ones. So the one up here in the top is this scale line control. If you've got really good eyes and watch that,
13:00
you should see, as I zoom in and out, that scale line is animated with the resolution on the map. So it's showing the resolution at the center of the map at all times. If I zoom way out here, you should see that even as I change the center, the scale line changes
13:21
because we're changing resolution as we go further north in that case. So that's the scale line control. I mentioned the zoom controls. Those let you zoom in and out. Another control that we have included but that is not enabled by default
13:41
is this geolocation control. So I'm gonna see if I can locate ourselves here. And that gets our location and bounces in. I'm gonna zoom in a bit further here, see if it was close. At least I saw Nottingham there.
14:01
Anybody start recognizing campus? All right, so I can explore around here, hit locate again and see if it takes us down. Seems like it did find us accurately. So one thing I mentioned but haven't shown yet is this rotation, drag rotation interaction.
14:21
So I'm going to Alt Shift drag and I can rotate the map around the center. If you're looking carefully up at the far top right, you can see a little slider there that changes as I rotate the map around. And this is an HTML5 has added the range type input.
14:43
So this is just an input that takes a value, a rotation value. And if you provide this range type, supported browsers will actually show you a little slider like this. And what I'm showing you here is this two way binding between that input element and the map view rotation.
15:02
So as I move this slider, the map rotates. As I move, as I rotate the map with the drag rotation interaction, the slider moves. And the library allows you to do that sort of two way binding with things like input elements or other elements in your application.
15:21
I'm already in full screen, but if you weren't in full screen, we provide a full screen control that expands your map to full screen. It's really a nice immersive experience. And so those are some custom controls
15:41
that you can add to and extend the defaults with. Okay, next goal might be to work with vector data. All I've shown you so far is working with raster data with raster tiles, but a big focus in open layers three is working efficiently with vector layers. So previously I was showing you tile layers
16:02
and tile sources. In this example, it's a vector layer. We're using the base vector source. And here I've just given it the URL path to my data. And I've told it this is gonna be GeoJSON. We currently have support for GeoJSON, TopoJSON, GML, KML, GPX, vector data sources.
16:24
Did I miss any? And we're expanding that list. So we plan to have feature parity with open layers two in terms of the wide variety of formats supported there. And again, those allow you to use the same, this source describes where the data is coming from. And then I tell it what format it's in
16:41
and the library will parse it for you, transform coordinates on the fly, and then render those. So looking at the vector layer example, here is just a country's data set. As I zoom in here, you can see labels coming in. One thing I wanna mention about the vector rendering,
17:02
this isn't, you can see it's pretty low quality data here but one of the things that's worked into the vector render right now is this internal tiled rendering. So while you're animating, while I'm zooming in and out or doing this animated pan, I'm not actually going back to the data and re-rendering with every move.
17:23
I'm using cached vector tiles from the previous render and using those to display while we're in this animated transition between resolutions. It may be that we changed the strategy for this, we're experimenting with strategies that are gonna be the most efficient for rendering large amounts of data
17:42
and still providing really nice interactivity. So that was a pretty boring example, didn't have much style, just white polygons with blue outlines. The next thing you might wanna do is give your layers some style. So the style handling in OpenLayers 3 is pretty sophisticated. We intend on making it as convenient as possible.
18:03
This example shows creating a style with two symbolizers. So this is a fill symbolizer and a stroke symbolizer and if you give it polygon data, that will render your polygons with a fill and stroke. If you were to give that line data, it would just stroke them and if you were to give it point data,
18:21
that wouldn't render them at this point. I can talk to people afterwards about how to render point data, I don't have an example of that. So that was just saying render all my data in the same way. Typically what you want to do is provide some sort of selector, some filter. I wanna render this portion of my data in one way and the rest of my data in another way.
18:41
So in CSS, these are selectors and then your style declaration. In OpenLayers, we have rules. So rules have a filter which represents your selector. In this case, I'm saying I just want the highways to be rendered with this symbolizer. So a three pixel stroke for the highways and then it could provide another set of symbolizers,
19:03
it would say and the rest of my data render them with a different set of symbolizers. So you can stack these rules in here and use these filter expressions to determine which features are selected in rendering your data. So I grabbed a simple, this is a New York streets data set
19:22
and rendered these. I couldn't differentiate that. The data didn't have much variety in terms of attribute values, but there's a highway here running through Manhattan and then these surface roads are shown in yellow. If you're looking closely, you can see that these roads are cased. So there are two symbolizers. There's like an eight pixel wide stroke
19:41
and then a six pixel wide stroke over it. We intend to provide really robust control for Z index support. Right now, you can see I have this one example of a road going under, another example of a road going over. In some cases, the line cases don't overlay properly,
20:01
but we wanna give you that control so that you can say, I want the wider stroke to be underneath all, let's say have a lower Z index value and the narrower stroke to have a higher Z index value. So next goal would be to let users interact with data.
20:21
This is an example of just using an overlay. There's not gonna be any real data here. I've got to really speed up because I'm out of time, but this is just an example showing bootstrap popovers to add to your map. So I'm clicking on the map and I'm showing the location
20:40
where I clicked in this popover. OpenLayers doesn't provide a pop-up class itself, but if you're using something like bootstrap that does provide this jQuery plugin for popovers, you can use that. And what we do for you is anchor that at the location that you set. So as I rotate around here, I can see that pop-up stays in position.
21:02
As I zoom in and animate, it moves smoothly with the map. Okay, that was just really interaction with my location. Really, you want to typically interact with the data. In this case, I'm interacting with vector data that I have rendered on the client. This is sort of a nauseating example to look at,
21:22
but that's intentional. The idea is to show you that we can, our goal is to efficiently render far more features than you actually want to show people. So here are 20,000 points and they rendered quickly as you saw. And as I'm mousing over, I'm showing you the feature identifiers for those points. So you should get the impression that this is a very responsive,
21:42
one nice bit of functionality here too. My mouse is hovering over one, two, three, four, five, six, seven, eight features. And I get the feature identifiers for all of those back. So it's not just about the features on the top there. As I zoom in, you can see that I get nice animated zooming still with those 20,000 points
22:01
and they're rendered efficiently. So final goal I'd like to show is just to allow editing. And this is very experimental work at this point or unstable work, I should say, not necessarily unstable or experimental, but we have these two interactions that are in a branch right now being worked on, the select interaction and the modify interaction.
22:22
And these interactions will be composed in an editing control. And I'll just show you some of the behavior that those might have. So I'm looking at a state's layer rendered on the client here and I'm gonna zoom in
22:42
and show you what the select interaction looks like. So I'm clicking, I'm gonna double click there, clicking to select the layer that's shown in a different style. As I hover close to the layer,
23:00
you can see this point that should show up as I get close to vertices in this vector data. And then I can just drag those. So this is pretty basic vector editing functionality. You can see that I'm destroying the topology in my data when I'm doing this sort of editing.
23:20
So what we wanna be able to provide is the ability to maintain this topology without you having loaded a topological data structure or providing a bunch of rules, but just by interpreting the user's interactions. So if I get rid of those edits, select a different feature,
23:41
I'm gonna shift click to select a number of other features. Now I have shared vertex editing going on. So as I drag around these points, I'm changing the vertices of the adjacent polygons and maintaining the topology of my data there. So I decide I want to reshape Colorado here,
24:04
shouldn't be as big as it is. And I like these mountains down here. And I can efficiently have this sort of shared vertex editing with just some simple user interactions. I didn't have to specify my topology rules. I just let the user select a number of features and move the vertices together.
24:22
So the final goal I hope that I've motivated you to engage in is to get involved in the library. We encourage people to become contributors. Please find the code on GitHub. I saw some people make a mistake in a sprint earlier. We're working in the OL3 repository under the OpenLayers organization.
24:41
And then there's a mailing list. And soon we will have an updated website at this OL3js.org location. And if you're interested in playing around with these examples, you can see this whole, the slides up at this URL, tshub.net,
25:01
working with OL3. And thanks, sorry for going a little bit over, but I hope I've got time for a few questions.