Giter Site home page Giter Site logo

jakezatecky / d3-funnel Goto Github PK

View Code? Open in Web Editor NEW
329.0 17.0 97.0 1.67 MB

A JavaScript library for rendering funnel charts using the D3.js framework.

Home Page: http://jakezatecky.github.io/d3-funnel/

License: MIT License

JavaScript 99.79% Shell 0.21%
javascript chart visualization d3

d3-funnel's Introduction

d3-funnel

npm Build Status GitHub license

d3-funnel is an extensible, open-source JavaScript library for rendering funnel charts using the D3.js library.

d3-funnel is focused on providing practical and visually appealing funnels through a variety of customization options. Check out the examples page to get a showcasing of the several possible options.

Installation

Install this library via npm, yarn, pnpm, or your preferred package manager:

npm install d3-funnel --save

You can then load this library into your app using import:

import D3Funnel from 'd3-funnel';

Usage

To use this library, you must create a container element and instantiate a new funnel chart. By default, the chart will assume the width and height of the parent container:

<div id="funnel"></div>

<script>
    const data = [
        { label: 'Inquiries', value: 5000 },
        { label: 'Applicants', value: 2500 },
        { label: 'Admits', value: 500 },
        { label: 'Deposits', value: 200 },
    ];
    const options = {
        block: {
            dynamicHeight: true,
            minHeight: 15,
        },
    };

    const chart = new D3Funnel('#funnel');
    chart.draw(data, options);
</script>

Options

Option Description Type Default
chart.width The width of the chart in pixels or a percentage. mixed Container's width
chart.height The height of the chart in pixels or a percentage. mixed Container's height
chart.bottomWidth The percent of total width the bottom should be. number 1 / 3
chart.bottomPinch How many blocks to pinch on the bottom to create a funnel "neck". number 0
chart.inverted Whether the funnel direction is inverted (like a pyramid). bool false
chart.animate The load animation speed in milliseconds. number 0 (disabled)
chart.curve.enabled Whether the funnel is curved. bool false
chart.curve.height The curvature amount. number 20
chart.totalCount Override the total count used in ratio calculations. number null
block.dynamicHeight Whether the block heights are proportional to their weight. bool false
block.dynamicSlope Whether the block widths are proportional to their value decrease. bool false
block.barOverlay Whether the blocks have bar chart overlays proportional to its weight. bool false
block.fill.scale The background color scale as an array or function. mixed d3.schemeCategory10
block.fill.type Either 'solid' or 'gradient'. string 'solid'
block.minHeight The minimum pixel height of a block. number 0
block.highlight Whether the blocks are highlighted on hover. bool false
label.enabled Whether the block labels should be displayed. bool true
label.fontFamily Any valid font family for the labels. string null
label.fontSize Any valid font size for the labels. string '14px'
label.fill Any valid hex color for the label color. string '#fff'
label.format Either function(label, value) or a format string. See below. mixed '{l}: {f}'
tooltip.enabled Whether tooltips should be enabled on hover. bool false
tooltip.format Either function(label, value) or a format string. See below. mixed '{l}: {f}'
events.click.block Callback function(data) for when a block is clicked. function null

Label/Tooltip Format

The option label.format can either be a function or a string. The following keys will be substituted by the string formatter:

Key Description
'{l}' The block's supplied label.
'{v}' The block's raw value.
'{f}' The block's formatted value.

Event Data

Block-based events are passed a data object containing the following elements:

Key Type Description
index number The index of the block.
node object The DOM node of the block.
value number The numerical value.
fill string The background color.
label.raw string The unformatted label.
label.formatted string The result of options.label.format.
label.color string The label color.

Example:

{
    index: 0,
    node: { ... },
    value: 150,
    fill: '#c33',
    label: {
        raw: 'Visitors',
        formatted: 'Visitors: 150',
        color: '#fff',
    },
},

Overriding Defaults

You may wish to override the default chart options. For example, you may wish for every funnel to have proportional heights. To do this, simply modify the D3Funnel.defaults property:

