A framework for building reusable components with d3.js

Overview

Koto

A framework for creating reusable charts with D3.js, written in ES6.

Travis build status Code Climate codecov.io Dependency Status devDependency Status Join the chat at https://gitter.im/kotojs/kotojs Commitizen friendly

Introduction

KotoJS is HEAVILY inspired by another reusable charting framework maintained by the Miso Project called d3.chart. I think that project is well designed and well documented. For those who are not familiar with d3.chart, the framework provides a logical way to ensure that all data-visualization components that are authored using the framework are done in a way that facilitates re-usablily.

However, as somebody who greatly depends on the d3.chart framework, I've gotten concerned that support for the project has dwindled over the past several months. This has prompted me to write my own reusable charting framework, taking all the things the things that I really like about d3.chart and adding a few things that I had always wanted.

// Basic Example
KotoBarChart = class extends Koto {
  constructor(selection){
    // setup chart
    var bars = this.base.append('g').classed('bars', true);
    
    // define layer
    var layer = this.layer('bars', bars, {
      dataBind: function (data) {
        return this.selectAll('rect').data(data);
      },
      insert: function () {
        this.append('rect');
      }
    });
  
    // Setup life-cycle events on layers
    bars.on('enter', function () {
      // this => enter selection
    })
    .on('merge', function () {
      // this => base selection
    })
    .on('exit', function () {
      // this => exit selection
    });
  }
  preDraw(data) {
    // [Optional] Do something before draw
  }
}

var barChart = new KotoBarChart(d3.select('#vis'));
barChart.draw(data);

How is it different than d3.chart?

ES6 (ECMAScript 2015)

For starters, this entire framework is written in ES6 (ECMAScript 2015). This allows us to use classes as the base structure for widgets and use the syntatic sugar for authoring classes that has added in the latest version of the language commonly called JavaScript. This framework also utilizes Maps and Sets (another feature recently added to JS). The library has been compiled back to ES5 (using babel) and it has listed an ES6 polyfill as a dependency so legacy browsers should be able to use it just fine.

Modules (UMD)

I'm a big believer in modules. With KotoJS, all your components are exported as a UMD (Universal Module Definition) module so that they can be integrated with several bundlers/asset managers. So, if you like using CommonJS, or AMD, or nothing at all, these widgets will work exactly like you'd expect them to. I've tested them with bundlers like RequireJS, Webpack, and Browserify so I'm confident that koto can be easily integrated into most projects.

Common API for getting and setting configurable options.

In d3.chart, it is a common practice to have each configurable option (ex. Height, Widgth, fill) to have its own getter and setter method attached to the chart. This practice is suggested by Mike Bostock (creator of D3) and generally a good thing. For my own personal use case of this framework, I need the abily to store all the configs to a single object and so I found it much easier to have a common API for getting and setting config items like so:

// Similar syntax to other d3 methods like `attr` and `style`
var barChart = new KotoBarChart(d3.select('#vis'));

barChart
  .config('height', 500)
  .config('width', 500)
  .draw(data);

// -OR-
barChart
  .config({
    width: 500,
    height: 500
  })
  .draw(data);

Common API for getting and setting accessor functions.

In an effort to make components authored with this framework truely reusable, it was important to me that widgets could take in data with a variety of schemas. I can then tell my component how to "access" the data that it needs.

// Similar syntax to other d3 methods like `attr` and `style`
var barChart = new KotoBarChart(d3.select('#vis'));

barChart
  .accessor('name', function(d) { return d.country; })
  .accessor('value', function(d) { return d.population; })
  .draw(data);

// -OR-
barChart
  .accessor({
    name: function(d) { return d.country; },
    value: function(d) { return d.population; }
  })
  .draw(data);

Extra Hooks

In d3.chart, the only "hooks" that were available for you on the chart level was initialize and transform. In KotoJS I have extended the list to include initialize, transform, preDraw, and postDraw. I have also exposed a hasDrawn property that allows for you check if something is being "re-drawn". All of the hooks are optional so you don't have to use them if you don't want to.

Removed the extension of d3

In d3.chart, the API for initalizing a chart was an extension of d3's selection prototype. I felt wrong to me to extend d3 so I have removed the need to do that and have opted to have charts authored with KotoJS to initialize like any other constructor function.

