Tangram Versions Save

WebGL map rendering engine for creative cartography

v0.21.1

3 years ago

Bugfixes

  • Resolve named textures in imports using final merged scene #748 #770
    • Fixes issue where a named texture that is referenced but not defined in an imported scene (which is "later" defined by a sibling scene or importing ancestor scene) are resolved incorrectly, and interpreted as texture URLs.

v0.21.0

3 years ago

New Features + Improvements

  • Add support for text highlight boxes + underlines on point labels #761 #724 #723
    • Add an optional box behind text labels via the following parameters in a new font.background block:
      • font.background.color: text box fill color
      • font.background.alpha: optionally modify box fill alpha
      • font.background.stroke.color: text box stroke color
      • font.background.stroke.alpha: optionally modify box stroke alpha
      • font.background.stroke.width: text box stroke width (defaults to 1px)
    • Optional underline for text labels via new parameter font.underline
      • underline: true to enable text underline
    • Text box fill, stroke, and underline are independent options which can be mixed and matched as desired. Example with all 3:
        draw:
          text:
            font:
              ...
              background:
                color: white
                stroke:
                  color: red
                  width: 2px
              underline: true
      

tangram-1596403969461

  • Support variable font weight ranges + JS function weights #757
    • Variable fonts allow multiple variants of a font to be stored in a single file. Supporting these can streamline the Tangram font definition, reduces network requests, and introduces new cartographic flexibility for dynamically-driven font weights.
    • Example supporting font weights of 200 through 800:
      fonts:
        Open Sans:
            url: fonts/Open Sans.woff2
            weight: 200 800
      
    • Example of JS function-based font weight, e.g. mapping font weight to building heights:
      weight: |
        function() {
          return (feature.height||0) * 2 + 400;
      }
      
  • Automatically add Leaflet attribution controls based on data source property #763
    • Adds a new attribution property on data sources, which when present will add a Leaflet attribution control. Thanks @bdon!
    • Example:
        sources:
          tilezen:
            type: MVT
            url: https://tile.nextzen.org/tilezen/vector/v1/512/all/{z}/{x}/{y}.mvt
            attribution: Tiles by <a href="https://www.nextzen.org/" target="_blank">Nextzen</a>
            ...
      
  • Improved proxy tile handling for better coverage when zooming in/out (thanks @bdon!) #762
  • Support for MultiPoint geometries in MVT data sources 8554c27

Bug Fixes / Internal

  • Outlines are now properly extruded with their lines #749
  • Remove use of flatMap()
  • Upgrade earcut library to v2.2.2 #755

v0.20.1

4 years ago

New Functionality

  • Wireframe mode for debugging #745
    • Use debug option wireframe: true to draw geometry in a wireframe mode, helpful for seeing how Tangram converts feature geometries into renderable GL triangles, and debugging issues with such
    • Example of enabling wireframe mode when the Tangram layer is created:
    const layer = Tangram.leafletLayer({
      scene: 'scene.yaml',
      debug: {
        wireframe: true // enable for wireframe rendering mode
      }
    });
    

Bug Fixes

  • Fix inconsistencies in handling of line dash colors and alpha #741 #742
    • Alpha of dash foreground and background colors should not affect each other
    • More consistent handling of alpha cutout behavior for opaque blending
  • Remove spurious errors when an untiled data source is drawn with the all_layers flag set #747 77b9edb

Internal

  • Upgrade geojson-vt to v3.2.1

v0.20.0

4 years ago

