Code Monkey home page Code Monkey logo

paths-js's Introduction

Paths.js

Build Status

Paths.js is a library to generate SVG paths, allowing you to create your own charts using a functional and testable API. It provides the primitives to create various shapes and charts starting from raw data, but it does not prescribe how you render these charts. This means you can use Paths.js to build components for your favorite frontend framework, and works even server-side on NodeJS.

Paths.js offers three APIs, of increasing abstraction. The lowest level is a chainable API to generate an arbitrary SVG path. On top of this, paths for simple geometric shapes such as polygons or circle sectors are defined. At the highest level, there is an API to generate some simple graphs (pie, line chart, radar...) for a collection of data, assembling the simple shapes.

Latest version is 0.4.6 - see this for the necessary changes from 0.3.5.

Table of contents

Demos

Of course, when judging a chart library, the first request is to have a look at results. But Paths.js is different: it provides the geometry, and you draw the charts.

That said, we have two demos. The first one is written using React (source here).

The old demo is written using Ractive (source here).

Philosophy

Drawing beautiful charts is a craft, and often one needs to add custom interactions, styling or animations. There are some beautiful chart libraries out there, such as Flotcharts or Dimple, and if those are enough for your needs, they can be a pleasure to use.

In many cases, though, what I really wanted was a library to take care of the generation of the chart, while still leaving me the possibility to render the actual thing. Paths.js does exactly this. It eventually generates SVG paths with a high level API. These paths can be then used together with a template engine such as Mustache or Handlebars to display SVG graphics in the browser. If instead of a static template engine, you use a data binding library, such as Facebook React, Ractive.js or Angular, you get animated graphics for free.

In designing Paths.js, I have tried to follow a few principles:

  • paths should be immutable
  • all exposed methods should be pure
  • from this follows that it is trivial to test components
  • and that they work on Node.js as well
  • it should be easy to integrate Paths.js into various frameworks

Documentation

A detailed documentation is available on the wiki. Here are links to the main entry points.

Paths.js offers three APIs, of increasing abstraction. The lowest level is a chainable API to generate an arbitrary SVG path. On top of this, paths for simple geometric shapes such as polygons or circle sectors are defined. At the highest level, there is an API to generate some simple graphs (pie, line chart, radar...) for a collection of data, assembling the simple shapes.

Those users who prefer explicit typed interfaces can browse the API of the Scala.js bindings.

Resources

These resources give a more detailed exposition of the philosophy behind Paths.js:

Browser support

Paths.js works in any environment that supports a modern version of Javascript, namely ES5. This includes any version of Node.js and all recent browsers. If you need support for older browsers, you can include an ES5 polyfill.

On the other hand, not every browser will be able to display the SVG graphics that you will generate. Usually, recent desktop browsers are ok, but mobile browser are slow in adopting the SVG specification. You can refer to caniuse for more detailed information.

Migration to 0.4

Version 0.4 was rewritten in ES6 instead of CoffeeScript for future-proofing. The currently published version is 0.4.0.

A few API changes were introduced, namely all keys are now camel cased.

In particular:

  • in the low-level verbose API, large_arc_flag has been renamed to largeArcFlag, and sweep_flag to sweepFlag
  • the rectangle width in the Sankey diagram, is now called rectWidth instead of rect_width

Also, the default for the gutter parameter is now 10 everywhere (that is, also in the Bar and Waterfall charts).

Everything else should be the same, so if you find any regression, please open a issue.

Using Paths.js with the Canvas API

Paths.js does not directly support the canvas element, essentially because there is no need to do so. The canvg project allows to draw SVG paths on a <canvas> element, and it seems that canvas will be able to support SVG paths natively. Of course, canvas-based solutions limit the possibilities offered by data binding libraries for interaction, but they could be used as a fallback on less recent browsers.

Using Paths.js with Scala.js

It is possible to use Paths.js with Scala.js - this library defines the bindings.

Contributing

Contributions to Paths.js are always welcome! See this wiki page for suggestions and guidelines.

paths-js's People

Contributors

andreaferretti avatar bryhoyt avatar gregerg avatar lvl9lightspell avatar nhunzaker avatar o-klp avatar paulomoreno avatar pazqo avatar tp avatar vabite avatar wykhuh avatar yowzadave 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

paths-js's Issues

Circular arc command as part of low level api?

