If we have a gridded vector source, the grid should have something to do with the source data (e.g. the vector data is available in a regular grid). The vector layer renderer's internal grid is for rendering canvas tiles and doesn't have anything to do with the source.
We should discuss whether post render functions must be run after each render frame or not. If these can be run after multiple render frames, it would make sense to increase the timeout. As it is, it looks like post render functions are run for every render. Hard to see what the benefit is in this case.
This simple expression constructor will be used for symbolizer properties and the layer will generate symbolizer literals for rendering by evaluating any expressions with a feature as the this argument and feature attributes as the scope. This allows generating labels that concatenate multiple attribute values together or displaying point symbols that are sized according to a population attribute divided by an area attribute, for example.
This implementation will not work in environments where the content security policy disallows the use of the Function constructor. This is the case on browser extensions. A more content-security-policy-friendly implementation would be to come up with a restricted grammar and write a lex/parser. This is the road I started down, but this verison is far less code, and I think the security policy limitations are minor at this point. This version will always be faster/lighter than a parser, so one is written in the future, it should only be pulled in where content security policy mandates it.
Assuming browser garbage collection cannot happen while we have listeners in the global registry, we need to listenOnce to avoid memory leaks with the tile queue.
Instead of going into an unnecessary animation loop, we can simply wait to be notified when tiles load.
The WebGL renderer still sets frameState.animate true, but I think this too should be unnecessary (full page example works without it, side-by-side example shows it cannot yet be removed).
Instead of keeping track of wanted tile ranges, we can instead track wanted tiles individually. This provides enough for the map to know how to prioritize tiles and should be more efficient (no extra calls to extend tile ranges or check for tile containment within a range).
Without this change, tiles that are enqueued on the first rendering will always get priority `ol.TileQueue.DROP` because `map.frameState_` is not yet defined (meaning a single render call doesn't result in any tiles loading).
It looks like this approach will work well for panning (as anticipated). For animated zooming, it is not going to work as is. It looks like the canvas tile generation is too much for this type of animation loop. Though there are clearly still areas for optimization:
* Don't create new tiles while animating between zoom levels. Using existing tiles only while animating should bring a significant performance gain.
* Simple spatial index for tiles - each tile coord in the matrix could have a feature lookup object (keyed by id). This needs to account for rendered dimension (as witnessed by the point being cut by a tile). Given that the current example uses only three features, adding the spatial index should only be a minor improvement.
* Reuse a fixed set of canvas tiles that are generated at construction (and increased/decreased with view size changes).
* If a fixed set of tiles is not used, at least new ones could be cloned from existing ones (minor).
* Do some profiling to look for more ideas.
In addition, world-wrapping needs addressed. I don't think this renderer is the right (or at least the only) place to address this. And the cache of tiles needs to be managed for real. But hey, at least we've got a working tiled vector renderer now.
I think it's complicating things at this point to deal with this. Unfortunately, it's not proper dateline wrapping as is (only arbitrary tile range extent wrapping).
There is a ton of room for optimization here. The vector layer renderer should only render dirty areas and could maintain a cache of rendered canvas tiles. The vector source could have a simple spatial index for features (by tile coord). Need to also discuss how to work with this animation framework (to avoid the excess work while waiting for tiles to load on every other layer).
Currently only renders points as circles. Eventually will have methods for other geometry types and other symbolizer types. Also provides static methods to render point symbolizers (returning a canvas that can be drawn on another).
The `window.location.search` string includes the "?" symbol. Without this change, `createFromQueryData` only works if the "renderer" parameter is not in first position (see 4037bafc45).
This commit is a cherry-pick of 19f7778.
The current draft of the [filter spec](https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html)
describes brightness, contrast, hue-rotate, and saturate functions that
roughly match our layer's setBrightness, setContrast, setHue, and
setSaturation methods. These changes make the range of our methods match
the corresponding functions in the spec. The one exception is the
brightness function. The spec says it has a range of 0 to positive infinity.
The WebKit implementation accepts a range of -1 to 1 (as of
https://github.com/WebKit/webkit/commit/8f4765e569). There's an open
(ticket)[https://www.w3.org/Bugs/Public/show_bug.cgi?id=15647] recommending
that the spec be changed to match.
I'm not stuck on having our methods match those of the filter spec, but the
parity would be nice.
These changes leave the WebGL map renderer "broken" (whacky colors). It would
be straightforward to update the current fragment shader to handle the new
range of hue, but the brightness, contrast, and saturation handling will
need to be reworked.
For inspiration, here are the color transformation
matrix calculations the WebKit filters:
https://github.com/WebKit/webkit/blob/8f4765e5698c9171c2b3f984d0d9d65188185de3/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurfaceFilters.cpp#L64-80
Conflicts:
src/ol/renderer/dom/domlayerrenderer.js
Telling the compiler that object keys are numeric causes more harm
than good (see === comparison that could never be met though the
compiler didn't catch it).
Never use goog functions without reading the source first. The
goog.array.sort method does nothing special sorting numeric strings
(so the zs array might be ['1', '10', '2'] here).
The render method always generates a map of all tiles that should be drawn
(called tilesToDrawByZ). This includes tiles at alternate resolutions, tiles
still loading, and tiles previously rendered. At the end of the render
sequence we can simply remove all previously rendered tiles that aren't in
tilesToDrawByZ. This provides an alternate solution to the problem described
in #53 and more.
This brings equivalent behavior when rotating in both renderers. Previously, offsets were maintained with style top/left. Now a single transform handles the translation and rotation. The scale3d function removes the separation between tiles. The next step for the DOM renderer is to scale in this same transform.
When loading this example in compiled mode, the page displays the following:
ol3 proj4js demo
[object Object][object Object]
With `mode=RAW`, it does display some numbers, but I think we could better explain this functionality with a different sort of tutorial/example.
Thanks @fredj for the inspiration. This gives us initial rotation support. It exposes some issues in the interactions that I'll address separately. Closes#22.
When zooming to a new zoom level, we can immediately remove tiles from the previous level. This (strongly) suggests not adding images to the container until they have actually loaded.
We only want to adjust things that have to do with rendering (like the position of the layers panel) when actually rendering. The handleXChange methods may be called more times than we can actually render, so we never want to do anything that touches the DOM there. Instead, we have to keep track of the state at previous render and adjust the layers panel (or other) based on changes only when rendering.
When zooming or panning, if we have tiles at alternate resolutions, those tiles are inserted in the DOM before the tiles at the target resolution. This means you should see blurry tiles instead of whitespace when panning (assuming you've already zoomed in a bit).
Tile pruning code separated into to methods for clarity. Alt-z tiles are only removed when all current-z tiles have loaded. Thanks @elemoine for the excellent debugging session.