New Functionality

  • Custom attributes for styles #739
    • Styles can now define custom vertex attributes/varyings for use in GLSL shader code. This simplifies existing uses of per-feature property data in shaders (which have usually been "smuggled" into the shader by encoding non-color values in the color parameter), moving these values to semantic-appropriate attributes, and enabling more advanced forms of custom shader visualizations by allowing for multiple attributes to be defined.
    • In a style declaration, the shaders block can now contain a new entry called attributes -- a mapping of names to properties of custom vertex attributes. Those new attributes are given values in draw groups by assigning a value to the attribute's name in a new attributes block, and are then available inside shader blocks. All together, the new syntax looks like this:
      buildings:
        base: polygons
        shaders:
          attributes:
            height:
              type: float
          blocks:
            color: |
              // Use the custom attribute's varying to shade by height
              color.rgb = vec3(min(height / 100., 1.), 0., 0.);
        draw:
          # use default draw parameters to set the height attribute value from the height feature property
          attributes:
            height: function() { return feature.height; }
      
    • The above example uses default draw parameters (inside the style definition) to assign the attribute values, which is convenient if the attribute is always tied a specific feature property. However, these attributes can also be set in any draw group within layers, as with all other draw parameters.
    • Attribute values can be set as a JS function (e.g. to tie a numeric feature property to an attribute of the same name, likely the most common case for this functionality: custom: function(){ return feature.custom; }), a single value (custom: 5), or zoom-interpolated values (custom: [[14, 50], [15, 150], [16, 300]]).
    • Only 32-bit floating point values (defined as type: float in the attribute definition) are supported at this time (other attribute types may be supported in the future).
    • See #739 for full syntax.
  • Alpha parameter for draw groups #740
    • A new alpha parameter inside draw groups allows the scene author to set only the alpha channel of a color, independently of the RGB channels. This is useful for cases such as:
      • Modifying the alpha for named CSS colors
      • Modifying the alpha channel in a sub-layer
      • Using a feature property to set the color, but then modifying only the alpha
    • In draw groups where an alpha parameter is present, its value will override the alpha channel set by the corresponding color parameter. For example:
      translucent_polygons:
        color: red
        alpha: 0.5 # red polygon with 50% opacity
      
    • The alpha parameter is available for polygons (fill color), lines (inline and outline color), points (fill and outline color), text (font fill and stroke color), and raster (color).
    • alpha values can be set as a single value (alpha: 0.5), zoom-interpolated values (alpha: [[14, 0.5], [16, 1]]), or JS function (alpha: function(){ return feature.height/200; })
    • See #740 for full syntax.
  • Add raster-based styles to blend/base default styles 4609a89
    • An oversight when these new built-in style combinations were added in v0.19.0

Bug Fixes

  • Fix mesh variant cache for line outlines 4fc6b91
  • Fix event subscription notifications for style compilation errors e76e4fd
    • Fixes Tangram Play inline shader compile errors

Internal

  • Avoid polluting user-defined styles (scene.config.styles) with blend/base default styles 824ec12

v0.19.1

4 years ago

Improvements

  • Support HTTP 204 response #734
    • Adds support for HTTP 204 (No Content) responses in tile requests. These tiles will be considered to have loaded successfully, but will simply be empty. Previously these requests would cause warnings.
  • Updates to built-in demo UX and scene examples.