D3Funnel.defaults.block.dynamicHeight = true;

Should you wish to override multiple properties at a time, you may consider using lodash's _.merge or jQuery's $.extend:

D3Funnel.defaults = _.merge(D3Funnel.defaults, {
    block: {
        dynamicHeight: true,
        fill: {
            type: 'gradient',
        },
    },
    label: {
        format: '{l}: ${f}',
    },
});

Advanced Data

In the examples above, both label and value were just to describe a block within the funnel. A complete listing of the available options is included below:

Option Type Description Example
label mixed Required. The label to associate with the block. 'Students'
value number Required. The value (or count) to associate with the block. 500
backgroundColor string A row-level override for block.fill.scale. Hex only. '#008080'
formattedValue mixed A row-level override for label.format. 'USD: $150'
hideLabel bool Whether to hide the formatted label for this block. true
labelColor string A row-level override for label.fill. Hex only. '#333'

API

Additional methods beyond draw() are accessible after instantiating the chart:

Method Description
destroy() Removes the funnel and its events from the DOM.

License

MIT license.

d3-funnel's People

Contributors

arfon avatar dependabot-preview[bot] avatar dependabot[bot] avatar freak3dot avatar greenkeeper[bot] avatar jakezatecky avatar jonathanmv 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

d3-funnel's Issues

README example code are buggy

Hi! Today i seen next bug.

When i call draw function in next code:

var data = [
    ["Plants",     5000],
    ["Flowers",    2500],
    ["Perennials", 200],
    ["Roses",      50]
];

var chart = new D3Funnel("#funnel");
chart.draw(data);

I have next js error:

Uncaught TypeError: undefined is not a function d3-funnel.js?body=1:308
D3Funnel._makePaths d3-funnel.js?body=1:308
D3Funnel.draw d3-funnel.js?body=1:95

Error occurs in this line:

count = this.data[i][1].replace(/\,/g, "")

Then i use string instead int type it works.
i.e.

var data = [
    ["Plants",     "5000"],
    ["Flowers",    "2500"],
    ["Perennials", "200"],
    ["Roses",      "50"]
];

Versions:

jquery - 1.11.1
d3 - 3.5.2

Percentage width/height and horizontal/vertical alignment

I am suggesting adding an option to specify the width and height as percentage (e.g. 50%) which would be good for responsive design. This could be achieved either via new options or using the current width and height by providing strings such as "50%".

A good feature to go with it is the ability to align the chart horizontally and vertically for both pixel and percentage-based dimension such as:

  • hAlign: right|center|left.
  • vAlign: top|center|bottom.

Support D3 4.x

D3 4.x is out, but includes a variety of backwards-incompatible changes. Will still need to support 3.x for a while.

Gradient background does not persist on hover

When block.fill.type and block.highlight are set to 'gradient' and true respectively, any block that is highlighted on hover reverts back to a singular shade of color, rather than the gradient.

Problems with isInverted when sorted in reverse order and dynamic Area

