Giter Club home page Giter Club logo

mapbox-vector-tile-cs's Introduction

mapbox-vector-tile-cs

NuGet Status

.NET 8

.NET 8 library for decoding a Mapbox vector tile.

Optionally it's possible to convert the tile into a collection of GeoJSON FeatureCollection objects.

For each layer there is one GeoJSON FeatureCollection. Code is tested using the Mapbox tests from

https://github.com/mapbox/vector-tile-js

Dependencies

  • GeoJSON.NET

  • JSON.NET

  • protobuf-net

Installation

$ Install-Package mapbox-vector-tile

Usage

const string vtfile = "vectortile.pbf";
using (var stream = File.OpenRead(vtfile))
{
  // parameters: tileColumn = 67317, tileRow = 43082, tileLevel = 17 
  var layerInfos = VectorTileParser.Parse(stream);
  var fc = layerInfos[0].ToGeoJSON(67317,43082,17);
  Assert.IsTrue(fc.Features.Count == 47);
  Assert.IsTrue(fc.Features[0].Geometry.Type == GeoJSONObjectType.Polygon);
  Assert.IsTrue(fc.Features[0].Properties.Count==2);
}

See also https://github.com/bertt/mapbox-vector-tile-cs/blob/master/tests/mapbox.vector.tile.tests/TileParserTests.cs for working examples

Tip: If you use this library with vector tiles loading from a webserver, you could run into the following exception: 'ProtoBuf.ProtoException: Invalid wire-type; this usually means you have over-written a file without truncating or setting the length' Probably you need to check the GZip compression, see also TileParserTests.cs for an example.

Building

$ git clone https://github.com/bertt/mapbox-vector-tile-cs.git
$ cd mapbox-vector-tile-cs
$ dotnet build

Testing

$ git clone https://github.com/bertt/mapbox-vector-tile-cs.git
$ cd mapbox-vector-tile-cs/tests/mapbox.vector.tile.tests
$ dotnet test
Passed!
Failed: 0, Passed: 38, Skipped: 0, Total: 38, Duration: 937 ms

Benchmarking

Test performed with Mapbox vector tile '14-8801-5371.vector.pbf'

Layers used:

Point layer: parks (id=17) - 558 features

Line layer: roads (id=8) - 686 features

Polygon layer: building (id=5) - 975 features

Host Process Environment Information:
BenchmarkDotNet.Core=v0.9.9.0
OS=Microsoft Windows NT 6.2.9200.0
Processor=Intel(R) Core(TM) i7-6820HQ CPU 2.70GHz, ProcessorCount=8
Frequency=2648440 ticks, Resolution=377.5808 ns, Timer=TSC
CLR=MS.NET 4.0.30319.42000, Arch=32-bit RELEASE
GC=Concurrent Workstation
JitModules=clrjit-v4.6.1586.0

Type=ParsingBenchmark  Mode=Throughput
-------------------------------- |-------------- |-------------|
                          Method |    Median     |    StdDev   |
-------------------------------- |-------------- |-------------|
       ParseVectorTileFromStream |     1.7147 us |   0.0196 us |
 --------------------------------|-------------- |------------ |
   VectorTilePointLayerToGeoJSON |   719.3773 us |   5.7271 us |
    VectorTileLineLayerToGeoJSON | 1,532.6888 us | 114.5458 us |
 VectorTilePolygonLayerToGeoJSON | 4,458.0017 us | 274.7238 us |
-------------------------------- |-------------- |-------------|

History

2023-11-26: Release 5.0.2, containing .NET 8

2022-10-29: Release 5.0.1, upgrading dependencies

2022-10-29: Release 5.0 containing .NET 6

2018-08-28: Release 4.2 containing .NET Standard 2.0

