It is time to fix time vector
This commit is contained in:
parent
fbd1b46b91
commit
10ad3be6b3
|
@ -1,5 +1,3 @@
|
|||
open ForetoldComponents.Base;
|
||||
|
||||
let data: DistributionTypes.xyShape = {
|
||||
xs: [|1., 10., 10., 200., 250., 292., 330.|],
|
||||
ys: [|0.0, 0.0, 0.1, 0.3, 0.5, 0.2, 0.1|],
|
||||
|
|
|
@ -11,16 +11,17 @@ type primaryDistribution = {
|
|||
let make =
|
||||
(
|
||||
~height=?,
|
||||
~verticalLine=?,
|
||||
~showVerticalLine=?,
|
||||
~marginBottom=?,
|
||||
~marginTop=?,
|
||||
~showDistributionLines=?,
|
||||
~maxX=?,
|
||||
~minX=?,
|
||||
~onHover=(f: float) => (),
|
||||
~primaryDistribution=?,
|
||||
~scale=?,
|
||||
~showDistributionLines=?,
|
||||
~showVerticalLine=?,
|
||||
~timeScale=?,
|
||||
~verticalLine=?,
|
||||
~children=[||],
|
||||
) =>
|
||||
ReasonReact.wrapJsForReason(
|
||||
|
@ -28,16 +29,17 @@ let make =
|
|||
~props=
|
||||
makeProps(
|
||||
~height?,
|
||||
~verticalLine?,
|
||||
~marginBottom?,
|
||||
~marginTop?,
|
||||
~onHover,
|
||||
~showVerticalLine?,
|
||||
~showDistributionLines?,
|
||||
~maxX?,
|
||||
~minX?,
|
||||
~onHover,
|
||||
~primaryDistribution?,
|
||||
~scale?,
|
||||
~showDistributionLines?,
|
||||
~showVerticalLine?,
|
||||
~timeScale?,
|
||||
~verticalLine?,
|
||||
(),
|
||||
),
|
||||
children,
|
||||
|
|
|
@ -18,26 +18,28 @@ module Styles = {
|
|||
[@react.component]
|
||||
let make =
|
||||
(
|
||||
~data,
|
||||
~minX=?,
|
||||
~maxX=?,
|
||||
~scale=?,
|
||||
~height=200,
|
||||
~color=`hex("111"),
|
||||
~data,
|
||||
~height=200,
|
||||
~maxX=?,
|
||||
~minX=?,
|
||||
~onHover: float => unit,
|
||||
~scale=?,
|
||||
~timeScale=?,
|
||||
) => {
|
||||
<div className={Styles.graph(color)}>
|
||||
<CdfChart__Base
|
||||
height
|
||||
?minX
|
||||
?maxX
|
||||
?minX
|
||||
?scale
|
||||
?timeScale
|
||||
height
|
||||
marginBottom=50
|
||||
marginTop=0
|
||||
onHover
|
||||
showVerticalLine=false
|
||||
showDistributionLines=false
|
||||
primaryDistribution={data |> Shape.XYShape.toJs}
|
||||
showDistributionLines=false
|
||||
showVerticalLine=false
|
||||
/>
|
||||
</div>;
|
||||
};
|
|
@ -2,16 +2,19 @@ module Continuous = {
|
|||
[@react.component]
|
||||
let make = (~data, ~unit) => {
|
||||
let (x, setX) = React.useState(() => 0.);
|
||||
let timeScale = unit |> DistributionTypes.DistributionUnit.toJson;
|
||||
let chart =
|
||||
React.useMemo1(
|
||||
() =>
|
||||
<CdfChart__Plain
|
||||
data
|
||||
timeScale
|
||||
color={`hex("333")}
|
||||
onHover={r => setX(_ => r)}
|
||||
/>,
|
||||
[|data|],
|
||||
);
|
||||
|
||||
<div>
|
||||
chart
|
||||
<table className="table-auto">
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
const _ = require('lodash');
|
||||
const d3 = require('d3');
|
||||
const moment = require('moment');
|
||||
|
||||
class Chart {
|
||||
export class CdfChartD3 {
|
||||
|
||||
constructor() {
|
||||
this.attrs = {
|
||||
|
@ -13,10 +14,11 @@ class Chart {
|
|||
marginRight: 50,
|
||||
marginLeft: 5,
|
||||
|
||||
container: 'body',
|
||||
container: null,
|
||||
minX: false,
|
||||
maxX: false,
|
||||
scale: 'linear',
|
||||
timeScale: null,
|
||||
showDistributionLines: true,
|
||||
areaColors: ['#E1E5EC', '#E1E5EC'],
|
||||
logBase: 10,
|
||||
|
@ -28,6 +30,7 @@ class Chart {
|
|||
};
|
||||
this.hoverLine = null;
|
||||
this.xScale = null;
|
||||
this.xScaleTime = null;
|
||||
this.dataPoints = null;
|
||||
this.mouseover = this.mouseover.bind(this);
|
||||
this.mouseout = this.mouseout.bind(this);
|
||||
|
@ -59,6 +62,11 @@ class Chart {
|
|||
return this;
|
||||
}
|
||||
|
||||
timeScale(timeScale) {
|
||||
this.attrs.timeScale = timeScale;
|
||||
return this;
|
||||
}
|
||||
|
||||
onHover(onHover) {
|
||||
this.attrs.onHover = onHover;
|
||||
return this;
|
||||
|
@ -119,10 +127,7 @@ class Chart {
|
|||
const len = data.xs.length;
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
dt.push({
|
||||
x: data.xs[i],
|
||||
y: data.ys[i]
|
||||
})
|
||||
dt.push({ x: data.xs[i], y: data.ys[i] });
|
||||
}
|
||||
|
||||
return dt;
|
||||
|
@ -133,6 +138,7 @@ class Chart {
|
|||
const container = d3.select(attrs.container);
|
||||
if (container.node() === null) return;
|
||||
|
||||
// Sets the width from the DOM element.
|
||||
const containerRect = container.node().getBoundingClientRect();
|
||||
if (containerRect.width > 0) {
|
||||
attrs.svgWidth = containerRect.width;
|
||||
|
@ -159,10 +165,6 @@ class Chart {
|
|||
this.xScale = d3.scaleLinear()
|
||||
.domain([attrs.minX || xMin, attrs.maxX || xMax])
|
||||
.range([0, calc.chartWidth]);
|
||||
} else if (attrs.scale === 'time') {
|
||||
this.xScale = d3.scaleLinear()
|
||||
.domain([new Date(2012, 0, 1), new Date(2020, 0, 31)])
|
||||
.range([0, calc.chartWidth]);
|
||||
} else {
|
||||
this.xScale = d3.scaleLog()
|
||||
.base(attrs.logBase)
|
||||
|
@ -178,9 +180,17 @@ class Chart {
|
|||
.range([calc.chartHeight, 0]);
|
||||
|
||||
// Axis generator.
|
||||
if (attrs.scale === 'time') {
|
||||
if (!!this.attrs.timeScale) {
|
||||
const zero = _.get(this.attrs.timeScale, 'zero', moment());
|
||||
const unit = _.get(this.attrs.timeScale, 'unit', null);
|
||||
const length = zero.clone().add('year', 5);
|
||||
|
||||
this.xScaleTime = d3.scaleLinear()
|
||||
.domain([zero.toDate(), length.toDate()])
|
||||
.range([0, calc.chartWidth]);
|
||||
|
||||
this.xAxis = d3.axisBottom()
|
||||
.scale(this.xScale)
|
||||
.scale(this.xScaleTime)
|
||||
.ticks(5)
|
||||
.tickFormat(this.formatDates);
|
||||
} else {
|
||||
|
@ -329,16 +339,16 @@ class Chart {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
d3.selection.prototype.patternify = function patternify(params) {
|
||||
const selector = params.selector;
|
||||
const elementTag = params.tag;
|
||||
const data = params.data || [selector];
|
||||
|
||||
const selection = this.selectAll('.' + selector).data(data, (d, i) => {
|
||||
if (typeof d === 'object' && d.id) return d.id;
|
||||
return i;
|
||||
});
|
||||
const selection = this.selectAll('.' + selector)
|
||||
.data(data, (d, i) => {
|
||||
if (typeof d === 'object' && d.id) return d.id;
|
||||
return i;
|
||||
});
|
||||
|
||||
selection.exit().remove();
|
||||
|
||||
|
@ -348,9 +358,3 @@ d3.selection.prototype.patternify = function patternify(params) {
|
|||
.merge(selection)
|
||||
.attr('class', selector);
|
||||
};
|
||||
|
||||
function chart() {
|
||||
return new Chart();
|
||||
}
|
||||
|
||||
export default chart;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { useSize } from 'react-use';
|
||||
|
||||
import chart from './cdfChartD3';
|
||||
import { CdfChartD3 } from './cdfChartD3';
|
||||
|
||||
/**
|
||||
* @param min
|
||||
|
@ -19,8 +19,9 @@ function getRandomInt(min, max) {
|
|||
* @returns {*}
|
||||
* @constructor
|
||||
*/
|
||||
function CdfChart(props) {
|
||||
const id = "chart-" + getRandomInt(0, 100000);
|
||||
function CdfChartReact(props) {
|
||||
const containerRef = React.createRef();
|
||||
const key = "cdf-chart-react-" + getRandomInt(0, 1000);
|
||||
const scale = props.scale || 'linear';
|
||||
const style = !!props.width ? { width: props.width + "px" } : {};
|
||||
|
||||
|
@ -33,7 +34,7 @@ function CdfChart(props) {
|
|||
});
|
||||
|
||||
useEffect(() => {
|
||||
chart()
|
||||
new CdfChartD3()
|
||||
.svgWidth(width)
|
||||
.svgHeight(props.height)
|
||||
.maxX(props.maxX)
|
||||
|
@ -46,9 +47,10 @@ function CdfChart(props) {
|
|||
.showDistributionLines(props.showDistributionLines)
|
||||
.verticalLine(props.verticalLine)
|
||||
.showVerticalLine(props.showVerticalLine)
|
||||
.container("#" + id)
|
||||
.container(containerRef.current)
|
||||
.data({ primary: props.primaryDistribution })
|
||||
.scale(scale)
|
||||
.timeScale(props.timeScale)
|
||||
.render();
|
||||
});
|
||||
|
||||
|
@ -59,8 +61,12 @@ function CdfChart(props) {
|
|||
},
|
||||
}, [
|
||||
sized,
|
||||
React.createElement("div", { id, style, key: id }),
|
||||
React.createElement("div", {
|
||||
key,
|
||||
style,
|
||||
ref: containerRef,
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
export default CdfChart;
|
||||
export default CdfChartReact;
|
||||
|
|
|
@ -46,4 +46,15 @@ type genericDistribution = {
|
|||
probabilityType,
|
||||
domain,
|
||||
unit: distributionUnit,
|
||||
};
|
||||
|
||||
module DistributionUnit = {
|
||||
let toJson = (distributionUnit: distributionUnit) =>
|
||||
switch (distributionUnit) {
|
||||
| Time({zero, unit}) =>
|
||||
Js.Null.fromOption(
|
||||
Some({"zero": zero, "unit": unit |> TimeTypes.TimeUnit.toString}),
|
||||
)
|
||||
| _ => Js.Null.fromOption(None)
|
||||
};
|
||||
};
|
|
@ -20,6 +20,21 @@ type timePoint = {
|
|||
value: float,
|
||||
};
|
||||
|
||||
module TimeUnit = {
|
||||
let toString = (timeUnit: timeUnit) =>
|
||||
switch (timeUnit) {
|
||||
| `days => "days"
|
||||
| `hours => "hours"
|
||||
| `milliseconds => "milliseconds"
|
||||
| `minutes => "minutes"
|
||||
| `months => "months"
|
||||
| `quarters => "quarters"
|
||||
| `seconds => "seconds"
|
||||
| `weeks => "weeks"
|
||||
| `years => "years"
|
||||
};
|
||||
};
|
||||
|
||||
module TimePoint = {
|
||||
let fromTimeVector = (timeVector, value): timePoint => {timeVector, value};
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user