This excellent d3 addon seems perfect for a need I have to do a simple pyramid. However, I need the biggest at bottom and going up in decreasing order with dynamic area such that the top is a triangle.
When I do that it seems to miscalculate areas and ends up with NaN in the path (from the calculation of bottomBase for last (now highest) data point.
I tried to understand why but could.
This is the options and the sort I add to the basic example on usage page:
var options = { bottomWidth: 0, isInverted:true, dynamicArea:true };

    data.sort(function (a, b) { return a[1] - b[1]; });

Why do you use jquery in examples instead of D3 itself?

This library is powered by d3js but jquery is used in examples while d3js can be used instead of d3js in most situations specially examples of this library. Using a lot of different libraries in projects would slow down the clients and even local servers.
Please explain why do you use jquery?

Refactor library

The source file is in need of a major overhaul. Its design makes several of the methods very long, hard to follow, and hard to add in new components. Need to modularize where we can, slim down methods, and make the order much easier to follow.

Add label positioning

Sometimes it may be desired that labels are positioned outside of the trapezoids, especially if the text will overflow. We should have an option to allow the labels be placed within the funnel or outside of the funnel (say, to the right). This would ultimately leave less real estate for the actual funnel itself and would require calculations on the text width.

Fix npm main file

The current package.json points main to ./src/d3-funnel/d3-funnel.js, when it should point to the UMD-exported ./dist/d3-funnel.js.

Gradient definition can conflict with other definitions

The linearGradient definition used for gradient definitions always produces definitions with ID's of gradient-{index}. If more than one funnel chart is in use, then there will be duplicate ID definitions and the first definition will be used. If the colors between two funnel charts differ, then this leads to the colors of the first chart affecting any other chart.

Since ID's must be used for linearGradient definitions, the following tasks should be achieved:

  • Use d3-funnel ID prefix to avoid global namespace conflict
  • Make each funnel instance avoid ID conflicts with each other

Pinched blocks do not have the same width as bottomWidth

When bottomPinch is non-trivial, the pinched blocks have a larger width than that specified in bottomWidth. This is because the initial slope calculation assumes we are using the entire funnel height, when we should subtract the height of those pinched blocks to sharpen the slope.

Funnel Width Function of Value

Is it possible to configure the chart such that the width of a block if a function of the value for that block, such that the following would give an hour glass appearance:
var data = [ ['Plants', 5000], ['Flowers', 200], ['Perennials', 200], ['Roses', 5000] ];

Exclusively use ES6 import/export

The lack of export makes it difficult to test classes and makes the code less pure. This will involve some backwards-incompatible installation, but is preferable to maintaining the current model.

.editorconfig

Hi,

it would be nice if you added an .editorconfig to the project, otherwise it's hard not to overwrite the settings you prefer.

Regards
Stefan

Allow closed range interval in bottomWidth

Currently, the chart only produces meaningful results if bottomWidth is part of the open interval (0, 1). It definitely makes sense to be at least right closed (0, 1], given that this will just produce a bunch of rectangles. It probably also makes sense to be left closed [0, 1) such that we have a triangle produced.

Minimum Height of Level (prevent text overflow)

When dynamicArea is set to true, some levels can be so small that the labels overflow above them. I am going to look at setting a minimum height, have you looked into this before or do you want to wait for a pull request?

Add support for formatted labels

I am thinking of adding a pull-request to allow formatted values to be displayed. So in my solution you can do either

var data = [
    ["Teal",      12000, "#008080"],
    ["Byzantium", 4000,  "#702963"],
    ["Persimmon", 2500,  "#ff634d"],
    ["Azure",     1500,  "#007fff"]
];

or

var data = [
    ["Teal",      [12000, 'EUR 12,000'], "#008080"],
    ["Byzantium", [4000, 'EUR 4,000'],  "#702963"],
    ["Persimmon", [2500, 'EUR 2,500'],  "#ff634d"],
    ["Azure",     [1500, 'EUR 1,500'],  "#007fff"]
];

Does this sound good for you?

Regards
Stefan

D3 v4.0

Release 4.0 is eventually coming and will support arrow functions a bit more sanely.

Add tooltips

May also provide weak HTML support. Possibly use d3-tip.

Upgrade to Babel 6

Babel 6 is out. Configuration needs to be modified and need to upgrade gulp-babel.

Wrong height proportions.

I noticed that height proportions are wrong when using dynamic Height with data with multiple same values. I assume it is because block height is calculated using block area. I think it is wrong. For example. Top 2 block values are 20 or whatever. Despite the same values, area will differ because bottom block is wider and it leads to bigger area and different height.
Wouldn't it be better if block height would be calculated based on block value and overall chart height? I modified the plugin and it seems to calculate height of the block better. There are few problems when value is 0 or calculated height is below minHeight but that can be fixed.

Responsive Width

I'm currently using this setup to make the chart responsive onload:

var data = [
    [ "Clicked", "5,000" ],
    [ "Joined", "2,500" ],
    [ "Took Action", "200" ],
    [ "Shared", "50" ]
];

width = $('#funnelPanel').width();

var options = {
    width : width - 30,
    height : 400,
    bottomWidth : 1/3,
    bottomPinch : 0,      // How many sections to pinch
    isCurved : false,     // Whether the funnel is curved
    curveHeight : 20,     // The curvature amount
    fillType : "solid",   // Either "solid" or "gradient"
    isInverted : true,   // Whether the funnel is inverted
    hoverEffects : true  // Whether the funnel has effects on hover
};

$( "#funnelContainer" ).css( "width", width);

var funnel = new D3Funnel ( data, options );
funnel.draw ( "#funnelContainer" );

I would love to, however, be able to do something like:

var options = {
    width : "100%",
    height : "100%"
};

and have the chart responsive as I change the width.

How do I do this?

Pass DOM node to event data

Often, it would be useful to directly access the node associated with an event. We should pass the node in the data object.

Allow for custom coloring

Allow custom colors to be assigned along with the data values. Handle both hex and RGB values. Potentially also allow for gradient strength to be set.

Improve min height calculation

Currently, the minimum height calculation allocates the minimum height for each section, then the remaining pool is available based on the ratio of the section. This makes small sections greedy, where they allocate even more height despite getting the minimum.

A less greedy solution is the following:

  1. Have the normal pool share, but calculate from the smallest guy first and go onward (bottom to top).
  2. Calculate the required area for the section based on its ratio. If less than the minimum, use the minimum height and subtract from remaining area. Otherwise, use the ratio.
  3. Note: still need to draw from top to bottom, so the draw order is reversed from the calculation order.

Also, we can run out of room from all these small fries taking space. Need to precalculate beforehand to see if we will have a problem, and, if so, throw an exception.

Internal API cleanup

The internal API has grown over time and many methods are far too long. Key tasks:

  • Use settings object over multiple class properties
  • Simplify and offload D3Funnel.makePaths
  • Add missing tests (especially the more complex Bezier curve calculations)
  • Improve method documentation, parameters, and return types

Error on implementation

Hi,

I'm trying to implement your d3-funnel library, but I'm getting "Unexpected token =>" message from the browser for line 1 of the d3-funnel.js file.

I've tried several things already:

  • Changing order or loading
  • Changing Jquery version
  • Removing all other JS from the page

Any ideas what I'm doing wrong?

Wouter

Add chart legend

It would probably be useful to display a color-coded legend somewhere. Need to have the ability to specify the location.

Allow the specification of the block color scale

Currently, background and label foreground colors are specified through additional array members in the data array. This makes it to where a background color must be specified for a label color to be specified, but also potentially pollutes the data array in case if the caller wishes to use add any other data.

Although it's possible to allow null for any sections that we want the colors to default to, it's probably best just to have this specified through the options.

Make default options overridable

Currently, the defaults options are attached to the prototype. While this can be edited after the fact, it's probably a better idea to make the default options static and document the process of overriding the defaults.

Dynamic slope

Dynamic slope would be nice (screenshot from Kendo UI funnel-charts)
image

Change funnel orientation

Is there any way to change the funnel from a vertical view to a horizontal view?
I haven't look into the code to check how that can be done but wanted to check first to see if there is any possibility to do this.

Progress bar look for each block

Jake, thank you for a great library. I extended it slightly to show a funnel where each block looks like a bar chart. Would you be interested in merging adding this feature to d3-funnel? If so, I could tidy up the source code, add a few tests and submit a pull-request.

example

source code

screen shot 2016-03-07 at 5 07 04 pm 2

Container content not removed

Hi,

If you have any content in the funnel container it will remain after the funnel has been added. For example:

  <div id="funnel">Loading ...</div>

You can see this in the image below.

image

funnel chart not redraw when window size changed

Currently I have to redraw the funnel chart when window resize event fired, but this is not ideal because I only want to redraw the chart after container size is changed.

It would be great if the funnel chart can redraw itself after the the container size is changed.

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.