GithubHelp home page GithubHelp logo

2d-inc / historyofeverything Goto Github PK

View Code? Open in Web Editor NEW
6.4K 6.4K 986.0 10.22 MB

Flutter Launch Timeline Demo

Home Page: https://medium.com/2dimensions/the-history-of-everything-981d989e1b45

License: MIT License

Java 0.16% Objective-C 0.31% Dart 98.65% Ruby 0.88%

historyofeverything's Introduction

The History of Everything

The History of Everything is a vertical timeline that allows you to navigate, explore, and compare events from the Big Bang to the birth of the Internet. Events are beautifully illustrated and animated.

The concept for this app was inspired by the Kurzgesagt video, Time: The History & Future of Everything.

The app was built with Flutter by 2Dimensions and it's available on Android and iOS.

Usage

Make sure you have Flutter installed on your local machine. For more instructions on how to install flutter, look here.

git clone https://github.com/2d-inc/HistoryOfEverything.git
cd HistoryOfEverything/app
git submodule init
git submodule update
flutter run

Overview

The app consists of three main views:

  1. Main Menu - /app/lib/main_menu
    This is the initial view for the app when it opens up. It shows a search bar on top, three menu sections for each major time era, and three buttons on the bottom for accessing favorites, sharing a link to the store, and the about page.

  2. Timeline - /app/lib/timeline
    This view is displayed when an item from the menu is selected: the user is presented with a vertical timeline. It can be scrolled up and down, zoomed in and out.
    When an event is in view, a bubble will be shown on screen with a custom animated widget right next to it. By tapping on either, the user can access the ArticlePage.

  3. ArticlePage - /app/lib/article
    The ArticlePage displays the event animation, together with a full description of the event.

Animated Widgets

This relies heavily on the animations built on 2dimensions and they are seamlessly integrated with Flutter by using the Flare and Nima libraries.

One of Flutter's biggest strengths is its flexibility, because it exposes the architecture of its components, which can be built entirely from scratch: it's possible to create custom widgets out of the SDK's most basic elements.

An example can be found in /app/lib/article/timeline_entry_widget.dart
This file contains two classes:

  • TimelineEntryWidget that extends LeafRenderObjectWidget
  • VignetteRenderObject that extends RenderBox

LeafRenderObjectWidget

This class (docs) is a Widget: it can be inserted in any widget tree without any other default component:

Container(
  child: TimelineEntryWidget(
        isActive: true,
        timelineEntry: widget.article,
        interactOffset: _interactOffset
    )
)

This snippet is used in /app/lib/article/article_widget.dart

The LeafRenderObjectWidget is responsible for having a constructor and encapsulating the values that the RenderObject needs.

The following two overrides are also fundamental:

  • createRenderObject()
    Instantiates the actual RenderObject in the Widget Tree;
  • updateRenderObject()
    Any change to the parameters that are passed to the Widget can be reflected also on the UI, if needed. Updating a RenderObject will cause the object to redraw.

RenderObject

As specified in the docs, this is an object in the render tree, and it defines what and how its creator Widget will paint on the screen.

The key override here is paint():
    the current PaintingContext exposes the canvas, and this class can draw, taking full advantage of the exposed API.
The Flare library, granted access to the canvas, draws the animation.
To have the animation reproduce correctly, it's also necessary to call advance(elapsed) on the current FlutterActor each frame. Moreover, the current ActorAnimation requires that the function apply(time) is called on it to display it's correct interpolated values.
This is all made possible by relying on Flutter's SchedulerBinding.scheduleFrameCallback().

This is just a brief overview of how the Flare widgets can be customized for every experience.

License

All the animations in the /assets folder are distributed under the CC-BY license.

All the articles in assets/articles are from Wikipedia, and are thus distributed under the GNU Free Documentation License.

The rest of the repository's code and contents are distributed under the MIT license as specified in LICENSE.

historyofeverything's People

Contributors

filiph avatar luigi-rosso avatar mishrabhilash avatar neurowave avatar umberto-sonnino 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  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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