Hey @andreaferretti, I think it would be really nice if users could define a circular arc with a slightly simplified api:

.arcCircular(xCenter, yCenter, r, sAngle, eAngle, counterclockwise)

This api mirrors the canvas arc api and I think it is a lot more straightforward for this particular use case.
http://www.w3schools.com/tags/canvas_arc.asp

What do you think?

I'd be happy to try to implement it myself, but am a little confused as to whether I should be modifying the path.coffee file or the one under the node dir?

Thanks for the great library!

Pie-chart with only one slice

path-js works great, most of the time, for me. But when I end up with data for only one slice (i.e. 100% of the data), the slice is not drawn.

If I set a stroke color I can see that only the line from center to perimeter (radius) is drawn. Is there any properties I have forgot to set? Otherwise it seems like some kind of bug where a full circle (360 degrees) become a null circle (0 degrees).

zero value graph throwing error

This is in reference to this issue with react-native-pathjs-charts.

For I've only tested the example Bar chart but was able to trace it back to the Bar object from the paths-js library.

The example Bar chart located here. The values in the data array were all changed to 0, resulting in a similar error to the one provided in the issue above.

allow more than 2 accessors, for instance for Bubble charts

Hi Andrea,
how about allowing to have a third accessor? like zaccessor, so when we do line.path.points(), we have arrays of 3 coordinates (x,y and z) and z can be assigned to the r parameter, so from a scatter plot charts we can also do bubble charts?

or change accessors to be an object, so it can be extended to more than 2 accessors? but i can guess that would be a breaking change.
Cheers

Specify a starting point for Bar charts

What would be the best way to offset the bar chart before printing it?

var offset = 100;

var chart = Bar({
	data: [...],
	width: 400,
	height: 400,
	// --> offset: [100, 100]
});

chart.curves.forEach( function(curve, index) {
	console.log( curve.line.path.print() )
});

// The log outputs something like this
// M 46 84...
// M 93 56...

// but what I need is the offset (100) added to M:
// M 146 184...
// M 193 156...

I used center for Pie charts which seemed to work fine but I'm not sure how this would be done with Bar.

[Questions] polyfill and SVG generate path

I have two question:

  • What polyfills are required for this script to run? Would my minifill cover the needs for paths.js?
  • Does this script generate path for given SVG elements that don't have it? Like below?
<path d="M 100 100 L 300 100 L 200 300 z" fill="red" stroke="blue" stroke-width="3" />

Thanks so much.

Connect multiple paths without 'lineto' in low-level API?

Is there a way to connect multiple Paths without drawing a line between them, using the low-level API? I want to draw a hole within the bounding shape. I can do this by simply drawing the first shape, than using .moveto() to move to a different location and drawing the second path. But I can't seem to draw two separate Paths and then connect them, without the low-level API drawing a line between the shapes.

Sector not able to wrap around 0.

Hey there, I'm trying to draw a Sector (represented by the blue highlight here) with

startAngle: 2.2244817547157543
endAngle: 1.6781178149610074

in a clockwise direction. Unfortunately this is what I'm ending up with currently when passing in those angles to the command:

image

Ideally the blue highlight would loop around the whole circle, but it seems like I can't draw a sector that passes through the 0-angle right now?

Is there a way to achieve this? If not, maybe a clockwise flag could be added to allow for it?

Desired output:
image

Thank you

Path: transformations for vline and hline commands fail

Steps to reproduce:

var path = Path()
  .moveto(10, 20)
  .vlineto(30, 50)
  .hlineto(25, 28)
  .qcurveto(27, 30, 32, 27)
  .translate(10, 10)
  .closepath();

Exception:

      x: point.x * matrix[0] + point.y * matrix[2] + matrix[4],
                         ^

TypeError: Cannot read property '0' of undefined
    at C:\dev\sandbox\paths-js\dist\node\geom.js:73:26

Ability to max-width rectangles?

Heya. Firstly, rad library, I'm really enjoying it. Is there an easy way to supply a max-width for individual columns in the waterfall and bar charts? My problem is if I have only 2 data points for a waterfall, but the graph is the width of 1200px, those columns are really wide. I could reduce the size of the graph - but it's a dynamic graph that could have over 20 columns.

For example, it currently might look like this:

chart1

If i could supply it a max column width, to look like this:

chart2

Any ideas? Thanks!

Bezier curves error out on minus method

Hi there I'm using paths-js version 0.3.5 and I'm having issues with Bezier curves. Anytime I try to generate a curve either though a SmothCurve graph or directly using the Bezier function, I get an error. Here is a way to reproduce the error.

> var Bezier = require('paths-js/bezier');
undefined
> Bezier({points: [[97,219],[119.69932031054931,198.5]]})
TypeError: Cannot read property '0' of undefined
    at Object.module.exports.minus (node_modules/paths-js/ops.js:38:13)
    at module.exports.reflect (node_modules/paths-js/bezier.js:14:14)
    at node_modules/paths-js/bezier.js:27:41
> Bezier({points: [[0,0],[1,1]]})
TypeError: Cannot read property '0' of undefined
  [snip]

As you can see, even the simple example going from (0,0) to (1,1) errors out. Is there something I'm doing wrong here?

Change build step to avoid including almond.js

It seems that the global build using require.js and concatenating almond.js at the beginning creates incompatibilities with other libraries.

For instance the following gives an error in the console and fails to load Ractive globally

<!doctype html>
<html>
  <head>
    <title>Pathjs</title>  </head>
  <body>
    <script src='js/paths.js'></script>
    <script src='js/Ractive.js'></script>
  </body>
</html>

athough inverting the order of dependencies does work

No working examples

The documentation could really use some minimal working code snippets. How do you convert the Path() object into an actual svg element?

Edit: never mind, I just somehow scrolled past that part of the docs. Still, it would be nice to emphasize it more (e.g. with a "Getting started" header).

Forced Directed Graph

I was wondering the "dual tree" described in this video can be achieved with paths-js? The challenge I believe in this graph is the placement of various nodes (person) to represent a tree. Is the Forced Directed Graph aimed for this type of drawing?

Support for Typescript typings

This library doesn't have support for Typescript's type definitions, right?

Is it planned to add those?

I don't see any community-provided typings on DefinitelyTyped

Pass offsets to bar graph constructor

I want to pass offsets to the bar graph constructor (xOffset for placing Y-axis, yOffset for placing text on top of the bar), but don't see anything in bar.coffee for doing so.

Vuejs

Hi, i'm wondering if you're thought about porting to Vue.js.

  • very similar to Ractive.
  • well supported, low issue count.
  • very popular:
    • Vuejs: 28,000+ stars on github
    • Ractive: around 5,000
    • Angular: around 16,000
    • React: around 49,000

Dave

How can we use this library on server side (Node JS)?

I do have a requirement of sending an email based on a template (using handlebars) which should show a chart in it. I am planning to use Path.js as the main README says that I can use this library on server side too. But I am clueless about how can I use it on server side. Can you provide some guidance or route to get it done?

StockCurve[A].item returns a collection of items

So, according to the documentation, Stock.curves returns a collection of curves, "each having the properties line, area, item and index. [...] Under item one finds the original element in the data."

The problem is that this implies that each curve is associated with a singular item, despite the fact that the curve is dependent on a series of items. This is formalized in the explicitly typed scala.js documentation. Where the type of StockCurve[A].item is A rather than Array[A]

This is inspite of the fact the .item actually returns an array, leading to a runtime error when treating item like an A.

Horizontal bar support?

Would you support horizontal bar chart? This chart is good for anything related to progress tracking.

Stock API calculates NaN with y points of same value

The Stock API calculates NaN for the line.centroid[1]

I pass in the following to pathsjs.Stock({
data: [
{
"date": new Date("2015-01-09T07:00:00.000Z"),
"netPay": 200.45
},
{
"date": new Date("2015-01-23T07:00:00.000Z"),
"netPay": 200.45
},
{
"date": new Date("2015-02-06T07:00:00.000Z"),
"netPay": 200.45
},
{
"date": new Date("2015-02-20T07:00:00.000Z"),
"netPay": 200.45
},
{
"date": new Date("2015-03-06T07:00:00.000Z"),
"netPay": 200.45
}
],
xaccessor: function(x) {return x.date.valueOf();},
yaccessor: function(x){x.netPay;),
width: 414,
height: 80
})

The resulting paths.curves[0].line.centroid[0] is 207 and paths.curves[0].line.centroid[0] is NaN

Graph Layout