// d3.chart
var barChart = d3.select('#vis').chart('BarChart');
barChart.draw(data);

// KotoJS
var barChart = new KotoBarChart(d3.select('#vis'));
barChart.draw(data);

Getting Started

koto.js has been written in ES6 and then transpired to ES5 with babel. It uses the UMD syntax so that it can be integrated with many module/bundle loaders.

Install

You can install koto via bower by running:

$ bower install koto --save

or via npm by running:

$ npm install koto --save

Documentation

Build Instructions

Build requirements:

$ npm install
$ npm run build

Community

The goal is to have a large library of pre-built widgets using this framework open sourced and available for all to use. I'm still thinking through the details but be expecting something to be released soon. If you'd like to contribute a widget (or 2 or 42), I'd welcome the support.

Examples

If you have any example code that you would like to share, please let me know!

Acknowledgements

This project is HEAVILY inspired by the awesome work done by @jugglinmike and @iros and their charting framework called d3.chart.

Contributors

Thanks goes to these wonderful people (emoji key):


Nick Randall

💻 📖 💡 ⚠️

i alarmed alien

📖

This project follows the all-contributors specification. Contributions of any kind welcome!

Comments
  • Change config functionality

    Change config functionality

    TL;DR

    I'm thinking about changing how configs work in KotoJS. The basic functionality will remain the same but the advanced functionality would be replaced in favor of a better alternative.

    My plan

    The config method will remain very similar to d3's attr and style methods as it will be a basic getter/setter for config properties.

    chart.config('height', 500); // sets height config to 500
    chart.config('height'); // => returns config value (500)
    

    When defining the default config options for a chart, a user will be able to optionally set a few basic validation and meta-data like properties on the config object to provide consumers of the chart with support and documentation of what configs are available on a specific chart as well as what type(s) of values it is looking for. This idea is inspired by Joi.js, an excellent validation library. We probably won't use Joi directly because it's too heavy for this use case. I'm thinking that I will build a "lighter" version of this lib that internally uses some of d3's methods for validation.

    import C from 'koto-config';
    
    // set in the chart somewhere
    this._config  = {
      height: C.number().positivie().default(500).decription('the height of the chart').units('px'),
      width: C.number().positivie().default(500).decription('the height of the chart').units('px'),
      fill: C.color(),
      orientation: C.string().in(['vertical', 'horizontal']).default('vertical'),
      xScale: C.scale()
    };
    
    // later when user tries to set a config
    chart.config('height', -100); 
      // => throws error with helpful message like:
      // "the value for the `height` config for `koto-bar-chart`, decribed as "the height of the chart", was expecting a positive integer (in "px") and got -100. 
    

    Again, this would all be optional. Authors of Koto charts would still be able to setup default config values like so and the only validation that would occur when getting or setting a config value is that that particular config exists on the chart.

    this._config  = {
      height: 500,
      width: 500,
      fill: '#9ce',
      orientation: 'vertical',
      xScale: d3.scale.linear()
    };
    

    Before I make this change, I want to get some validation/feedback on the idea. If you don't like it or have a better idea, please let me know!

    enhancement help wanted idea 
    opened by nicksrandall 9
  • Add missing import

    Add missing import

    Minor omission but ended up being pretty hard to track down. For reference, the way this manifested in my project was as an undefined reference to d3 when asserting instanceof d3.selection.

    opened by ericsoco 4
  • What's the distinction between .config & .accessor

    What's the distinction between .config & .accessor

    Is there any guidance for when to use one vs the other? How to decide when one is or is not appropriate?

    e.g.

    • chart.config('height', 500) vs chart.accessor('height')(500)
    • chart.config('xScale', d3.scaleLinear) vs chart.accessor('xScale')(d3.scaleLinear)

    I thought it might have something to do with the API we're exposing to users, but a & c (along with accessors and configs) are exposed on the instance property (along with anything else assigned to this like x and xAxis) I'm don't think that's it.

    opened by jfsiii 3
  • Layer-related suggestions

    Layer-related suggestions

    I'm finding it very useful to be able to subclass the Layer class to create layers with specialised functionality that can be used by various different charts (e.g. a tooltip layer). At the moment, I'm making my own build with a slightly customised Layer object that acts as a base for the various subclasses. These alterations may be useful to others, so I thought I would mention them here, too.

    • expose the Layer constructor by default to make it easy to subclass

    • use duck-typing to identify Layer objects that are being added to a chart: I add my custom layer objects by calling

      chart.layer( 'name', new FunkyLayer( selection, layer_args ) );
      

    thus avoiding the default Layer constructor. The chart tests for selection instanceof Layer before adding the layer, which fails for custom layer objects. Locally, I've edited chart.js to test whether the layer object has dataBind and insert (the two mandatory Layer functions) defined, i.e.:

    // we are reattaching a previous layer, which the
    // selection argument is now set to.
    if (arguments.length === 2) {
    
      if (selection instanceof Layer || ( 'undefined' !== typeof selection.dataBind && 'undefined' !== typeof selection.insert ) ) {
        selection._chart = this;
        this._layers.set(name, selection);
        return this._layers.get(name);
      } else {
        kotoAssert(false, 'When reattaching a layer, the second argument must be a koto layer');
      }
    }
    
    • the dataBind function doesn't seem to have a way to access the parent layer object; this could be enabled with the following edit to Layer.draw:

    old:

    bound = this.dataBind.call(this._base, data);
    

    new:

    bound = this.dataBind.call(this._base, data, this);
    

    (note the this argument has been added)

    idea 
    opened by ialarmedalien 3
  • Support D3 v4

    Support D3 v4

    Master currently fails with Error: [koto] d3 js is required. if a global d3 isn't present. This blocks devs who don't import d3 from "d3" and only import any of the many small modules they need.

    As far as I can tell, Koto only needs d3-selection.

    d3-selection.v1.min.js is ~13KB (5KB gzipped) and [email protected]/dist/koto.js is ~10KB (3.5KB gzipped). Supporting d3 v4 means a user could have Koto for under 10KB gzipped.

    Even if the size savings isn't compelling, it's important for Koto to support those who don't import d3 from "d3" in their project/page.

    opened by jfsiii 2
  • Examples don't work in IE11, Firefox or Safari

    Examples don't work in IE11, Firefox or Safari

    Hi,

    I really like the idea of Koto and am looking into it in more detail. I noticed that the 2 examples only work under Chrome - Firefox, Safari and IE seem to be left in the cold.

    I know Babel is a great transpiler and the solution is to use it when using KotoJS but shouldn't it be used for the samples?

    opened by emrul 2
  • Example charts

    Example charts

    Would you be able to create some sample charts / bl.ocks to demonstrate koto.js in action? It would be particularly useful to see some of the "classic" d3 charts (e.g. the bar chart from the tutorial http://mbostock.github.com/d3/tutorial/bar-2.html) re-implemented using koto.js.

    help wanted 
    opened by ialarmedalien 2
  • More examples [Stacked bar chart]

    More examples [Stacked bar chart]

    KotoJS looks great but really lacks some examples. We thought we'd try to fix it and would like to contribute the following example of a stacked bar chart (inspired from a pre-existing D3 chart)

    http://jsbin.com/nifoxohuxa/edit?js,output

    Demonstrates multiple layers, pre-draw, accessor methods and read-only config variables.

    This was a learning exercise in Koto so feedback invited - especially on any missed opportunities to improve readability or maintainability.

    opened by emrul 1
  • Fixing typos and references to d3.chart, add watch task

    Fixing typos and references to d3.chart, add watch task

    This is mostly aesthetic changes -- I replaced the references to d3.chart with koto and fixed some typos, including the calculatePercentage function name. I also added a watch task to package.json that I use for development -- you can take it or leave it as you see fit.

    opened by ialarmedalien 1
  • Add a Gitter chat badge to README.md

    Add a Gitter chat badge to README.md

    kotojs/kotojs now has a Chat Room on Gitter

    @nicksrandall has just created a chat room. You can visit it here: https://gitter.im/kotojs/kotojs.

    This pull-request adds this badge to your README.md:

    Gitter

    If my aim is a little off, please let me know.

    Happy chatting.

    PS: Click here if you would prefer not to receive automatic pull-requests from Gitter in future.

    opened by gitter-badger 1
  • Koto successor

    Koto successor

    Hi there,

    A few years ago I used Koto and I just loved how elegant and clean it was.

    The project looks idle, 3 years since the last commit, and I'm sure there is a good reason for that.

    I wonder if you could advice any good alternative? I'm struggling to find anything as well-designed and modern as your micro-framework.

    Here are a few example of charts I did with Koto: https://projects.icij.org/paradise-papers/the-influencers/ https://jplusplus.github.io/okf-farmcompass/

    opened by pirhoo 0
  • D3 with plugins over Webpack

    D3 with plugins over Webpack

    Hi there,

    I'm trying to use Koto with Webpack and additional plugins for D3:

    // Use the CommonJS bundle as suggested by mbostock 
    // @see https://github.com/d3/d3-selection-multi/issues/15#issuecomment-294917716
    import * as d3 from 'd3/build/d3.node';
    // Extend D3 with this 2 plugins
    import 'd3-selection-multi';
    import 'd3-jetpack';
    
    export default d3;
    

    But since Koto uses its own export of D3, validation fails when returning the dataBind selection. The two instances of d3.selection are obviously not the same.

    Invalid selection defined by `Layer#dataBind` method.
    

    I see two solutions but I'll be glad to have you opinion on this. I'll be happy to submit a pull request then:

    • use D3 as an attribute of Koto, so it would be easy to override ;
    • export the Koto's D3 so I can use it within my own code.

    Cheers!

    opened by pirhoo 1
  • d3 v4 issue

    d3 v4 issue

    I took the example you provided and updated it to run on D3 v4 which produced strange effects.

    What i did:

    • edit the example http://jsbin.com/qopuwerixa/edit?js,output
    • <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.7.4/d3.js"></script>
    • <script src="https://cdnjs.cloudflare.com/ajax/libs/koto/0.4.2/koto.js"></script>
    • change this.x = d3.scale.linear()... to this.x = d3.scaleLinear()...
    • change this.y = d3.scale.linear()... to this.y = d3.scaleLinear()...
    • watch the chart being rendered in a non desired manner

    Would be nice if you could try this too and check whats wrong within the Kudo Library.

    opened by arnonuem 0
  • increase usability

    increase usability

    It would be more intuitive if the KotoChart would not have been called with a d3.select(...) in the constructor but instead with just an ID.

    That said, Koto should take this id and attach the SVG to the dom on its own.

    With the current situation i need to have an SVG tag in my html and also i need to import d3 for just giving a d3 selection into the chart.

    opened by arnonuem 0
  • A list of examples

    A list of examples

    Hi there,

    First of all, I have to say that Koto is amazing. I already knew d3.chart but the ES6 is incredibly more intuitive and your library is well designed.

    The only pitfall I met during my transition to Koto is the lack of examples. Even if the document is great it would be awesome to have more use cases. For instance, until I saw your bar chart examples, I didn't get (maybe I'm stupid) that you have to define configs options within the constructor.

    BTW I'm currently coding a chart similar to this one and I would be happy to give you the link to the repository when it's done if you think it can be helpful for other users.

    Cheers,

    Pierre

    opened by pirhoo 7
  • Add documentation to wiki on config and accessor methods

    Add documentation to wiki on config and accessor methods

    There is no documentation about using a configuration file or creating custom accessors in the wiki at the moment.

    On a semi-related note, JSON Schema might be useful for creating and interpreting chart configuration objects. There is also a nice ES6 library for creating mixins, mixwith -- maybe the ability to use a config file could be applied with a mixin that could intelligently apply the appropriate functions to a chart, given a config file? The plot.ly library does just about everything with JSON configs. This is something I'm actively exploring at the moment so it would be useful to know what you're planning. Thanks!

    documentation 
    opened by ialarmedalien 3