historyofeverything's Issues

Add more padding at the bottom of articles

Entirely subjective, but I like to have some breathing room at the bottom of text. Right now the text only has the regular paragraph padding at the very bottom.

I think this can easily be 20-40% of the screen.

Lines go to 20018?

Not sure if it's a bug. Seems like the 5 lines up to recorded history go to 20018. Maybe it's meant to go to 2018?

Feature request: Click to zoom on area

To save on pinching (which can become repetitive and almost tiresome after a while), the user should be able to zoom in on a period by simply clicking on (or close to) the vertical line associated with the event.

For example, clicking on the light-green vertical line next to "Animals" here ...

screenshot-1541257497775

... should zoom in so that we see this:

screenshot-1541257611675

Integrate CI

It would be good if we could have a free build server to see if any commit made break the code. I have heard there are few such services like Fastlane or Nevercode.

Remove ImageFilter on the app bar in non-ludicrous mode

This is probably a large resource hog, and without it, I think the app might lose much of its jank on old devices.

Do this only if it's easy to do. Otherwise, let's talk about other possibilities. For the very low-spec devices, we might want to do more drastic optimizations, such as pausing the animations on scroll.

Experiment with higher inertia for scrolling

Flinging doesn't seem right, at least not on Android. As a user, I am used to fling and see the contents scroll with inertia.

Gif:
screencapture-1541253095698 2018-11-03 14_53_56

Expected scroll behavior:
screencapture-1541253316814 2018-11-03 14_56_24