2018-03-08: Release 4.1 with fix for issue 16 (#16 - about serializing attributes)

2017-10-19: Release 4.0 for .NET Standard 1.3

2016-11-03: Release 3.1

Changes: Add support for polygon inner- and outerrings

2016-10-31: Release 3.0

Changes: Add support for multi-geometries

2015-07-08: Release 2.0

2015-07-07: Release 1.0

mapbox-vector-tile-cs's People

Contributors

bertt avatar cschwarz avatar pauldendulk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mapbox-vector-tile-cs's Issues

Support older versions with polygons having outer/inner ring NOT coded by winding order

I have a version of Mapnik producing tiles with layers of version 1 of the spec, where polygons seems to be coded with outer ring first and any holes after that, i.e. NOT coded by winding order.

Version 2 of the spec first defined how to interpret which rings are exterior and which are interior.
MVT renderers seems to be relaxed regarding how to interpret polygons of version 1.
So I suggest this library do this to.

I can create a PR if you believe this is a wanted feature in your library.

[Question] Mapbox vector tile server solution

Hi,

I would like to create a PoC for .Net based Vector Tile server and serve Mapbox and GeoJson vector tile format. I'm planning to load the map data from OSM with OsmSharp

Do you know a sample about it or could you adjust me to a right direction?

I'm new in the map rendering and vector tile rendering so any help would be awesome.

Thanks

Nested geometry data arrays are not identified.

I tried to use this plugin with the mapbox tile:
https://b.tiles.mapbox.com/v4/mapbox.mapbox-terrain-v2,mapbox.mapbox-streets-v7/13/4260/2911.vector.pbf

If I parse this tile with javascript libraries, I see multiple arrays in the geometry of a feature:
tile.layers.road.feature(i).loadGeometry().length
//usually has a value of 1, but sometimes more

The c# package can only show a single List and the lines I render jump around the tile, connecting the separate paths.

I can include more detailed instructions to show the problem, but I found the issue to be obvious in any tile I try to load and display with c# code.

C#: How to encode vector tiles to be used in a mapbox endpoint

I'm using react-map in a project. This map, adds a tile layer:

layers.push({
            'id': "map-layer-2",
            'type': 'line',
            'source': {
                'type': 'vector',
                'tiles': [
                    "http://localhost:52358/api/Planet/Test/7?TileRow={y}&TileCol={x}&Zoom={z}"
                ],
                'minzoom': 12
            },
            'source-layer': 'planet_osm_line',
            'layout': {
                'line-cap': 'round',
                'line-join': 'round'
            },
            'paint': {
                'line-opacity': 0.6,
                'line-color': 'rgb(14,144,236)',
                'line-width': 3
            }
        });

As you can see this layer queries an endpoint which provides a tile-layer. This endpoint is made in C#, and simple returns a Stream which reads a valid pbf file. However I don't want to provide the base pbf, I need to work a little on it first.

So I'm using your library to decode the pbf, and work with it, before returning the result to client. But, i don't know how to encode again the object, there is no to-pbf-byte method.

public async Task<Stream> Data(long tileRow, long tileCol, int zoom, ClientSettings clientSettings){
     //...some extra code here
     Stream data = //don't bother how this gets initialized. It's a correct pbf

      //At this point, if a simply do: "return data" everything works as expected. Mapbox show the plain data

     //Deserialize data to work with it
     var layerInfo = VectorTileParser.Parse(data);  //<---At this point layerInfo has all the info of the pbf. No problem here

     //For test purpose there is no more code.
     //At this point I need to create a valid pbf again
     return layerInfo.???;
}

I tried to serialice vector tile using BinaryFormatter, but it seems VectorTileLayer it's not marked as serializable, because it throws an exception.

using (var stream = new MemoryStream())
        {
            var formatter = new BinaryFormatter();
            formatter.Serialize(stream, layerInfo); //<-- exception here
            stream.Flush();
            return stream;
        }

Bugs in Attribute Parser ...

The AttributeParser does not currently handle sIntValues and the code is incorrect for uInts. The bottom of the GetAttr method should look like this:

        else if(value.HasSIntValue)
        {
            res = value.SintValue;
        }
        else if (value.HasUIntValue)
        {
            res = value.UintValue;
        }

Cheers,
Tom Cuthill

Issues with thread safety ...

If I try to use the VectorTileParser.Parse method running in multiple threads I consistently get exceptions being thrown from the protobuf-net library. Here is the internal exception:

Timeout while inspecting metadata; this may indicate a deadlock. This can often be avoided by preparing necessary serializers during application initialization, rather than allowing multiple threads to perform the initial metadata inspection; please also see the LockContended event

Apparently reading a class's metadata in the protobuf-net library is not thread safe. See here:
http://stackoverflow.com/questions/17096359/is-protobuf-net-thread-safe

The recommended solution is prepare the serializer for the class before the Serializer.Deserializer is called.

I tried following the advice, and put this at the top of the VectorTileParser class:

static VectorTileParser()
{
Serializer.PrepareSerializer();
}

I can see, while using a debugger, that the static initializer is called first, and then the subsequent calls to the Parse method come in. Unfortunately the same exception still happens.

I've attached some sample code to demo the problem. I am not an expert on threading, but I can not see how the mapbox-vector-tile-cs library can be causing a deadlock. Based on the exception, it appears there is contention on reading the Tile classes metadata. I would have thought that doing the PrepareSerializer() in the static constructor would have prevented this from happening?

Being able to load vector tiles in parallel is important to the app I am building so that there is decent performance on the client.

Please let me know your thoughts,

Cheers,
Tom Cuthill

TestCode.txt

Zero integer values lost on serialization

Hi, first thing first - great project, huge timesaver. I know it is intended only as decoder, but I am using it with success to do minor edits to vector tiles - deserialize, rename some layers, remove some layers, remove some features from layers, and serialize back. It generally works great, with one exception - attributes (properties) which are for example integer value zero, and are correctly deserialized as HasIntValue=true and IntValue=0 are not correctly serialized back (if you deserialize the tile serialized this way, HasIntValue' is falsein thatValue` object.
Do you think this can be fixed easily somehow? Thanks!

Mapbox-vector-tile does not support MemoryStream

The case is:

Im trying to read .pbf files from Rosreestr and in case where I want to transform them into MemoryStream and pass to mapbox-tile-server the library doesnt parse it.

Example file
1195.pbf.zip

This example works totally fine

namespace test_mapbox;
using GeoJSON.Net.Feature;

using Mapbox.Vector.Tile;

class Program
{
    static void Main(string[] args)
    {
        using (var stream = File.OpenRead("test.pbf"))
        {
            var tile = VectorTileParser.Parse(stream);
            foreach (var layer in tile)
            {
                Console.WriteLine(layer.Name);
            }            
        }
    }
}

But when I try to:

var pbfFile = response.ResponseBinary;
var stream = new MemoryStream();
stream.Write(pbfFile, 0, pbfFile.Length);
var layers = VectorTileParser.Parse(stream); // This one returns zero length sequence

You can try download the file by yourself using this link https://pkk.rosreestr.ru/arcgis/rest/services/Hosted/caddivsion/VectorTileServer/tile/12/1190/2392.pbf but VPN within Russia is needed to access it

Decryption of Encrypted Vector Tiles

Hi, I'll try to be brief, but I'll share the whole picture.

Problem Statement

I am using vector tile from tippecanoe from mapbox to create .pbtiles from my geojson data. The issue is, on a web client when I see the inspect element and download the .pbf and run it by this (mapbox-vector-tile-cs) library, I am able to successfully get the data from the tile. Which means that any one with some basic google search can also steal my data from the vector tiles.

What I was able to achieve

To avoid the security concern, with the short timeline I have, I came up with a quick and dirty way. After tippecanoe creates the .mbtiles sqlite db, I run a java utility I made to encrypt the data in the blob using AES 256 encryption and stored it in two different ways in two different sqlite db's:

  1. Stored as bytes into a different .mbtiles sqlite db (which get's stored as Blob). Along with z, x, y and metadata

  2. Encoded the encrypted data as base64 and then stored the base64encoded encrypted tile data into a string data type column. Along with z, x, y and metadata.

and stored the key (base64 encoded) and initialization vector (base64 encoded) into a file.

The API side (Question 1)

Now, when I get the non encrypted .pbf from the API, a header of type gzip and application/x-protobuf is set that helps to convert the unencrypted blob data to a protobuf and returns a .pbf file that gets downloaded.

Now when I try to get the encrypted data from the API with the same header as the non encrypted on, the download of the .pbf fails saying Failed - Network error. I realized that it's being caused as the header application/x-protobuf is trying to package the file into a .pbf while the contents of the blob might not be matching what's expected and hence the result.

I removed the header application/x-protobuf and since I can't gzip now, i removed the header of gzip too. Now the data gets displayed on the chrome browser instead of being downloaded, I figure as now it's just a random response.

The question is, How can I make it to send a .pbf that has encrypted data in it and this((mapbox-vector-tile-cs)) library can parse the data? I know the data will be need to be decrypted first before I pass it for parsing assuming that it's decrypted and I have the data that was stored into the blob of the .mbtiles.

This Library with a UWP project (Question 2)

So now currently as mentioned above (since i don't have a solution to the headers part) I removed the headers and let the API return me a direct response.

The Issue now I am facing is that when I pass in the decryted (I checked the decryption was successful and the decrypted data is an exact match to the what was stored in the Blob) Blob data to the

var layerInfos = VectorTileParser.Parse(stream);

code line returns me an IEnumerable<Tile> that is not null but has 0 layers in it. while the actual tile contains 5 layers in it.

My Question is, how do I get this((mapbox-vector-tile-cs)) library to return me the layers.

The code to fetch the tile from the server and decrypt before I send it for parsing is as below:

 //this code downloads the tile, layerInfos is returned as an empty collection
 private async Task<bool> ProcessTile(TileData t, int xOffset, int yOffset)
 {
      var stream = await GetTileFromWeb(EncryptedTileURL,true);

      if (stream == null)
          return false;

      var layerInfos = VectorTileParser.Parse(stream);

      if (layerInfos.Count == 0)
          return false;

      return true;
 }

The tiles are fetched from the server using a GetTileFromWeb() method:

    private async Task<Stream> GetTileFromWeb(Uri uri, bool GetEnc = false)
    {
        var handler = new HttpClientHandler();

        if (!GetEnc)
            handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;

        var gzipWebClient = new HttpClient(handler);


        var bytes = gzipWebClient.GetByteArrayAsync(uri).Result;

        if (GetEnc)
        {
            var decBytes = await DecryptData(bytes);
            return decBytes;
        }

        var stream = new MemoryStream(bytes);
        return stream;
    }

PS: Sorry for such a long question, I am not used to such elaborate detail, but seemed I need to share more as Encryption is my forte while map data vector tiles isn't.

Signed area calculation is incorrect ...

It appears that the code to implement the Surveyors / Shoelace formula in the SignedArea method is incomplete. It is missing the boundary conditions when you consider the last point's X needs to match with the first point's Y and vice-versa.

Consider the simple triangle with vertices: [1,1], [2,2], [3,1]. The area of a triangle is a half of the base times the height. That gives an area of 1. Your algorithm gives an area of 2.

A proper implementation would look like this:

private double SignedArea(List points)
{
double sum = 0.0;
for (int i = 0; i < points.Count; ++i)
{
sum += points[i].X * (((i + 1) == points.Count) ? points[0].Y : points[i + 1].Y);
sum -= points[i].Y * (((i + 1) == points.Count) ? points[0].X : points[i + 1].X);
}
return 0.5 * sum;
}

Note as well, that vector tiles have an origin at the top left of the tile (ie. the Y axis is inverted). As a result your tests for clockwise / counterclockwise are the opposite of what they should be.

According to the 2.1 spec (https://github.com/mapbox/vector-tile-spec/tree/master/2.1) :

4.3.4.4. Polygon Geometry Type
...
An exterior ring is DEFINED as a linear ring having a positive area as calculated by applying the surveyor's formula to the vertices of the polygon in tile coordinates. In the tile coordinate system (with the Y axis positive down and X axis positive to the right) this makes the exterior ring's winding order appear clockwise.

An interior ring is DEFINED as a linear ring having a negative area as calculated by applying the surveyor's formula to the vertices of the polygon in tile coordinates. In the tile coordinate system (with the Y axis positive down and X axis positive to the right) this makes the interior ring's winding order appear counterclockwise.

Hope this helps,
Tom

Not supported in a UWP application

I tried to install in my UWP application and the nugget installation failed. The below is the log:
`PM> Install-Package mapbox-vector-tile
Restoring packages for 'VectorMaps'.
Restoring packages for c:\users\ceinfo\documents\visual studio 2015\Projects\VectorMaps\VectorMaps\project.json...
GET https://api.nuget.org/v3-flatcontainer/mapbox-vector-tile/index.json
OK https://api.nuget.org/v3-flatcontainer/mapbox-vector-tile/index.json 1032ms
GET https://api.nuget.org/v3-flatcontainer/mapbox-vector-tile/3.1.1/mapbox-vector-tile.3.1.1.nupkg
OK https://api.nuget.org/v3-flatcontainer/mapbox-vector-tile/3.1.1/mapbox-vector-tile.3.1.1.nupkg 1194ms
Installing mapbox-vector-tile 3.1.1.
Install-Package : mapbox-vector-tile 3.1.1 is not compatible with UAP,Version=v10.0.
At line:1 char:1

  • Install-Package mapbox-vector-tile
  •   + CategoryInfo          : NotSpecified: (:) [Install-Package], Exception
      + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand
    
    

Install-Package : Some packages are not compatible with UAP,Version=v10.0.
At line:1 char:1

  • Install-Package mapbox-vector-tile
  •   + CategoryInfo          : NotSpecified: (:) [Install-Package], Exception
      + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand
    
    

Install-Package : mapbox-vector-tile 3.1.1 is not compatible with UAP,Version=v10.0 (win10-arm).
At line:1 char:1

  • Install-Package mapbox-vector-tile
  •   + CategoryInfo          : NotSpecified: (:) [Install-Package], Exception
      + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand
    
    

Install-Package : Some packages are not compatible with UAP,Version=v10.0 (win10-arm).
At line:1 char:1

  • Install-Package mapbox-vector-tile
  •   + CategoryInfo          : NotSpecified: (:) [Install-Package], Exception
      + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand
    
    

Install-Package : mapbox-vector-tile 3.1.1 is not compatible with UAP,Version=v10.0 (win10-arm-aot).
At line:1 char:1

  • Install-Package mapbox-vector-tile
  •   + CategoryInfo          : NotSpecified: (:) [Install-Package], Exception
      + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand
    
    

Install-Package : Some packages are not compatible with UAP,Version=v10.0 (win10-arm-aot).
At line:1 char:1

  • Install-Package mapbox-vector-tile
  •   + CategoryInfo          : NotSpecified: (:) [Install-Package], Exception
      + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand
    
    

Install-Package : mapbox-vector-tile 3.1.1 is not compatible with UAP,Version=v10.0 (win10-x64).
At line:1 char:1

  • Install-Package mapbox-vector-tile
  •   + CategoryInfo          : NotSpecified: (:) [Install-Package], Exception
      + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand
    
    

Install-Package : Some packages are not compatible with UAP,Version=v10.0 (win10-x64).
At line:1 char:1

  • Install-Package mapbox-vector-tile
  •   + CategoryInfo          : NotSpecified: (:) [Install-Package], Exception
      + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand
    
    

Install-Package : mapbox-vector-tile 3.1.1 is not compatible with UAP,Version=v10.0 (win10-x64-aot).
At line:1 char:1

  • Install-Package mapbox-vector-tile
  •   + CategoryInfo          : NotSpecified: (:) [Install-Package], Exception
      + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand
    
    

Install-Package : Some packages are not compatible with UAP,Version=v10.0 (win10-x64-aot).
At line:1 char:1

  • Install-Package mapbox-vector-tile
  •   + CategoryInfo          : NotSpecified: (:) [Install-Package], Exception
      + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand
    
    

Install-Package : mapbox-vector-tile 3.1.1 is not compatible with UAP,Version=v10.0 (win10-x86).
At line:1 char:1

  • Install-Package mapbox-vector-tile
  •   + CategoryInfo          : NotSpecified: (:) [Install-Package], Exception
      + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand
    
    

Install-Package : Some packages are not compatible with UAP,Version=v10.0 (win10-x86).
At line:1 char:1

  • Install-Package mapbox-vector-tile
  •   + CategoryInfo          : NotSpecified: (:) [Install-Package], Exception
      + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand
    
    

Install-Package : mapbox-vector-tile 3.1.1 is not compatible with UAP,Version=v10.0 (win10-x86-aot).
At line:1 char:1

  • Install-Package mapbox-vector-tile
  •   + CategoryInfo          : NotSpecified: (:) [Install-Package], Exception
      + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand
    
    

Install-Package : Some packages are not compatible with UAP,Version=v10.0 (win10-x86-aot).
At line:1 char:1

  • Install-Package mapbox-vector-tile
  •   + CategoryInfo          : NotSpecified: (:) [Install-Package], Exception
      + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand
    
    

Package restore failed for 'VectorMaps'.
Install-Package : Package restore failed. Rolling back package changes for 'VectorMaps'.
At line:1 char:1

  • Install-Package mapbox-vector-tile
  •   + CategoryInfo          : NotSpecified: (:) [Install-Package], Exception
      + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand
    

`

Using The package on UWP application with .pbf extention files.

Hi, I tried to use the the XAMARIN sample for UWP app from here as directed in the description. The issue I am facing is the MapFilter Common project is fetching data from the local directory, with extentions .mvt the vector tiles I want to deploy are of the format .pbf . Please help me on how can I achieve to implement the .pbf extention vector Tiles files on my map control. Also I want to get the tiles from my server instead of the local directories. could you please help.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.