Owner
KotoJS
A reusable charting framework.
KotoJS
A reusable charting library written in d3.js

NVD3 - A reusable D3 charting library Inspired by the work of Mike Bostock's Towards Reusable Charts, and supported by a combined effort of Novus and

Novus 7.2k Jan 3, 2023
:bar_chart: A D3-based reusable chart library

c3 c3 is a D3-based reusable chart library that enables deeper integration of charts into web applications. Follow the link for more information: http

C3.js 9.2k Jan 2, 2023
A friendly reusable charts DSL for D3

D4 D4 is a friendly charting DSL for D3. The goal of D4 is to allow developers to quickly build data-driven charts with little knowledge of the intern

Mark Daggett 429 Dec 5, 2022
Reusable JavaScript library for creating sketchy/hand-drawn styled charts in the browser.

roughViz.js is a reusable JavaScript library for creating sketchy/hand-drawn styled charts in the browser, based on D3v5, roughjs, and handy. Why? Use

Jared Wilber 6.4k Jan 4, 2023
Easy-to-use js library for building graphs using svg.

LineChart Easy-to-use js library for building graphs using svg. Examples How to use Just add linechart.js from 'src' directory to your project. And ad

Korpusov Maxim 8 Nov 21, 2022
Data Visualization Components

react-vis | Demos | Docs A COMPOSABLE VISUALIZATION SYSTEM Overview A collection of react components to render common data visualization charts, such