(This could also be true for zooming, but I'm less sure about that.)

null asset on startup

Everything works, but in profile mode, starting the app will give the following in console:

I/flutter (18295): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter (18295): The following NoSuchMethodError was thrown during paint():
I/flutter (18295): The getter 'width' was called on null.
I/flutter (18295): Receiver: null
I/flutter (18295): Tried calling: width
I/flutter (18295): 
I/flutter (18295): When the exception was thrown, this was the stack:
I/flutter (18295): #0      MenuVignetteRenderObject.paint (package:timeline/main_menu/menu_vignette.dart:124)
I/flutter (18295): #1      RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2085)
I/flutter (18295): #2      PaintingContext.paintChild (package:flutter/src/rendering/object.dart:171)
I/flutter (18295): #3      _RenderStack&RenderBox&ContainerRenderObjectMixin&RenderBoxContainerDefaultsMixin.defaultPaint (package:flutter/src/rendering/box.dart:2273)
I/flutter (18295): #4      RenderStack.paintStack (package:flutter/src/rendering/stack.dart:594)
I/flutter (18295): #5      RenderStack.paint (package:flutter/src/rendering/stack.dart:602)
I/flutter (18295): #6      RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2085)
I/flutter (18295): #7      PaintingContext.paintChild (package:flutter/src/rendering/object.dart:171)
I/flutter (18295): #8      _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:122)
I/flutter (18295): #9      PaintingContext.pushClipRRect.<anonymous closure> (package:flutter/src/rendering/object.dart:418)
I/flutter (18295): #10     ClipContext._clipAndPaint (package:flutter/src/painting/clip.dart:29)
I/flutter (18295): #11     ClipContext.clipRRectAndPaint (package:flutter/src/painting/clip.dart:49)
I/flutter (18295): #12     PaintingContext.pushClipRRect (package:flutter/src/rendering/object.dart:418)
I/flutter (18295): #13     RenderClipRRect.paint (package:flutter/src/rendering/proxy_box.dart:1343)
I/flutter (18295): #14     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2085)
I/flutter (18295): #15     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:171)
I/flutter (18295): #16     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:122)
I/flutter (18295): #17     RenderDecoratedBox.paint (package:flutter/src/rendering/proxy_box.dart:1955)
I/flutter (18295): #18     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2085)
I/flutter (18295): #19     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:171)
I/flutter (18295): #20     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:122)
I/flutter (18295): #21     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2085)
I/flutter (18295): #22     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:171)
I/flutter (18295): #23     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:122)
I/flutter (18295): #24     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2085)
I/flutter (18295): #25     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:171)
I/flutter (18295): #26     RenderShiftedBox.paint (package:flutter/src/rendering/shifted_box.dart:70)
I/flutter (18295): #27     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2085)
I/flutter (18295): #28     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:171)
I/flutter (18295): #29     _RenderFlex&RenderBox&ContainerRenderObjectMixin&RenderBoxContainerDefaultsMixin.defaultPaint (package:flutter/src/rendering/box.dart:2273)
I/flutter (18295): #30     RenderFlex.paint (package:flutter/src/rendering/flex.dart:931)
I/flutter (18295): #31     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2085)
I/flutter (18295): #32     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:171)
I/flutter (18295): #33     _RenderSingleChildViewport.paint.paintContents (package:flutter/src/widgets/single_child_scroll_view.dart:516)
I/flutter (18295): #34     PaintingContext.pushLayer (package:flutter/src/rendering/object.dart:367)
I/flutter (18295): #35     PaintingContext.pushClipRect (package:flutter/src/rendering/object.dart:391)
I/flutter (18295): #36     _RenderSingleChildViewport.paint (package:flutter/src/widgets/single_child_scroll_view.dart:520)
I/flutter (18295): #37     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2085)
I/flutter (18295): #38     PaintingContext._repaintCompositedChild (package:flutter/src/rendering/object.dart:128)
I/flutter (18295): #39     PaintingContext.repaintCompositedChild (package:flutter/src/rendering/object.dart:96)
I/flutter (18295): #40     PipelineOwner.flushPaint (package:flutter/src/rendering/object.dart:852)
I/flutter (18295): #41     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:283)
I/flutter (18295): #42     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:674)
I/flutter (18295): #43     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:219)
I/flutter (18295): #44     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:990)
I/flutter (18295): #45     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:930)
I/flutter (18295): #46     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:842)
I/flutter (18295): #47     _invoke (dart:ui/hooks.dart:145)
I/flutter (18295): #48     _drawFrame (dart:ui/hooks.dart:134)
I/flutter (18295): 
I/flutter (18295): The following RenderObject was being processed when the exception was fired:
I/flutter (18295):   MenuVignetteRenderObject#d5d57
I/flutter (18295):   parentData: top=0.0; right=0.0; bottom=0.0; left=0.0; offset=Offset(0.0, 0.0)
I/flutter (18295):   constraints: BoxConstraints(w=371.4, h=150.0)
I/flutter (18295):   size: Size(371.4, 150.0)
I/flutter (18295): This RenderObject has no descendants.
I/flutter (18295): ════════════════════════════════════════════════════════════════════════════════════════════════════
I/flutter (18295): Another exception was thrown: NoSuchMethodError: The getter 'width' was called on null.
I/flutter (18295): Another exception was thrown: NoSuchMethodError: The getter 'width' was called on null.
I/flutter (18295): Another exception was thrown: NoSuchMethodError: The getter 'width' was called on null.
I/flutter (18295): Another exception was thrown: NoSuchMethodError: The getter 'width' was called on null.
I/flutter (18295): Another exception was thrown: NoSuchMethodError: The getter 'width' was called on null.
I/flutter (18295): Another exception was thrown: NoSuchMethodError: The getter 'width' was called on null.

The exception is thrown on the last line of the following snippet:

	@override
	void paint(PaintingContext context, Offset offset)
	{
		final Canvas canvas = context.canvas;
		TimelineEntry entry = timelineEntry;
		if(entry == null)
		{
			return;
		}

		TimelineAsset asset = entry.asset;
		
		canvas.save();	

		double w = asset.width;// * Timeline.AssetScreenScale;
                // ...

If this is the known issue from below, feel free to close.

Inconsistent Margins and Icons

Looks like we have inconsistent margins and icons across these pages. The margins on both sides of the screen should be 20.

It also looks like we're using the wrong back icon on the About page. We should either make it system dependent (iOS shows the one on the About page, Android shows the one on the detail view page), or we just pick one and use it everywhere on both systems. For simplicity, I'd say we use the Android one (which is the one on the detail view page), which is the one we had in the mockups and in Zeplin.

All the icons should be black with an opacity of .5. Header text should be black with an opacity of .6.

image 2018-11-03 at 5 31 46 pm

Search Bar Style

Mockup on left, real app screenshot on right. Looks like the search bar corners aren't perfectly round and the bar itself seems too tall.

image 2018-11-03 at 5 55 47 pm

Add to F-Droid

Now that this app is free as in freedom, it would be lovely to have it distributed through F-Droid.

documentation - "getting started" doesn't seem to "just work"

I try to follow the steps in getting started which are

git clone https://github.com/2d-inc/timeline.git
cd timeline/app
flutter run

when i use these steps i get an error as below

flutter run
Running "flutter packages get" in app...                         
Could not find a file named "pubspec.yaml" in "/Users/neil/timeline/dependencies/Flare-Flutter".
 
pub get failed (66)

Few cleanups to be done

  • Updating flare dependency in pubspec.yaml
  • Updating nima dependency in pubspec.yaml
  • Updating all int values to double to prevent this error -> error: The argument type 'int' can't be assigned to the parameter type 'double'.
  • Adding import Future to prevent this error -> error: Undefined class 'Future'. (undefined_class at [timeline] lib\main_menu\menu_data.dart:86)

[nit] The main menu is a hybrid between drawer and separate screen

On Android, at least, a hamburger icon at top left signifies a drawer. Drawers usually don't cover the whole width of the screen, ale let the user come back to previous position in the underlying "main" screen.

We should choose one way and stick to it:

  • Either we have a main menu. In that case, we should change the icon to something else. We should make it clear that going to the main menu screen will prevent you from getting back to the previous position in the timeline.
  • Or we have a drawer. The drawer can stop all animation (and blur) the underlying timeline for performance reasons. But it needs to cover the timeline only partially, so it's easy to swipe it left, or click onto the part of the screen where the drawer isn't. Now it's easy to go back to previous position in the timeline. And we can keep the hamburger icon. But it's also more work.

Unable to open it

Is this complete app..because I'm unable to run it in my Android Studio... is there any other file we have to download...
Please someone guide me how to do it properly

Improve scrolling behavior on the main menu screen

On Android, there are two problems with the main menu:

  1. The scroll container is narrower than the screen, so that the blue overscroll animation looks weird (it should cover the whole width of the screen).
  2. There should be more padding between the top of the screen and the subtitle ("Flutter Presents"), if we choose to keep it.

Gif:
screencapture-1541253036713 2018-11-03 14_58_51

App lags (and sometimes crashes) on Route from Timeline to Artice screen

Hi!

I think I found a bug in the app.

You can reproduce it as follow:

  1. Start app (I'm using iPhone Xr ios emulator)
  2. Go to "Animals" and find "Mammals"
  3. Zoom the "Mammals" so that Year 210M is at top and 186 M at bottom of screen. (Mammals in the middle)
  4. Click on Tap on Mammals

This route to article page is veery laggy and sometimes even the whole app crashes without any messages in the console. (You can see it here: bug video on WeTransfer)

App Exits Randomly

I've seen this happen after hot reloading quite a few times in a development session.

I'm not sure if it is related to a memory leak, but it sort of looks like a memory issue. No errors reported, I haven't profiled for it yet either but I saw it enough times today that I wanted to make sure we are tracking it.

It would be really good to get people testing the release build.

Hard freeze on scroll

On Android, in Profile mode:

  1. Open app
  2. Search for "world"
  3. Click on World War II

The app switches to the timeline, scrolls down fast, then stops at around 1724 A.D. and stops responding. Looks like an infinite loop in the main Flutter/Dart isolate.

There is no console output, as far as I can tell.

Gif:
screencapture-1541255131925 2018-11-03 15_32_04

Error running Gradle

I ran the commands in the readme below but came across an error with running Gradle.
Startup commands:

git clone https://github.com/2d-inc/HistoryOfEverything.git
cd HistoryOfEverything/app
git submodule init
git submodule update
flutter run

Error:
Launching lib/main.dart on SM G935P in debug mode...
Initializing gradle... 1.7s
Resolving dependencies...

  • Error running Gradle:
    ProcessException: Process "/Users/sagardesai/Documents/Personal/Repos/HistoryOfEverything/app/android/gradlew" exited abnormally:

FAILURE: Build failed with an exception.

  • Where:
    Build file '/Users/sagardesai/Documents/Personal/Repos/HistoryOfEverything/app/android/app/build.gradle' line: 53

  • What went wrong:
    A problem occurred evaluating project ':app'.

path may not be null or empty string. path='null'

  • Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

  • Get more help at https://help.gradle.org

BUILD FAILED in 1s
Command: /Users/sagardesai/Documents/Personal/Repos/HistoryOfEverything/app/android/gradlew app:properties

Please review your Gradle project setup in the android/ folder.

Any idea what could be going on?

Feature issue about timeline plugin

I loved your app. I would like to use this timeline in an application, would it be possible to set up an external plugin to implement this timeline, which will avoid modifying and revising these thousands of lines of code.

PS: I tested a lot of other timeline plugin, I admit that side design, ergonomics and customization, yours is by far the best.

How do i resolve this error?

Logs:
error: Invalid override. The type of 'AmeliaController.initialize' ('(FlutterActorArtboard) → void') isn't a subtype of 'FlareInteractionController.initialize' ('(dynamic) → void'). (strong_mode_invalid_method_override at [timeline] lib\article\controllers\amelia_controller.dart:24)

Deal with flicker on home screen

When opening the app, the Life on Earth and Common Era animations flicker.

Gif:
screencapture-1541253899242 2018-11-03 15_07_21

Maybe just delay the appearance of the animation until it's properly loaded.

Add Licence

What is the licence for this? MIT would be great. Thanks

How to add more events?

How are we supposed to add more events? As far as I've reach, I made a Nima animation and exported it as generic binary and loaded it in assets dir. Then I added an entry in timeline.json with it's path but it doesn't load it. Am I doing sth wrong?

flutter has exited unexpectedly

I had installed the flutter SDK, when I execute the following command

git clone https://github.com/2d-inc/HistoryOfEverything.git
cd HistoryOfEverything/app
git submodule init
git submodule update
flutter run

There is something wrong as follow:

bogon:app mq$ flutter run
Running "flutter packages get" in app... 7.0s
Launching lib/main.dart on ALP AL00 in debug mode...
Initializing gradle... ⢿
Oops; flutter has exited unexpectedly.

Sending crash report to Google.
Failed to send crash report due to a network error: SocketException: OS Error: Operation timed out, errno = 60, address =
clients2.google.com, port = 51139
Crash report written to /Users/mq/flutter/demo/HistoryOfEverything/app/flutter_01.log;
please let us know at https://github.com/flutter/flutter/issues.
bogon:app mq$

And my network is well ,What is wrong ? help me ,thanks

Timeline Ticks Precision

As you zoom out and bigger jumps are displayed, don't show decimal points. E.g. -4B, -3B, -2B, etc.

As you zoom in and more precision is required, show decimal points. E.g. -4.9B, -4.8B, -4.7B, -4.6B, etc.

NoSuchMethodError >

dependencies:
flutter:
sdk: flutter
// nima:
// path: ../dependencies/Nima-Flutter
// flare:
// path: ../dependencies/Flare-Flutter
nima: ^1.0.2
flare_flutter: ^1.2.0

I/flutter (12646): Another exception was thrown: NoSuchMethodError: The method '>' was called on null.

Back Edge Swipe

Can we use an edge swipe gesture to go back? It would be nice if we could do this sort of parallax effect too, where the back layer slides as the forward layer is sliding. Would be nice to do this when we're going forward into the detail views from the timeline as well.

back_swipe

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.