react-liquidchart
Advanced tools
Comparing version 0.0.14 to 0.0.16
@@ -27,2 +27,14 @@ 'use strict'; | ||
var _d3Color = require('d3-color'); | ||
var d3Color = _interopRequireWildcard(_d3Color); | ||
var _ReactIf = require('./ReactIf'); | ||
var _ReactIf2 = _interopRequireDefault(_ReactIf); | ||
var _Text = require('./Text'); | ||
var _Text2 = _interopRequireDefault(_Text); | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } | ||
@@ -76,8 +88,13 @@ | ||
value: function setRes() { | ||
// set an array filled with zeros, | ||
// we are just going to use the index anyways | ||
this.arr = new Array(100); | ||
// get the clip path | ||
this.wave = (0, _d3Selection.select)(this.clipPath).datum([this.props.value]); | ||
// get the tspan | ||
this.text = (0, _d3Selection.select)(this.container).selectAll('text').selectAll('tspan.value'); | ||
var width = this.props.width * this.props.innerRadius / 2; | ||
var height = this.props.height * (this.props.innerRadius - this.props.margin) / 2; | ||
// to animate the wave we need to set the width of the path double the diameter | ||
// of the liquid. | ||
this.x = (0, _d3Scale.scaleLinear)().range([-this.liquidRadius * 2, this.liquidRadius * 2]).domain([0, 100]); | ||
@@ -91,4 +108,5 @@ this.y = (0, _d3Scale.scaleLinear)().range([height, -height]).domain([0, 100]); | ||
// ready the chart | ||
this.setRes(); | ||
// some basic trig | ||
var val = (0, _d3Shape.area)().x(function (d, i) { | ||
@@ -101,3 +119,6 @@ return _this2.x(i); | ||
}); | ||
// set the clip path d attribute | ||
this.wave.attr('d', val(this.arr)); | ||
// set the text to the rounded value | ||
// decimal formatting todo | ||
this.text.text(Math.round(this.props.value)); | ||
@@ -110,34 +131,56 @@ } | ||
// ready the chart and do calculations | ||
this.setRes(); | ||
var val = (0, _d3Shape.area)().x(function (d, i) { | ||
return _this3.x(i); | ||
}).y0(function (d, i) { | ||
return _this3.y(Math.sin(i / 4)); | ||
}).y1(function (d) { | ||
return _this3.props.height / 2; | ||
}); | ||
// reduce the wave when it's close to 0 or 100 | ||
var waveScale = void 0; | ||
if (this.props.waveScaleLimit) { | ||
waveScale = (0, _d3Scale.scaleLinear)().range([0, this.props.amplitude, 0]).domain([0, 50, 100]); | ||
} else { | ||
waveScale = (0, _d3Scale.scaleLinear)().range([this.props.amplitude, this.props.amplitude]).domain([0, 50, 100]); | ||
} | ||
// the d3 timer goes from from 0 to 1 | ||
var time = (0, _d3Scale.scaleLinear)().range([0, 1]).domain([0, this.props.animationTime]); | ||
var interpolateValue = (0, _d3Interpolate.interpolate)(this.wave.node().old || 0, this.props.value); | ||
var interpolateWave = (0, _d3Interpolate.interpolate)(0, this.liquidRadius); | ||
// start animation | ||
var animationTimer = (0, _d3Timer.timer)(function (t) { | ||
// set the easing | ||
var animate = _this3.props.ease(time(t)); | ||
var animateWave = ease.easeSinInOut(time(t)); | ||
var value = interpolateValue(animate); | ||
// calculate the wave | ||
val.y0(function (d, i) { | ||
return _this3.y(_this3.props.amplitude * Math.sin(i / _this3.props.frequency) + interpolateValue(animate)); | ||
return _this3.y(waveScale(value) * Math.sin(i / _this3.props.frequency) + value); | ||
}); | ||
_this3.text.text(Math.round(interpolateValue(animate))); | ||
// set the text value | ||
_this3.text.text(Math.round(value)); | ||
// set the wave data attribute | ||
_this3.wave.attr('d', val(_this3.arr)); | ||
_this3.wave.attr('transform', 'translate(' + interpolateWave(animateWave) + ',0)'); | ||
// If we are making waves then set the easing and move the path | ||
if (_this3.props.animateWaves) { | ||
var animateWave = ease.easeSinInOut(time(t)); | ||
_this3.wave.attr('transform', 'translate(' + interpolateWave(animateWave) + ',0)'); | ||
} | ||
// the transition has ended | ||
if (t >= _this3.props.animationTime) { | ||
// make sure that the chart ends in the right position | ||
// stop the timer | ||
animationTimer.stop(); | ||
_this3.text.text(Math.round(interpolateValue(animate))); | ||
// Make sure that the animation stops in the right place | ||
// we set 1 as the interpolation parameter | ||
val.y0(function (d, i) { | ||
return _this3.y(waveScale(_this3.props.value) * Math.sin(i / _this3.props.frequency) + interpolateValue(1)); | ||
}); | ||
_this3.text.text(Math.round(interpolateValue(1))); | ||
_this3.wave.attr('d', val(_this3.arr)); | ||
_this3.wave.attr('transform', 'translate(' + interpolateWave(1) + ',0)'); | ||
_this3.text.text(Math.round(_this3.props.value)); | ||
// do the same if we are animating waves | ||
if (_this3.props.animateWaves) { | ||
_this3.wave.attr('transform', 'translate(' + interpolateWave(1) + ',0)'); | ||
} | ||
// if the onEnd prop is set then call the function | ||
@@ -162,5 +205,11 @@ if (_this3.props.onEnd !== undefined) { | ||
var outerArc = (0, _d3Shape.arc)().outerRadius(this.props.outerRadius * this.radius).innerRadius(this.props.innerRadius * this.radius).startAngle(0).endAngle(Math.PI * 2); | ||
var cX = this.props.width * this.props.offsetX / 2; | ||
var cY = this.props.height * this.props.offsetY / 2; | ||
// set the chart center | ||
var cX = this.props.width / 2; | ||
var cY = this.props.height / 2; | ||
var fillCircle = this.props.liquid.fill; | ||
if (this.props.gradient) { | ||
fillCircle = 'url(#' + this.props.gradient + ')'; | ||
} | ||
return _react2.default.createElement( | ||
@@ -189,49 +238,11 @@ 'g', | ||
), | ||
(0, _Text2.default)(this.props, this.props.number), | ||
_react2.default.createElement( | ||
'text', | ||
{ | ||
textAnchor: 'middle', | ||
fontSize: this.props.fontSize, | ||
fill: this.props.number.fill, | ||
stroke: this.props.number.stroke | ||
}, | ||
_react2.default.createElement( | ||
'tspan', | ||
{ className: 'value' }, | ||
this.props.value | ||
), | ||
_react2.default.createElement( | ||
'tspan', | ||
{ fontSize: this.props.smallFontSize }, | ||
'%' | ||
) | ||
), | ||
_react2.default.createElement( | ||
'g', | ||
{ | ||
clipPath: 'url(#clip)' | ||
}, | ||
{ clipPath: 'url(#clip)' }, | ||
_react2.default.createElement('circle', { | ||
r: this.liquidRadius, | ||
fill: this.props.liquid.fill | ||
fill: fillCircle | ||
}), | ||
_react2.default.createElement( | ||
'text', | ||
{ | ||
textAnchor: 'middle', | ||
fontSize: this.props.fontSize, | ||
fill: this.props.liquidNumber.fill, | ||
stroke: this.props.liquidNumber.stroke | ||
}, | ||
_react2.default.createElement( | ||
'tspan', | ||
{ className: 'value' }, | ||
this.props.value | ||
), | ||
_react2.default.createElement( | ||
'tspan', | ||
{ fontSize: this.props.smallFontSize }, | ||
'%' | ||
) | ||
) | ||
(0, _Text2.default)(this.props, this.props.liquidNumber) | ||
), | ||
@@ -293,11 +304,10 @@ _react2.default.createElement('path', { | ||
frequency: _react.PropTypes.number, | ||
// scaling the wave when it´s close to 0 or 100 | ||
waveScaleLimit: _react.PropTypes.bool, | ||
// on click | ||
onClick: _react.PropTypes.func, | ||
offsetY: _react.PropTypes.number, | ||
offsetX: _react.PropTypes.number, | ||
// Font size for the number | ||
fontSize: _react.PropTypes.string, | ||
// font size for the percentage | ||
smallFontSize: _react.PropTypes.string, | ||
animateWaves: _react.PropTypes.bool | ||
// if true then animate waves | ||
animateWaves: _react.PropTypes.bool, | ||
// the gradient string | ||
gradient: _react.PropTypes.string | ||
}; | ||
@@ -313,2 +323,3 @@ LiquidChart.defaultProps = { | ||
amplitude: 2, | ||
waveScaleLimit: true, | ||
frequency: 4, | ||
@@ -315,0 +326,0 @@ outerArcStyle: { |
@@ -6,13 +6,20 @@ 'use strict'; | ||
}); | ||
exports.Gradient = exports.Liquid = exports.Chart = undefined; | ||
var _react = require('react'); | ||
var _Chart = require('./Chart/Chart'); | ||
var _react2 = _interopRequireDefault(_react); | ||
var _Chart2 = _interopRequireDefault(_Chart); | ||
var _Chart = require('./Chart/'); | ||
var _Liquid = require('./Chart/Liquid'); | ||
var _Chart2 = _interopRequireDefault(_Chart); | ||
var _Liquid2 = _interopRequireDefault(_Liquid); | ||
var _Gradient = require('./Chart/Gradient'); | ||
var _Gradient2 = _interopRequireDefault(_Gradient); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
exports.default = _Chart2.default; | ||
exports.Chart = _Chart2.default; | ||
exports.Liquid = _Liquid2.default; | ||
exports.Gradient = _Gradient2.default; |
{ | ||
"name": "react-liquidchart", | ||
"version": "0.0.14", | ||
"version": "0.0.16", | ||
"description": "A Reusable liquid chart made with d3 and react", | ||
@@ -48,2 +48,3 @@ "main": "dist/index.js", | ||
"dependencies": { | ||
"d3-color": "^1.0.2", | ||
"d3-ease": "^1.0.2", | ||
@@ -50,0 +51,0 @@ "d3-interpolate": "^1.1.2", |
@@ -12,14 +12,17 @@ # React-Liquidchart | ||
import { render } from 'react-dom'; | ||
import Liquid from 'react-liquidchart'; | ||
import { Chart, Liquid, Gradient } from 'react-liquidchart'; | ||
class Chart extends Component { | ||
class ChartLiquid extends Component { | ||
constructor() { | ||
super(); | ||
this.onClick = this.onClick.bind(this); | ||
this.state = { | ||
value: Math.random() * 100, | ||
}; | ||
this.state = ({ | ||
value: (Math.random() * 100), | ||
}); | ||
} | ||
onClick() { | ||
this.setState({ value: Math.random() * 100 }); | ||
this.setState({ | ||
value: (Math.random() * 100), | ||
}); | ||
} | ||
@@ -31,13 +34,25 @@ | ||
style={{ | ||
width: '800px', | ||
height: '350px', | ||
marginLeft: 'auto', | ||
marginRight: 'auto', | ||
width: '100%', | ||
height: '500px', | ||
}} | ||
> | ||
<Liquid | ||
onClick={this.onClick} | ||
value={this.state.value} | ||
animate | ||
/> | ||
<Chart | ||
responsive | ||
gradient="liquid" | ||
> | ||
<Liquid | ||
animate | ||
animateWaves | ||
onClick={this.onClick} | ||
amplitude={4} | ||
value={this.state.value} | ||
/> | ||
<Gradient> | ||
<stop stopColor="someColor" offset="somepercentage%"/> | ||
<stop stopColor="someColor" offset="somepercentage%"/> | ||
<stop stopColor="someColor" offset="somepercentage%"/> | ||
<stop stopColor="someColor" offset="somepercentage%"/> | ||
</Gradient> | ||
</Chart> | ||
</div> | ||
@@ -47,33 +62,49 @@ ); | ||
} | ||
render(<Chart />, document.getElementById('app')); | ||
render(<ChartLiquid />, document.getElementById('app')); | ||
``` | ||
## PropTypes | ||
### value : number | ||
## Components | ||
### Chart | ||
The Chart container component, calculates width and height and renders the svg and charts | ||
#### Chart PropTypes | ||
##### responsive : boolean | ||
Makes the chart listen to changes in screen size and resize the chart on screen resize | ||
##### gradient : string | ||
If liquid is gradient then set the string to something, it's used to set the fill | ||
### Liqiud | ||
The Liquid Component has all the visable Components | ||
#### Liquid PropTypes | ||
##### value : number | ||
a percentage from 0 to 100 | ||
### animate : boolean | ||
##### animate : boolean | ||
if true then animate | ||
### animateWaves : boolean | ||
##### animateWaves : boolean | ||
if true then animate waves | ||
### onEnd : function | ||
##### gradient : boolean | ||
If true then add gradient effect on liquid based on liquid.fill color | ||
##### onEnd : function | ||
A function that is called when animation is done | ||
### outerArcStyle : Object { fill: string, stroke: string } | ||
##### outerArcStyle : Object { fill: string, stroke: string } | ||
A fill and stroke for the outer arc, defaults to fill: 'rgb(23, 139, 202)' | ||
### liquid : Object { fill: string, stroke: string } | ||
##### liquid : Object { fill: string, stroke: string } | ||
A fill and stroke for the liquid, defaults to fill: 'rgb(23, 139, 202)' | ||
### liquidNumber : Object { fill: string, stroke: string } | ||
##### liquidNumber : Object { fill: string, stroke: string } | ||
A fill and stroke for the part of the number that is in liquid | ||
defaults to fill: 'rgb(164, 219, 248)', | ||
### number : Object { fill: string, stroke: string } | ||
##### number : Object { fill: string, stroke: string } | ||
A fill and stroke for the 'dry' part of the number default to fill: 'rgb(4, 86, 129)' | ||
### amplitude : number | ||
##### amplitude : number | ||
the wave height | ||
### frequency : number | ||
##### frequency : number | ||
The inverse of frequency actually, the higher the number the smother the wave | ||
### responsive : boolean | ||
Makes the chart listen to changes in screen size and resize the chart on screen resize | ||
### fontSize : string | ||
##### waveScaleLimit : bool | ||
scaling the wave when it´s close to 0 or 100 so the area does not appear empty at those values | ||
##### fontSize : string | ||
The font size attribute for the number | ||
### smallFontSize : string | ||
##### smallFontSize : string | ||
font size for the percentage sign | ||
### Gradient | ||
The Gradient is just a thin wrapper for linearGradient it takes in stop children, | ||
if none are set it makes a gradient out of the shades of the liquid.fill proptype | ||
@@ -93,3 +124,2 @@ ## Development | ||
This is a react remake and slightly altered version of http://bl.ocks.org/brattonc/5e5ce9beee483220e2f6 | ||
So a big thanks to Chris Bratton for making the original | ||
So a big thanks to Chris Bratton for making the original! |
@@ -8,2 +8,6 @@ import React, { Component, PropTypes } from 'react'; | ||
import { interpolate } from 'd3-interpolate'; | ||
import * as d3Color from 'd3-color'; | ||
import ReactIf from './ReactIf'; | ||
import Text from './Text'; | ||
/* | ||
@@ -52,11 +56,10 @@ PropType for fill and stroke.. | ||
frequency: PropTypes.number, | ||
// scaling the wave when it´s close to 0 or 100 | ||
waveScaleLimit: PropTypes.bool, | ||
// on click | ||
onClick: PropTypes.func, | ||
offsetY: PropTypes.number, | ||
offsetX: PropTypes.number, | ||
// Font size for the number | ||
fontSize: PropTypes.string, | ||
// font size for the percentage | ||
smallFontSize: PropTypes.string, | ||
// if true then animate waves | ||
animateWaves: PropTypes.bool, | ||
// the gradient string | ||
gradient: PropTypes.string, | ||
} | ||
@@ -73,2 +76,3 @@ | ||
amplitude: 2, | ||
waveScaleLimit: true, | ||
frequency: 4, | ||
@@ -110,9 +114,15 @@ outerArcStyle: { | ||
setRes() { | ||
// set an array filled with zeros, | ||
// we are just going to use the index anyways | ||
this.arr = new Array(100); | ||
// get the clip path | ||
this.wave = select(this.clipPath).datum([this.props.value]); | ||
// get the tspan | ||
this.text = select(this.container) | ||
.selectAll('text').selectAll('tspan.value'); | ||
const width = (this.props.width * this.props.innerRadius) / 2; | ||
.selectAll('text') | ||
.selectAll('tspan.value'); | ||
const height = (this.props.height * (this.props.innerRadius - this.props.margin)) / 2; | ||
// to animate the wave we need to set the width of the path double the diameter | ||
// of the liquid. | ||
this.x = scaleLinear().range([-this.liquidRadius * 2, this.liquidRadius * 2]).domain([0, 100]); | ||
@@ -123,11 +133,15 @@ this.y = scaleLinear().range([height, -height]).domain([0, 100]); | ||
draw() { | ||
// ready the chart | ||
this.setRes(); | ||
// some basic trig | ||
const val = area() | ||
.x((d, i) => this.x(i)) | ||
.y0((d, i) => this.y( | ||
(this.props.amplitude * Math.sin(i / this.props.frequency)) + | ||
this.props.value)) | ||
.y1(d => this.props.height / 2); | ||
.x((d, i) => this.x(i)) | ||
.y0((d, i) => this.y( | ||
(this.props.amplitude * Math.sin(i / this.props.frequency)) + | ||
this.props.value)) | ||
.y1(d => this.props.height / 2); | ||
// set the clip path d attribute | ||
this.wave.attr('d', val(this.arr)); | ||
// set the text to the rounded value | ||
// decimal formatting todo | ||
this.text.text(Math.round(this.props.value)); | ||
@@ -137,31 +151,58 @@ } | ||
animate() { | ||
// ready the chart and do calculations | ||
this.setRes(); | ||
const val = area() | ||
.x((d, i) => this.x(i)) | ||
.y0((d, i) => this.y(Math.sin(i / 4))) | ||
.y1(d => this.props.height / 2); | ||
.x((d, i) => this.x(i)) | ||
.y1(d => this.props.height / 2); | ||
// reduce the wave when it's close to 0 or 100 | ||
let waveScale; | ||
if (this.props.waveScaleLimit) { | ||
waveScale = scaleLinear() | ||
.range([0, this.props.amplitude, 0]) | ||
.domain([0, 50, 100]); | ||
} else { | ||
waveScale = scaleLinear() | ||
.range([this.props.amplitude, this.props.amplitude]) | ||
.domain([0, 50, 100]); | ||
} | ||
// the d3 timer goes from from 0 to 1 | ||
const time = scaleLinear().range([0, 1]).domain([0, this.props.animationTime]); | ||
const interpolateValue = interpolate(this.wave.node().old || 0, this.props.value); | ||
const interpolateWave = interpolate(0, this.liquidRadius); | ||
// start animation | ||
const animationTimer = timer((t) => { | ||
// set the easing | ||
const animate = this.props.ease(time(t)); | ||
const animateWave = ease.easeSinInOut(time(t)); | ||
const value = interpolateValue(animate); | ||
// calculate the wave | ||
val.y0((d, i) => this.y( | ||
(this.props.amplitude * Math.sin(i / this.props.frequency)) | ||
+ interpolateValue(animate))); | ||
this.text.text(Math.round(interpolateValue(animate))); | ||
(waveScale(value) * Math.sin(i / this.props.frequency)) | ||
+ value)); | ||
// set the text value | ||
this.text.text(Math.round(value)); | ||
// set the wave data attribute | ||
this.wave.attr('d', val(this.arr)); | ||
this.wave.attr('transform', `translate(${interpolateWave(animateWave)},0)`); | ||
// If we are making waves then set the easing and move the path | ||
if (this.props.animateWaves) { | ||
const animateWave = ease.easeSinInOut(time(t)); | ||
this.wave.attr('transform', `translate(${interpolateWave(animateWave)},0)`); | ||
} | ||
// the transition has ended | ||
if (t >= this.props.animationTime) { | ||
// make sure that the chart ends in the right position | ||
// stop the timer | ||
animationTimer.stop(); | ||
this.text.text(Math.round(interpolateValue(animate))); | ||
// Make sure that the animation stops in the right place | ||
// we set 1 as the interpolation parameter | ||
val.y0((d, i) => this.y( | ||
(waveScale(this.props.value) * Math.sin(i / this.props.frequency)) | ||
+ interpolateValue(1))); | ||
this.text.text(Math.round(interpolateValue(1))); | ||
this.wave.attr('d', val(this.arr)); | ||
this.wave.attr('transform', `translate(${interpolateWave(1)},0)`); | ||
this.text.text(Math.round(this.props.value)); | ||
// do the same if we are animating waves | ||
if (this.props.animateWaves) { | ||
this.wave.attr('transform', `translate(${interpolateWave(1)},0)`); | ||
} | ||
// if the onEnd prop is set then call the function | ||
@@ -187,5 +228,11 @@ if (this.props.onEnd !== undefined) { | ||
.endAngle(Math.PI * 2); | ||
const cX = (this.props.width * this.props.offsetX) / 2; | ||
const cY = (this.props.height * this.props.offsetY) / 2; | ||
// set the chart center | ||
const cX = this.props.width / 2; | ||
const cY = this.props.height / 2; | ||
let fillCircle = this.props.liquid.fill; | ||
if (this.props.gradient) { | ||
fillCircle = `url(#${this.props.gradient})`; | ||
} | ||
return ( | ||
@@ -205,27 +252,9 @@ <g | ||
</defs> | ||
<text | ||
textAnchor="middle" | ||
fontSize={this.props.fontSize} | ||
fill={this.props.number.fill} | ||
stroke={this.props.number.stroke} | ||
> | ||
<tspan className="value">{this.props.value}</tspan> | ||
<tspan fontSize={this.props.smallFontSize}>%</tspan> | ||
</text> | ||
<g | ||
clipPath="url(#clip)" | ||
> | ||
{Text(this.props, this.props.number)} | ||
<g clipPath="url(#clip)"> | ||
<circle | ||
r={this.liquidRadius} | ||
fill={this.props.liquid.fill} | ||
fill={fillCircle} | ||
/> | ||
<text | ||
textAnchor="middle" | ||
fontSize={this.props.fontSize} | ||
fill={this.props.liquidNumber.fill} | ||
stroke={this.props.liquidNumber.stroke} | ||
> | ||
<tspan className="value">{this.props.value}</tspan> | ||
<tspan fontSize={this.props.smallFontSize}>%</tspan> | ||
</text> | ||
{Text(this.props, this.props.liquidNumber)} | ||
</g> | ||
@@ -232,0 +261,0 @@ <path |
@@ -1,4 +0,5 @@ | ||
import React, { Component } from 'react'; | ||
import Liquid from './Chart/'; | ||
import Chart from './Chart/Chart'; | ||
import Liquid from './Chart/Liquid'; | ||
import Gradient from './Chart/Gradient'; | ||
export default Liquid; | ||
export { Chart, Liquid, Gradient }; |
@@ -9,3 +9,3 @@ const path = require('path'); | ||
devtool: 'eval-source-map', | ||
entry: './examples/index.jsx', | ||
entry: './exampleTest/index.jsx', | ||
output: { | ||
@@ -12,0 +12,0 @@ path: __dirname, |
49471
24
1212
122
10
+ Addedd3-color@^1.0.2