Uber Open Source 8.4k Jan 2, 2023
:bar_chart: A library of modular chart components built on D3

Plottable Plottable is a library of chart components for creating flexible, custom charts for websites. It is built on top of D3.js and provides highe

Palantir Technologies 2.9k Dec 31, 2022
Matteo Bruni 4.7k Jan 4, 2023
Free Bootstrap 5 Admin and Dashboard Template that comes with all essential dashboard components, elements, charts, graph and application pages. Download now for free and use with personal or commercial projects.

PlainAdmin - Free Bootstrap 5 Dashboard Template PlainAdmin is a free and open-source Bootstrap 5 admin and dashboard template that comes with - all e

PlainAdmin 238 Dec 31, 2022
React components for Chart.js, the most popular charting library

react-chartjs-2 React components for Chart.js, the most popular charting library. Supports Chart.js v3 and v2. Quickstart • Docs • Slack • Stack Overf

null 5.6k Jan 4, 2023
Synchro Charts is a front-end component library that provides a collection of components to visualize time-series data.

Synchro Charts Synchro Charts is a front-end component library that provides a collection of components to visualize time-series data. You can learn m

Amazon Web Services - Labs 60 Dec 29, 2022
Babylon.js is a powerful, beautiful, simple, and open game and rendering engine packed into a friendly JavaScript framework.