Hi,

thanks for the awesome lib, I'm using scala version path.js. I was wondering if there is a way to put graph layout algorithms into path.js highlevel api. something like dager.js or so. I would appreciate your idea about the best way to this using path-scala-js.

thanks

Race condition at loading for paths global object

Using paths.js global version (hence without require.js) together with Ractive, it appears to happen a race condition causing a ReferenceError.

<script src='js/paths.js'></script>
<script src='js/Ractive.js'></script>
<script src='js/test.js'></script>

Then in test.js

var ractive = new Ractive({
      el: 'pie',
      template: '#myTemplate',
      data: {
          Pie: paths.Pie,
      }
...
});

causes a ReferenceError on paths in the expression paths.Pie

Tested on both Chrome and Safari.
Checking in the developer console, after loading paths appears correctly defined

Move to Babel 7

Babel changed quite a bit from 5 to 6 (babel-cli, transform-plugins-modules, just to mention a few of the changes).

We should probably find the time to upgrade the build and possibly remove browserify.

Offset for the rest of the charts.

I noticed there's an offset for Bar but not for the rest of the charts. It would be nice to have an offset for Pie, Smooth Line, etc as well.

Serverside and client side output is diffrent

Hi,

I'm trying to make React Isomorphic app with charts rendering using Paths. However there is diffrent output from calculations done by browser and server side. The only reason I can think of it is that server side and browser side are using diffrent Number bit resolution (32bit vs 64bit). React tells me about diffrence between serverside markup and browser markup.

This one is using smoothline source code from http://andreaferretti.github.io/paths-js-react-demo/

(client) 556554 C 1.2368633799195998 317.72517853
(server) 556554 C 1.2368633791238002 317.72517853

However even with simpler one (using Stock example from wiki) I have diffrent results

(client) ath d="M 0 180 L 155 200 L 300 140" fill
(server) ath d="M 0 180 L 155.00000002797069 200

Server is on IOJS 1.7.2 and Browser is Chrome 41

Maybe it would be enough to add some number rounding somewhere where you do calculations?

scaling a chart

Hi, let's say I have the following set of data:

var data = [{year: 2008, val: 7.2},
{year: 2009, val: 8.1},
{year: 2010, val: 7.7},
{year: 2011, val: 6.8},
{year: 2012, val: 6.7}]

If I use data as parameter for a Stock chart for instance, with year on the x-axis and val on the y-axis, by default when using the Stock chart, paths-js scales automatically using the maximum value of val for y.
Is there a way to use a different scale, for instance [0,15] so the values appear more in the middle of the chart instead of the top? Is there a method for it? Thx

Stock can't be used to draw step chart

The stock graph function is written in a way which prevents the drawing of a step chart.

image

I've been fiddling with drawing a step chart for the better part of the evening, and I finally found why it wouldn't render correctly.

In src/line-chart-comp.js on line 8
let sorted = points.sort(([a, b], [c, d]) => a - c)
This sorts the data by x (presumably so that if unsorted data gets passed in, it renders as expected). If I want to draw a step chart, I'm going to have to add in multiple points with the same x, which might change index after an unstable sort. As a result, the points of a step in the step chart would be connected out of order.

For example, these are the points the library generates.

  1. [0, 200]

  2. [34.1747572815534, 200]

  3. [34.1747572815534, 0]

  4. [43.49514563106796, 200]

  5. [43.49514563106796, 0]

  6. and 5. were swapped by the unstable sort. In my original data they were in the reversed position. If you chart these points you wouldn't get a step chart, but if you swapped 4. and 5., you would.

I suppose removing the sort at this point would be a breaking change, but how about adding an option?

Latest builds are broken

dist/global/paths.js is broken for the last couple of releases (at least until 0.3.3 -- didn't check earlier). Latest commit fixes the issue but there's been no release incorporating it so far. It'd be wonderful if you released a new version with the fix.

Error while using paths-js as a yarn/npm dependency

We're currently using a library that depends on paths-js and transpiling to ES5 (don't ask) using Babel and webpack. This gives an error in npm reporting "Module not found, can't resolve paths-js." This is because webpack expects the default entry to be index.js, but the entry to paths-js is all.js.

This can be solved by adding a line to the package.json "main": "./all.js". I'm unsure if this will break a more typical use case, but I can't see why it would.

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.