Bug Fixes

  • Fix dynamic font sizes (size: function() { ... }) on high-density displays (previously, display density scaling wasn't applied, so these fonts would be too small on > 1x displays). feca756 9406e5d

v0.19.0

4 years ago

New Features

  • Add new built-in rendering styles for all combinations of blend and base #719
    • This feature eases another common pain point with blend modes, as a follow-up to enabling blend_order to be set at the draw level in v0.18.0.
    • New built-in rendering styles are now included, to make it easier to use the different blend modes without having to write boilerplate styles. For each combination of blend mode (opaque, overlay, etc.) and style base (polygons, lines, etc.), a style is automatically created at scene load-time with the naming scheme blend_base, e.g. translucent_polygons, overlay_lines, etc. Each of these is a minimal style definition, such as (if expressed in YAML):
    translucent_polygons:
      base: polygons
      blend: translucent
    
    • To maintain backwards compatibility, any of these new "bootstrapped" styles is skipped if the user has already defined one with the same name in their scene.
  • Add support for parsing MVT feature properties as JSON #715
    • Some MVT data sources include properties with a richer object format than just strings or numbers -- e.g. arrays, nested objects, etc. The MVT spec doesn't prescribe explicit behavior for these cases, but notes that common tools such as Tippecanoe and Mapnik will encode these properties as stringified JSON.
    • Client-side support for parsing these fields is added through a new parse_json property:
      • If parse_json is true, then each property will be checked to see if it "looks like" stringified JSON (defined as a string with first character being { or [); if so, it is parsed as JSON (with JSON.parse).
      • If parse_json is an array of property names, only those specific properties are checked for JSON parsing. This is preferred to the above, because it limits the parsing impact to only the fields that need it.
      • If parse_json is undefined/null/false, no special parsing of properties is done (e.g. the current behavior).
    • Example usage:
    sources:
      tiles:
        type: MVT
        url: https://...
        parse_json: [prop_a, prop_b] # treat feature properties 'prop_a' and 'prop_b' as stringified JSON
    
  • Add native filter syntax for accessing nested feature properties #715
    • Dot notation with . can be used to access nested feature properties (these properties could have been encoded in a GeoJSON/TopoJSON source, or parsed from MVT stringified JSON properties with the feature introduced above). Previously, these properties could only be accessed through custom JS filter functions.
    • Given a feature property a: { b: { c: 'test' } }, this filter will match:
      • filter: { a.b.c: test }
    • Feature property names that include a . can be escaped with \., e.g. a feature property named 'd.e.f': 'escaped' will match with:
      • filter: { d\.e\.f: escaped }
    • These could be mixed, e.g. a property { 'a.b': { c: 'mixed' } would match with:
      • filter: { a\.b.c: mixed }
  • Add native filter syntax for array-to-array operations #715
    • As part of the new support for "complex" property values that may be arrays, we can expand our filter syntax to support querying these fields more easily. Two keywords are added for this, extending the same filter object pattern we use for min/max range filter syntax.
    • includes_any: check if an array a contains one or more of the values p, q, r:
      • filter: { a: { includes_any: [p, q, r] } }
    • includes_all: check if an array a contains the values p, q, AND r:
      • filter: { a: { includes_all: [p, q, r] } }
  • Add all_layers: true wildcard for data source layer matching #713
    • Introduces a "wildcard" syntax for the source layer in the data block in layers. When the parameter all_layers: true is included, it will match ALL layers in the data source. This is useful for easily creating wireframe-like views, without knowing or needing to specify all the layers in the data source.

Improvements

  • More robust support for feature.id #720
    • All data formats supported by Tangram have a feature.id property (at the top feature level, outside feature.properties; some data sets may separately include an id or similar property within feature.properties), but we haven't had full support for it. This version fixes that.
    • Ensures feature.id persists wherever features are internally copied/synthesized/etc. internally
    • Provides access to feature.id in user-authored JS scene functions with a new $id variable
    • Includes feature.id in feature object results returned from scene.queryFeatures()
    • Includes feature.id in the default uniqueness check for scene.queryFeatures(), with $id syntax used if specifying a list of properties to uniqueify on (see #720 for details).
  • More intuitive default repeat_distance for point feature labels #718
    • The default repeat_distance for labels has always been 256px across the board. This is a sensible default for cases such as street labels (the original use case for repeat label culling) and road shields, but can generate unexpected results particularly when applied to point labels. For example, when labelling data with a property that has a finite set of values, such as category names ("bar", "restaurant", "hardware store", etc.) or numeric values, it's often surprising/undesirable that only a few labels are plotted.
    • This version changes this behavior such that:
      • For labels generated from point features, the default repeat_distance is 0px.
      • For all other labels, including those generated from line or polygon features (e.g. street names, road shields, park names, etc.), the default repeat_distance continues to be 256px. Note that in these examples, the labels themselves may still be point labels -- it is the underlying geometry type that matters, e.g. road shields are point labels generated from line geometries.
    • See #718 for example.

Bug Fixes

  • Handle tiles with no data in scene.queryFeatures() 7946554
  • Workaround for obscure bug seen with small (<28px) SVG images encoded as data URLs e1f2869

Performance/Internal

  • Add a collision grid for better performance of high density point/label scenes #722
    • Adds a simple collision grid system to drastically reduce the number of collisions performed for dense data sets. In a collision grid, the labels are divided (in this case in screen-space) into a grid of a given size; each label is added to the one or more grid cells that it intersects. When we need to know which labels a given label intersects, we only need to test the "local" labels that are in the same grid cells. See #722 for details.
  • Default to WebGL "high performance" mode #721
    • Defaults to using high-performance for WebGL's powerPreference setting. This will ask for use of the discrete GPU where possible. The user can override this default, as with other GL context options:
    const layer = Tangram.leafletLayer({ scene, { webGLContextOptions: { powerPreference: 'low-power' } } });
    

v0.18.2

4 years ago

Improvements

  • More efficient filters for checking value in array (e.g. kind_detail: [park, aerodrome, university]) bcd6754
  • Run collision immediately on view change to reduce label crowding on zoom out 6d40cd9

Bug Fixes

  • Don't overflow line texture u coordinates f2b4957
  • Namespace "private" shader variables with _ to reduce collisions with user-defined styles a3ab5d4
  • Fix label tile breach test 2a6fc6c

Demo

  • Add support for loading custom scene URLs with scene query param
  • Upgrade Refill version and use MVT tiles for default demo

v0.18.1

5 years ago

Improvements

  • Avoid redundant view_complete events while scene is updating. 593c312 8bc21d5
  • Improved build time for points and labels through decreased garbage collection (by avoiding memory allocation for temporary objects). Improves build time of dense point datasets by up to 33%. e0e99e6 9d772cd af89f8e f4905ff 482eada c5ed335 e2f0ab9 d55a9c5
  • Improved memory usage / garbage collection for collision detection through OBB (oriented bounding box) optimizations. ee9a0e5 5ae018d 11fd782 f0f9b41

Bug Fixes

  • Fix rotation of point label collision boxes. 1a16473
  • Don't wrap lat/lng coordinates when calculating tiles for data source bounds. b08f8c8
  • Only apply queryFeatures() to tiles that are loaded. fbb9e33

v0.18.0

5 years ago

New Features

  • More layer matching control with priority and exclusive #705
    • priority controls the order in which sub-layers at the same level are matched, and which one "wins" when multiple matching layers are merged.
    • exclusive ensures that the layer is mutually exclusive, and no other sub-layers at the same level will match.
    • Used together, if/else if/else filter patterns can be expressed with these new keywords, e.g.:
      layers:
        layerA:             # if matches layerA...
          filter: ...
          priority: 1
          exclusive: true
          draw: ...
        layerB:             # else if matches layerB...
          filter: ...
          priority: 2
          exclusive: true
          draw: ...
      
  • Data sources can define specific zoom levels at which tiles are loaded #702
    • In some cases it may be unnecessary or undesirable to load new tile data at every zoom level. The new zooms parameter allows for control over which map view zoom levels load new tiles, with tiles overzoomed when viewing zooms in between. For example, to only load new tile data at every other zoom level:
      sources:
        tilezen:
          type: MVT
          url: ...
          zooms: [0, 2, 4, 6, 8, 10, 12, 14, 16] # only load tiles every 2 zooms
      
    • If both zooms and max_zoom is present, the last zoom listed in zooms takes precedence, and overrides the max_zoom parameter. The min_display_zoom also automatically defaults to the first entry in the zooms list.
  • Enable setting of blend_order at the draw group level #703
    • Rather than requiring the blend_order to be set at the styles level (which has led to an unwieldy pattern of several "template" styles that vary only by blend_order), this change enables blend_order to be set within a draw group. This allows for much more flexible blend_order expressions, and a semantic use that aligns with the order parameter used for geometry world order of opaque-rendered features. For example, for a style with overlay blending:
      layers:
        overlays:
          draw:
            polygons-overlay:
              blend_order: 3
              ...
      
  • Quadkey support for tile URL templates #701
    • Support for the quadkey tile URL scheme is now available with the {q} token (as an alternative to the {x}/{y}/{z} URL pattern). For example, a Microsoft aerial imagery raster layer:
      sources:
        msft-aerial:
            type: Raster
            url: https://ecn.t3.tiles.virtualearth.net/tiles/a{q}.jpeg?g=587
      

Improvements

  • Improved label collision when zooming #709
  • Remove compounding alpha flicker artifacts when zooming non-opaque features #704

Bug Fixes

  • Fix force disable of Vertex Array Objects (for dev/debugging) f4235db

v0.17.5

5 years ago

Bug Fixes

  • Restore v0.16.x alpha cutout behavior for some points blend modes (opaque, translucent, multiply) 42381ec
    • Addresses regression with points rendered with non-overlay/inlay blending.
    • May revisit overall alpha cutout approach/consistency across styles in future release.
  • Guard against deleted mesh on main thread collision b91208a
    • Addresses rare race condition leading to (spurious) error log.

Improvements

  • Adjust tile pad scale to further minimize tile gaps/overlaps at high zooms f9b3f51
  • Additional alpha cutout behavior for un-tiled rasters in some blend modes (translucent, multiply), to avoid fully transparent pixels from obscuring geometry underneath (may revisit overall alpha cutout approach/consistency across styles in future release) 2601a1f