Babylon.js Getting started? Play directly with the Babylon.js API using our playground. It also contains a lot of samples to learn how to use it. Any

Babylon.js 19.1k Jan 4, 2023
Highcharts JS, the JavaScript charting framework

Highcharts JS is a JavaScript charting library based on SVG, with fallbacks to VML and canvas for old browsers. Official website: www.highcharts.com D

Highsoft 10.9k Jan 9, 2023
:bar_chart: Declarative Charting Framework for Angular

ngx-charts Declarative Charting Framework for Angular! ngx-charts is unique because we don't merely wrap d3, nor any other chart engine for that matte

Swimlane 4.2k Dec 27, 2022
A data visualization framework combining React & D3

Semiotic is a data visualization framework combining React & D3 Interactive Documentation API Docs on the wiki Examples Installation npm i semiotic E

nteract 2.3k Dec 29, 2022
Konva.js is an HTML5 Canvas JavaScript framework that extends the 2d context by enabling canvas interactivity for desktop and mobile applications.

Konva Konva is an HTML5 Canvas JavaScript framework that enables high performance animations, transitions, node nesting, layering, filtering, caching,

konva 8.7k Jan 8, 2023
🌀 The Javacript framework for creating a portal to your data. Perfect for a single dataset or a full catalog.

?? Portal.JS The javascript framework for data portals ?? portal is a framework for rapidly building rich data portal frontends using a modern fronten

Datopian 2k Dec 30, 2022
A simple and minimal, ultra-lightweight vanilla JS framework with 0 deps.

piss.js A simple and minimal, ultra-lightweight vanilla JS framework with 0 deps, containing one function, piss. This function has the background colo

grian 15 Oct 21, 2022
An All-in-one Visualization Framework for TiddlyWiki5 based on ECharts

ECharts for TiddlyWiki5 When I first started using TiddlyWiki a long time ago, I wanted TiddlyWiki to be able to visualize data. I wanted to generate

Tiddly Gittly 31 Dec 30, 2022