roughViz.js is a reusable JavaScript library for creating sketchy/hand-drawn styled charts in the browser, based on D3v5, roughjs, and handy.
Use these charts where the communication goal is to show intent or generality, and not absolute precision. Or just because they're fun and look weird.
Chart Type | API |
---|---|
Bar | roughViz.Bar |
Horizontal Bar | roughViz.BarH |
Donut | roughViz.Donut |
Line | roughViz.Line |
Pie | roughViz.Pie |
Scatter | roughViz.Scatter |
Stacked Bar | roughViz.StackedBar |
Visit this link for interactive examples of each chart.
Apply the features of roughjs
to each chart:
roughness:
As well as additional chart-specific options (see API below)
Via CDN (expose the roughViz
global in html
):
<script src="https://unpkg.com/[email protected]"></script>
Via npm
:
npm install rough-viz
Want to use with React
? There's a wrapper!:
npm install react-roughviz
Want to use with Vue
? There's a wrapper!:
npm install vue-roughviz
Want to use it with Python
? Go crazy:
pip install py-roughviz
If you're using ESM, make sure to import the library:
import roughViz from "rough-viz";
Create some container elements, one for each chart:
<!--you can name each id whatever you want -->
<div id="viz0"></div>
<div id="viz1"></div>
In the javascript, just create charts, referencing the desired container:
// create Bar chart from csv file, using default options
new roughViz.Bar({
element: '#viz0', // container selection
data: 'https://raw.githubusercontent.com/jwilber/random_data/master/flavors.csv',
labels: 'flavor',
values: 'price'
});
// create Donut chart using defined data & customize plot options
new roughViz.Donut(
{
element: '#viz1',
data: {
labels: ['North', 'South', 'East', 'West'],
values: [10, 5, 8, 3]
},
title: "Regions",
width: window.innerWidth / 4,
roughness: 8,
colors: ['red', 'orange', 'blue', 'skyblue'],
stroke: 'black',
strokeWidth: 3,
fillStyle: 'cross-hatch',
fillWeight: 3.5,
}
);
Required
-
element
[string]: Id or class of container element. -
data
: Data with which to construct chart. Can be either an object or string.- If object: must contain
labels
andvalues
keys:
new roughViz.Bar({ element: '.viz', data: {labels: ['a', 'b'], values: [10, 20]} })
- If string: must be a path/url to a
csv
ortsv
, and you must also specify thelabels
andvalues
as separate attributes that represent columns in said file:
new roughViz.Bar({ element: '#viz0', data: 'stringToDataUrl.csv', labels: 'nameOfLabelsColumn', values: 'nameOfValuesColumn', })
Optional
axisFontSize
[string]: Font-size for axes' labels. Default:'1rem'
.axisRoughness
[number]: Roughness for x & y axes. Default:0.5
.axisStrokeWidth
[number]: Stroke-width for x & y axes. Default:0.5
.bowing
[number]: Chart bowing. Default:0
.color
[string]: Color for each bar. Default:'skyblue'
.fillStyle
[string]: Bar fill-style. Should be one of fillStyles shown above.fillWeight
[number]: Weight of inner paths' color. Default:0.5
.font
: Font-family to use. You can use0
orgaegu
to useGaegu
, or1
orindie flower
to useIndie Flower
. Or feed it something else. Default:Gaegu
.highlight
[string]: Color for each bar on hover. Default:'coral'
.innerStrokeWidth
[number]: Stroke-width for paths inside bars. Default:1
.interactive
[boolean]: Whether or not chart is interactive. Default:true
.labelFontSize
[string]: Font-size for axes' labels. Default:'1rem'
.margin
[object]: Margin object. Default:{top: 50, right: 20, bottom: 70, left: 100}
padding
[number]: Padding between bars. Default:0.1
.roughness
[number]: Roughness level of chart. Default:1
.simplification
[number]: Chart simplification. Default0.2
.stroke
[string]: Color of bars' stroke. Default:black
.strokeWidth
[number]: Size of bars' stroke. Default:1
.title
[string]: Chart title. Optional.titleFontSize
[string]: Font-size for chart title. Default:'1rem'
.tooltipFontSize
[string]: Font-size for tooltip. Default:'0.95rem'
.xLabel
[string]: Label for x-axis.yLabel
[string]: Label for y-axis.
Required
-
element
[string]: Id or class of container element. -
data
: Data with which to construct chart. Can be either an object or string.- If object: must contain
labels
andvalues
keys:
new roughViz.BarH({ element: '.viz', data: {labels: ['a', 'b'], values: [10, 20]} })
- If string: must be a path/url to a
csv
ortsv
, and you must also specify thelabels
andvalues
as separate attributes that represent columns in said file:
new roughViz.BarH({ element: '#viz0', data: 'stringToDataUrl.csv', labels: 'nameOfLabelsColumn', values: 'nameOfValuesColumn', })
Optional
axisFontSize
[string]: Font-size for axes' labels. Default:'1rem'
.axisRoughness
[number]: Roughness for x & y axes. Default:0.5
.axisStrokeWidth
[number]: Stroke-width for x & y axes. Default:0.5
.bowing
[number]: Chart bowing. Default:0
.color
[string]: Color for each bar. Default:'skyblue'
.fillStyle
[string]: Bar fill-style. Should be one of fillStyles shown above.fillWeight
[number]: Weight of inner paths' color. Default:0.5
.font
: Font-family to use. You can use0
orgaegu
to useGaegu
, or1
orindie flower
to useIndie Flower
. Or feed it something else. Default:Gaegu
.highlight
[string]: Color for each bar on hover. Default:'coral'
.innerStrokeWidth
[number]: Stroke-width for paths inside bars. Default:1
.interactive
[boolean]: Whether or not chart is interactive. Default:true
.labelFontSize
[string]: Font-size for axes' labels. Default:'1rem'
.margin
[object]: Margin object. Default:{top: 50, right: 20, bottom: 70, left: 100}
padding
[number]: Padding between bars. Default:0.1
.roughness
[number]: Roughness level of chart. Default:1
.simplification
[number]: Chart simplification. Default0.2
.stroke
[string]: Color of bars' stroke. Default:black
.strokeWidth
[number]: Size of bars' stroke. Default:1
.title
[string]: Chart title. Optional.titleFontSize
[string]: Font-size for chart title. Default:'1rem'
.tooltipFontSize
[string]: Font-size for tooltip. Default:'0.95rem'
.xLabel
[string]: Label for x-axis.yLabel
[string]: Label for y-axis.
Required
-
element
[string]: Id or class of container element. -
data
: Data with which to construct chart. Can be either an object or string.- If object: must contain
labels
andvalues
keys:
new roughViz.Donut({ element: '.viz', data: {labels: ['a', 'b'], values: [10, 20]} })
- If string: must be a path/url to a
csv
,json
, ortsv
, and you must also specify thelabels
andvalues
as separate attributes that represent columns in said file:
new roughViz.Donut({ element: '#viz0', data: 'stringToDataUrl.csv', labels: 'nameOfLabelsColumn', values: 'nameOfValuesColumn', })
Optional
bowing
[number]: Chart bowing. Default:0
.colors
[array]: Array of colors for each arc. Default:['coral', 'skyblue', '#66c2a5', 'tan', '#8da0cb', '#e78ac3', '#a6d854', '#ffd92f', 'tan', 'orange']
.fillStyle
[string]: Bar fill-style. Should be one of fillStyles shown above.fillWeight
[number]: Weight of inner paths' color. Default:0.85
.font
: Font-family to use. You can use0
orgaegu
to useGaegu
, or1
orindie flower
to useIndie Flower
. Or feed it something else. Default:Gaegu
.highlight
[string]: Color for each arc on hover. Default:'coral'
.innerStrokeWidth
[number]: Stroke-width for paths inside arcs. Default:0.75
.interactive
[boolean]: Whether or not chart is interactive. Default:true
.legend
[boolean]: Whether or not to add legend. Default:'true'
.legendPosition
[string]: Position of legend. Should be either'left'
or'right'
. Default:'right'
.margin
[object]: Margin object. Default:{top: 50, right: 20, bottom: 70, left: 100}
padding
[number]: Padding between bars. Default:0.1
.roughness
[number]: Roughness level of chart. Default:1
.simplification
[number]: Chart simplification. Default0.2
.strokeWidth
[number]: Size of bars' stroke. Default:1
.title
[string]: Chart title. Optional.titleFontSize
[string]: Font-size for chart title. Default:'1rem'
.tooltipFontSize
[string]: Font-size for tooltip. Default:'0.95rem'
.
Required
element
[string]: Id or class of container element.data
: Must be a path/url to acsv
ortsv
, and you must also specify the eachy
as separate attributes that represent columns in said file. Each attribute prefaced withy
(exceptyLabel
) will receive its own line:new roughViz.Line({ element: '#viz0', data: 'https://raw.githubusercontent.com/jwilber/random_data/master/profits.csv', y1: 'revenue', y2: 'cost', y3: 'profit' })
Optional
axisFontSize
[string]: Font-size for axes' labels. Default:'1rem'
.axisRoughness
[number]: Roughness for x & y axes. Default:0.5
.axisStrokeWidth
[number]: Stroke-width for x & y axes. Default:0.5
.bowing
[number]: Chart bowing. Default:0
.circle
[boolean]: Whether or not to add circles to chart. Default:true
.circleRadius
[number]: Radius of circles. Default:10
.circleRoughness
[number]: Roughness of circles. Default:2
.colors
[array or string]: Array of colors for each arc. Default:['coral', 'skyblue', '#66c2a5', 'tan', '#8da0cb', '#e78ac3', '#a6d854', '#ffd92f', 'tan', 'orange']
. If string (e.g.'blue'
), all circles will take that color.fillStyle
[string]: Bar fill-style. Should be one of fillStyles shown above.fillWeight
[number]: Weight of inner paths' color. Default:0.5
.font
: Font-family to use. You can use0
orgaegu
to useGaegu
, or1
orindie flower
to useIndie Flower
. Or feed it something else. Default:Gaegu
.interactive
[boolean]: Whether or not chart is interactive. Default:true
.labelFontSize
[string]: Font-size for axes' labels. Default:'1rem'
.legend
[boolean]: Whether or not to add legend. Default:true
.legendPosition
[string]: Position of legend. Should be either'left'
or'right'
. Default:'right'
.margin
[object]: Margin object. Default:{top: 50, right: 20, bottom: 70, left: 100}
roughness
[number]: Roughness level of chart. Default:1
.simplification
[number]: Chart simplification. Default0.2
.stroke
[string]: Color of lines' stroke. Default:this.colors
.strokeWidth
[number]: Size of lines' stroke. Default:1
.title
[string]: Chart title. Optional.titleFontSize
[string]: Font-size for chart title. Default:'0.95rem'
.tooltipFontSize
[string]: Font-size for tooltip. Default:'0.95rem'
.xLabel
[string]: Label for x-axis.yLabel
[string]: Label for y-axis.
Required
-
element
[string]: Id or class of container element. -
data
: Data with which to construct chart. Can be either an object or string.- If object: must contain
labels
andvalues
keys:
new roughViz.Pie({ element: '.viz', data: {labels: ['a', 'b'], values: [10, 20]} })
- If string: must be a path/url to a
csv
,json
, ortsv
, and you must also specify thelabels
andvalues
as separate attributes that represent columns in said file:
new roughViz.Pie({ element: '#viz0', data: 'stringToDataUrl.csv', labels: 'nameOfLabelsColumn', values: 'nameOfValuesColumn', })
Optional
bowing
[number]: Chart bowing. Default:0
.colors
[array]: Array of colors for each arc. Default:['coral', 'skyblue', '#66c2a5', 'tan', '#8da0cb', '#e78ac3', '#a6d854', '#ffd92f', 'tan', 'orange']
.fillStyle
[string]: Bar fill-style. Should be one of fillStyles shown above.fillWeight
[number]: Weight of inner paths' color. Default:0.85
.font
: Font-family to use. You can use0
orgaegu
to useGaegu
, or1
orindie flower
to useIndie Flower
. Or feed it something else. Default:Gaegu
.highlight
[string]: Color for each arc on hover. Default:'coral'
.innerStrokeWidth
[number]: Stroke-width for paths inside arcs. Default:0.75
.interactive
[boolean]: Whether or not chart is interactive. Default:true
.legend
[boolean]: Whether or not to add legend. Default:true
.legendPosition
[string]: Position of legend. Should be either'left'
or'right'
. Default:'right'
.margin
[object]: Margin object. Default:{top: 50, right: 20, bottom: 70, left: 100}
padding
[number]: Padding between bars. Default:0.1
.roughness
[number]: Roughness level of chart. Default:1
.simplification
[number]: Chart simplification. Default0.2
.strokeWidth
[number]: Size of bars' stroke. Default:1
.title
[string]: Chart title. Optional.titleFontSize
[string]: Font-size for chart title. Default:'1rem'
.tooltipFontSize
[string]: Font-size for tooltip. Default:'0.95rem'
.
Required
-
element
[string]: Id or class of container element. -
data
: Data with which to construct chart. Can be either an object or string.- If object: must contain
x
andy
keys:
new roughViz.Scatter({ element: '.viz', data: {x: [1, 2, 35], y: [10, 20, 8]} })
- If string: must be a path/url to a
csv
ortsv
, and you must also specify thex
andy
as separate attributes that represent columns in said file:
new roughViz.Scatter({ element: '#viz0', data: 'stringToDataUrl.csv', x: 'nameOfLabelsColumn', y: 'nameOfValuesColumn', })
Optional
axisFontSize
[string]: Font-size for axes' labels. Default:'1rem'
.axisRoughness
[number]: Roughness for x & y axes. Default:0.5
.axisStrokeWidth
[number]: Stroke-width for x & y axes. Default:0.5
.bowing
[number]: Chart bowing. Default:0
.colors
[array or string]: Array of colors for each arc. Default:['coral', 'skyblue', '#66c2a5', 'tan', '#8da0cb', '#e78ac3', '#a6d854', '#ffd92f', 'tan', 'orange']
. If string (e.g.'blue'
), all circles will take that color.colorVar
[string]: If input data iscsv
ortsv
, this should be an ordinal column with which to color points by.curbZero
[boolean]: Whether or not to force (x, y) axes to (0, 0). Default:false
.fillStyle
[string]: Bar fill-style. Should be one of fillStyles shown above.fillWeight
[number]: Weight of inner paths' color. Default:0.5
.font
: Font-family to use. You can use0
orgaegu
to useGaegu
, or1
orindie flower
to useIndie Flower
. Or feed it something else. Default:Gaegu
.highlight
[string]: Color for each bar on hover. Default:'coral'
.highlightLabel
[string]: If input data iscsv
ortsv
, this should be a column representing what value to display on hover. Otherwise,(x, y)
values will be shown on hover.innerStrokeWidth
[number]: Stroke-width for paths inside circles. Default:1
.interactive
[boolean]: Whether or not chart is interactive. Default:true
.labelFontSize
[string]: Font-size for axes' labels. Default:'1rem'
.margin
[object]: Margin object. Default:{top: 50, right: 20, bottom: 70, left: 100}
radius
[number]: Circle radius. Default:8
.roughness
[number]: Roughness level of chart. Default:1
.simplification
[number]: Chart simplification. Default0.2
.stroke
[string]: Color of circles' stroke. Default:black
.strokeWidth
[number]: Size of circles' stroke. Default:1
.title
[string]: Chart title. Optional.titleFontSize
[string]: Font-size for chart title. Default:'0.95rem'
.tooltipFontSize
[string]: Font-size for tooltip. Default:'0.95rem'
.xLabel
[string]: Label for x-axis.yLabel
[string]: Label for y-axis.
Required
-
element
[string]: Id or class of container element. -
data
: Data with which to construct chart. Should be an object. -
labels
: String name of label key indata
object.new roughViz.StackedBar({ element: '#vis0', data: [ {month:'Jan', A:20, B: 5}, {month:'Feb', A:25, B: 10}, ], labels: 'month', })
Optional
axisFontSize
[string]: Font-size for axes' labels. Default:'1rem'
.axisRoughness
[number]: Roughness for x & y axes. Default:0.5
.axisStrokeWidth
[number]: Stroke-width for x & y axes. Default:0.5
.bowing
[number]: Chart bowing. Default:0
.colors
[string]: Array of colors for each bar grouping.fillStyle
[string]: Bar fill-style. Should be one of fillStyles shown above.fillWeight
[number]: Weight of inner paths' color. Default:0.5
.font
: Font-family to use. You can use0
orgaegu
to useGaegu
, or1
orindie flower
to useIndie Flower
. Or feed it something else. Default:Gaegu
.highlight
[string]: Color for each bar on hover. Default:'coral'
.innerStrokeWidth
[number]: Stroke-width for paths inside bars. Default:1
.interactive
[boolean]: Whether or not chart is interactive. Default:true
.labelFontSize
[string]: Font-size for axes' labels. Default:'1rem'
.margin
[object]: Margin object. Default:{top: 50, right: 20, bottom: 70, left: 100}
padding
[number]: Padding between bars. Default:0.1
.roughness
[number]: Roughness level of chart. Default:1
.simplification
[number]: Chart simplification. Default0.2
.stroke
[string]: Color of bars' stroke. Default:black
.strokeWidth
[number]: Size of bars' stroke. Default:1
.title
[string]: Chart title. Optional.titleFontSize
[string]: Font-size for chart title. Default:'1rem'
.tooltipFontSize
[string]: Font-size for tooltip. Default:'0.95rem'
.xLabel
[string]: Label for x-axis.yLabel
[string]: Label for y-axis.
This library wouldn't be possible without the following people:
- Mike Bostock for D3.js.
- Preet Shihn for rough.js.
- Jo Wood for handy processing lib.
MIT License
Copyright (c) 2019 Jared Wilber
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
roughviz's People
Forkers
virtual1 isuranimalasri hieuqtran ningchen8743 0xflotus murindwaz sethips sp1ke77 luuufan dondealban wintercomming falconzyx hadryan mashiane clayton-aldern tchigher esomkin git2358 fengweijp wilhantian imfantuan helioxgroup adrianochaar stroupjason roger-hiro bichikim armspkt koki-hayashi tchen0123 ianhongruzhang tavo379 soon-tw yut148 oneplusonecy bagginz approfir botbaht ryanaztec b-xiang sergii callin2 agileinsider schmidthaus edikking josemalcher guimenegussi daveslutzkin patrickb84 accountemail ashishpatel26 jogkunal5 thomas-programmierer rmsreis pranv12 jdiss hanhanwu dinour ibrahim-alsaadi kayazas123 winsomexjs haikyuu csvila jamesfebin codinronan johnjboren barrald acklenx prince-mishra mattlong htxryan longjohncoder neuroradiology woobs julian-becker kidgodzilla kubatyszko shafiahmed iamsingularity avancevl vrieni pedrodinisf wanli3815 xiaoxindian matrixknight woodguoyu rajdude0 jjhartmann bplus sherpadai stvhanna jvergara96 glenndmello maniacs-js intellibrain juergs hhy5277 bahadirdogru kod3r walways jichenshangguanroughviz's Issues
Axis-caption and hovering message-box displaced
I tested this with the current npm package as well as your unpkg-link versions 1.0.5, 1.0.4 and 1.0.3. If I create a simple chart with own object-data, the labels are one chart-size beneath the bars. With the example from your docs there are two axis-labelings. When I hover the charts, the info box gets displayed in the area of the displaced label svg box.
If I position the parent div relative and the two svgs inside absolute, they are displayed correctly, but the message box on hover is completely displaced.
A spell error in readme.md
Legend for `roughViz.StackedBar`
I think it is not possible at the moment, but would it be possible to have a legend for
roughViz.StackedBar
?Thanks in advance
Make charts responsive
I was thinking about making the charts responsive.
As far as I can tell, this may be done by changing the
width
andheight
attributes forthis.svg
in thesetSvg()
method topreserveAspectRatio
andviewBox
as follows:Old:
setSvg() { this.svg = select(this.el) .append('svg') .attr('width', this.width + this.margin.left + this.margin.right) .attr('height', this.height + this.margin.top + this.margin.bottom) .append('g') .attr('id', this.roughId) .attr('transform', 'translate(' + this.margin.left + ',' + this.margin.top + ')'); }
New
setSvg() { this.svg = select(this.el) .append('svg') .attr("preserveAspectRatio", "xMinYMin meet") .attr("viewBox", `0 0 ${(this.width + this.margin.left + this.margin.right)} ${(this.height + this.margin.top + this.margin.bottom)}`) .append('g') .attr('id', this.roughId) .attr('transform', 'translate(' + this.margin.left + ',' + this.margin.top + ')'); }
I can wait to make this change after you've finished the ABC, but since you're working on it (and I believe
setSVG()
will be a method of the ABC), I figured you could add it, assuming it works.Something to think about!
Originally posted by @jwilber in #32 (comment)
Legend overlaps title
some options with a value of `0` are overridden with the defaults
I expected to be able to provide a value of
0
for some options, but when I do they are turned into the defaults:this.roughness = roughCeiling(opts.roughness) || 1; this.axisRoughness = opts.axisRoughness || 0.5; this.simplification = opts.simplification || 0.2;
Crash with a zero value in Pie/Donut chart with Firefox 70.0.1
Description
When a value is 0 in a pie/donut chart, it makes the browser freezing (consuming tons of memory).
How to reproduce
Open the example for Pie/Donut and set a data value to 0
Workarounds
- Zero values could be filtered
- You can put a very small value
Different color bars in stacked bar
I messed with the example and changed the data on the 'March' row. I replaced
B
withD
. (Perhaps March doesn't have a B)
Nothing happened.
I was expecting the March column (right-most) to have a different color for theD
value.data: [ {month:'Jan', A:20, B: 5, C: 10}, {month:'Feb', A:25, B: 10, C: 20}, {month:'March', A:30, D:50, C:10} ],
React Wrapper?
Awesome package, thank you!
I took the liberty to wrap it for React: https://www.npmjs.com/package/react-roughviz
Maybe you want to link to it?
Installation via npm contains additional roughviz.min.js
Python Implementation
Hello, thanks for making such awesome visualization style. I made a Python wrapper based on your RoughViz
You could check it out here:
https://github.com/charlesdong1991/py-roughvizAnd would be appreciated if you'd like to add to your README, so that more people could see and try python version based on your library. ^^
Python Wrapper
Hello,
I have created a python wrapper for your library with most of the features.
You can check it out over here:
https://github.com/hannansatopay/roughviz
https://pypi.org/project/roughviz/nice! didn't you run into rough.js problems with size?
I've used rough.js in another context, and found that the roughness factor had to be set for each general range of size--for small objects, the roughness was off the charts, and for large minor, all given the same roughness factor.
Example links in README are 404
All “Example” links under the Features section of the readme go to 404 pages.
Stacked bar chart?
Can this be done or is this a feature request?
Feature Request: Animated redraw / Individually colored bars
Would it be possible to add a method that will allow the chart values to be updated and for any changes in the bar value to be shown by animating/transitioning to the new value.
I was able to get to the chart to redraw by force removal of the SVG nodes:-
function refreshChart(values, labels) { if (chart !== undefined) { chart.data.labels = labels; chart.data.values = values; chart.svg.selectAll("*").remove(); chart.drawChart(); } }
This works but looks a little janky and has downsides such as no longer supporting tooltips, interactive highlight, etc. as the nodes are being recreated:-
It would be awesome if there was a way to update all the options and call refresh()/redraw() and have these changes reflected without having to destroy the SVG nodes:-
I would also like to be able to supply an array of colours for the bar charts similar to what is supported for the pie charts. Supporting only a single colour seems very limiting for such a cool chart.
Thanks
Line chart with local data
Hi, would it be possible to use a line chart with local data, eg. objects instead of .csv files?
Edit: found out that when you pass an object an error occurs:
this.data.map
is not a function. This is a bug inLine.js:464
.Would like to open a PR for this.
Vue-Wrapper
I created a Vue-Wrapper.
Have a look: https://github.com/jolo-dev/vue-roughvizpiechart not drawn correctly
Save roughViz resulting chart to SVG
First of all: wonderful work!
Now... Would it be possible to save the resulting SVG chart to a SVG file?
Maybe using FileSave.js (eligrey/FileSaver.js#176)
(But in that case the chart would have to be converted to blob first... Is it possible?)
I think this would be a good workaround to make the result responsive...fillStyle in react-roughviz.Line doesn't work
Hi,
I found when 'fillStyle' is added in React component , it doesn't work.
It will be considered as a column in data and log an error during rendering.Deploy a 1.0.7
First off, I love this library, such a clever idea!
I'm building a website that is still a bit rough around the edges, and you can see that the graphs are broken (at the time of writing this), however this is a bug that has already been fixed.
It turns out that the contents of the
dist
folder in the npm package are not up to date, thesrc
folder is all good, but there are 2 dist files and neither are more recent than a year.Would you please consider rebuilding and publishing a
1.0.7
?Thanks again 🙂
Line data as Object (no csv or tsv)
Hey there !
Thanks for the fantastic work :-)
I'd love to use the RoughViz Line without having to create .csv or .tsv files (getting data directly from a private db).
Is this something that can be easily enabled ?
Ability to clear and re-draw
I'm currently using
ref.current.querySelectorAll("*").forEach(n => n.remove());
whereref.current
refers to the DOM<div>
element.
This kinda works but it appears the y-axis is changing which might be a bug but I'd rather figure out a way to re-draw or clear.Label names overlap each other
x axis labels in line plot as strings
Hi,
I am trying to plot a line graph where my xaxis are times (as strings i.e. '7am'), I have the following code:
new roughViz.Line( { element: '#streaming', data: './static/availability.csv', title: 'Line Chart', x: 'time', y1: '# games', width: window.innerWidth / 2, } );
It will render if I remove 'x', but otherwise I can't get it to use strings as the values- possibly because it needs continuous values? If so, is there a workaround to replace the visible tick labels?
Thanks!
HTML links to labels/titles
Very cool project! I was just playing with this yesterday and I was wondering if there's a way to add HTML links to either the label and/or titles?
Not working with Svelte = Cannot read property 'ownerDocument' of null
The provided demo throws
Cannot read property 'ownerDocument' of null
when used as a Svelte component. See the following Repl showing the issue.The reason seems to be (as covered in this video by Svelte Master) that the
index.js
is incorrect and contains the contents of what looks like a build / config issue:-content of index.js as installed via npm
// modules are defined as an array // [ module function, map of requires ] // // map of requires is short require name -> numeric require // // anything defined in a previous bundle is accessed via the // orig method which is the require for previous bundles parcelRequire = (function (modules, cache, entry, globalName) { // Save the require from previous bundle to this closure if any var previousRequire = typeof parcelRequire === 'function' && parcelRequire; var nodeRequire = typeof require === 'function' && require;
function newRequire(name, jumped) {
if (!cache[name]) {
if (!modules[name]) {
// if we cannot find the module within our internal map or
// cache jump to the current global require ie. the last bundle
// that was added to the page.
var currentRequire = typeof parcelRequire === 'function' && parcelRequire;
if (!jumped && currentRequire) {
return currentRequire(name, true);
}// If there are other bundles on this page the require from the // previous one is saved to 'previousRequire'. Repeat this as // many times as there are bundles until the module is found or // we exhaust the require chain. if (previousRequire) { return previousRequire(name, true); } // Try the node require function if it exists. if (nodeRequire && typeof name === 'string') { return nodeRequire(name); } var err = new Error('Cannot find module \'' + name + '\''); err.code = 'MODULE_NOT_FOUND'; throw err; } localRequire.resolve = resolve; localRequire.cache = {}; var module = cache[name] = new newRequire.Module(name); modules[name][0].call(module.exports, localRequire, module, module.exports, this); } return cache[name].exports; function localRequire(x){ return newRequire(localRequire.resolve(x)); } function resolve(x){ return modules[name][1][x] || x; }
}
function Module(moduleName) {
this.id = moduleName;
this.bundle = newRequire;
this.exports = {};
}newRequire.isParcelRequire = true;
newRequire.Module = Module;
newRequire.modules = modules;
newRequire.cache = cache;
newRequire.parent = previousRequire;
newRequire.register = function (id, exports) {
modules[id] = [function (require, module) {
module.exports = exports;
}, {}];
};var error;
for (var i = 0; i < entry.length; i++) {
try {
newRequire(entry[i]);
} catch (e) {
// Save first error but execute all entries
if (!error) {
error = e;
}
}
}if (entry.length) {
// Expose entry point to Node, AMD or browser globals
// Based on https://github.com/ForbesLindesay/umd/blob/master/template.js
var mainExports = newRequire(entry[entry.length - 1]);// CommonJS if (typeof exports === "object" && typeof module !== "undefined") { module.exports = mainExports; // RequireJS } else if (typeof define === "function" && define.amd) { define(function () { return mainExports; }); // <script> } else if (globalName) { this[globalName] = mainExports; }
}
// Override the current require with this new one
parcelRequire = newRequire;if (error) {
// throw error from earlier, after updating parcelRequire
throw error;
}return newRequire;
})({"../node_modules/parcel-bundler/src/builtins/bundle-url.js":[function(require,module,exports) {
var bundleURL = null;function getBundleURLCached() {
if (!bundleURL) {
bundleURL = getBundleURL();
}return bundleURL;
}function getBundleURL() {
// Attempt to find the URL of the current script and use that as the base URL
try {
throw new Error();
} catch (err) {
var matches = ('' + err.stack).match(/(https?|file|ftp|chrome-extension|moz-extension)://[^)\n]+/g);if (matches) { return getBaseURL(matches[0]); }
}
return '/';
}function getBaseURL(url) {
return ('' + url).replace(/^((?:https?|file|ftp|chrome-extension|moz-extension)://.+)/[^/]+$/, '$1') + '/';
}exports.getBundleURL = getBundleURLCached;
exports.getBaseURL = getBaseURL;
},{}],"../node_modules/parcel-bundler/src/builtins/css-loader.js":[function(require,module,exports) {
var bundle = require('./bundle-url');function updateLink(link) {
var newLink = link.cloneNode();newLink.onload = function () {
link.remove();
};newLink.href = link.href.split('?')[0] + '?' + Date.now();
link.parentNode.insertBefore(newLink, link.nextSibling);
}var cssTimeout = null;
function reloadCSS() {
if (cssTimeout) {
return;
}cssTimeout = setTimeout(function () {
var links = document.querySelectorAll('link[rel="stylesheet"]');for (var i = 0; i < links.length; i++) { if (bundle.getBaseURL(links[i].href) === bundle.getBundleURL()) { updateLink(links[i]); } } cssTimeout = null;
}, 50);
}module.exports = reloadCSS;
},{"./bundle-url":"../node_modules/parcel-bundler/src/builtins/bundle-url.js"}],"../node_modules/parcel-bundler/src/builtins/hmr-runtime.js":[function(require,module,exports) {
var global = arguments[3];
var OVERLAY_ID = 'parcel__error__overlay';
var OldModule = module.bundle.Module;function Module(moduleName) {
OldModule.call(this, moduleName);
this.hot = {
data: module.bundle.hotData,
_acceptCallbacks: [],
_disposeCallbacks: [],
accept: function (fn) {
this._acceptCallbacks.push(fn || function () {});
},
dispose: function (fn) {
this._disposeCallbacks.push(fn);
}
};
module.bundle.hotData = null;
}module.bundle.Module = Module;
var checkedAssets, assetsToAccept;
var parent = module.bundle.parent;if ((!parent || !parent.isParcelRequire) && typeof WebSocket !== 'undefined') {
var hostname = "" || location.hostname;
var protocol = location.protocol === 'https:' ? 'wss' : 'ws';
var ws = new WebSocket(protocol + '://' + hostname + ':' + "57962" + '/');ws.onmessage = function (event) {
checkedAssets = {};
assetsToAccept = [];
var data = JSON.parse(event.data);if (data.type === 'update') { var handled = false; data.assets.forEach(function (asset) { if (!asset.isNew) { var didAccept = hmrAcceptCheck(global.parcelRequire, asset.id); if (didAccept) { handled = true; } } }); // Enable HMR for CSS by default. handled = handled || data.assets.every(function (asset) { return asset.type === 'css' && asset.generated.js; }); if (handled) { console.clear(); data.assets.forEach(function (asset) { hmrApply(global.parcelRequire, asset); }); assetsToAccept.forEach(function (v) { hmrAcceptRun(v[0], v[1]); }); } else { window.location.reload(); } } if (data.type === 'reload') { ws.close(); ws.onclose = function () { location.reload(); }; } if (data.type === 'error-resolved') { console.log('[parcel] ✨ Error resolved'); removeErrorOverlay(); } if (data.type === 'error') { console.error('[parcel] 🚨 ' + data.error.message + '\n' + data.error.stack); removeErrorOverlay(); var overlay = createErrorOverlay(data); document.body.appendChild(overlay); }
};
}function removeErrorOverlay() {
var overlay = document.getElementById(OVERLAY_ID);if (overlay) {
overlay.remove();
}
}function createErrorOverlay(data) {
var overlay = document.createElement('div');
overlay.id = OVERLAY_ID; // html encode message and stack tracevar message = document.createElement('div');
var stackTrace = document.createElement('pre');
message.innerText = data.error.message;
stackTrace.innerText = data.error.stack;
overlay.innerHTML = '' + 'ERROR' + '🚨' + '';' + message.innerHTML + '' + '' + stackTrace.innerHTML + '
' + '
return overlay;
}function getParents(bundle, id) {
var modules = bundle.modules;if (!modules) {
return [];
}var parents = [];
var k, d, dep;for (k in modules) {
for (d in modules[k][1]) {
dep = modules[k][1][d];if (dep === id || Array.isArray(dep) && dep[dep.length - 1] === id) { parents.push(k); } }
}
if (bundle.parent) {
parents = parents.concat(getParents(bundle.parent, id));
}return parents;
}function hmrApply(bundle, asset) {
var modules = bundle.modules;if (!modules) {
return;
}if (modules[asset.id] || !bundle.parent) {
var fn = new Function('require', 'module', 'exports', asset.generated.js);
asset.isNew = !modules[asset.id];
modules[asset.id] = [fn, asset.deps];
} else if (bundle.parent) {
hmrApply(bundle.parent, asset);
}
}function hmrAcceptCheck(bundle, id) {
var modules = bundle.modules;if (!modules) {
return;
}if (!modules[id] && bundle.parent) {
return hmrAcceptCheck(bundle.parent, id);
}if (checkedAssets[id]) {
return;
}checkedAssets[id] = true;
var cached = bundle.cache[id];
assetsToAccept.push([bundle, id]);if (cached && cached.hot && cached.hot._acceptCallbacks.length) {
return true;
}return getParents(global.parcelRequire, id).some(function (id) {
return hmrAcceptCheck(global.parcelRequire, id);
});
}function hmrAcceptRun(bundle, id) {
var cached = bundle.cache[id];
bundle.hotData = {};if (cached) {
cached.hot.data = bundle.hotData;
}if (cached && cached.hot && cached.hot._disposeCallbacks.length) {
cached.hot._disposeCallbacks.forEach(function (cb) {
cb(bundle.hotData);
});
}delete bundle.cache[id];
bundle(id);
cached = bundle.cache[id];if (cached && cached.hot && cached.hot._acceptCallbacks.length) {
cached.hot._acceptCallbacks.forEach(function (cb) {
cb();
});return true;
}
}
},{}]},{},["../node_modules/parcel-bundler/src/builtins/hmr-runtime.js"], null)
//# sourceMappingURL=/index.js.map
Work arounds:-
import roughViz from 'node_modules/rough-viz/dist/rough-viz.min.js';
- rename the
roughviz.min.js
toindex.js
(which is probably related to issue #7)
Thanks for the great package. They are a great alternative to the standard charts and makes the charts fun :)
Abstract Class
Originally I wanted to create a chart Abstract Base Class with the common methods across the charts (e.g.
resolveFont()
,initChartValues()
,setSVG()
,resolveData()
, etc.) but didn't find a straightforward manner of doing so in ES6. I'm sure it can be done easily enough with prototypal inheritance, but I'd prefer to keep everything as ES6 as possible.I don't write too much JavaScript, so it's pretty likely that I missed something. Very open to any ideas!
Usage with React TypeScript
I have been having difficulties in integrating this with my TypeScript project. It is an amazing library but if there is an article or example I can refer to. Well, that would be amazing.
And I have tried to use react-roughviz as well but found the documentation majorly lacking. Any help would be highly appreciated.
Clickable bar charts
I'm using a stacked bar chart and I'd like things to happen when the user clicks bars. At the moment, a legend floats under the mouse cursor but I'd like to do more. I'd click to display information underneath the chart about the bar you clicked on.
Bar chart doesn't work
Bar chart doesn't work.
Unifiy titleFontSize
Some charts have
titleFontSize
with a default value set to'1rem'
and others set to'0.95rem'
.
For consistency, I think that all charts should have the same default value.Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
- If object: must contain
- If object: must contain
- If object: must contain
- If object: must contain
- If object: must contain