Skip to content

Instantly share code, notes, and snippets.

@sasha-id
Last active May 20, 2020 04:43
Show Gist options
  • Save sasha-id/23711382add03aa606e392f2d5f266ba to your computer and use it in GitHub Desktop.
Save sasha-id/23711382add03aa606e392f2d5f266ba to your computer and use it in GitHub Desktop.
react-stockcharts Zone component
<Zone zones={[
{
id: 'pre',
start: { hours: 4, minutes: 0, seconds: 0 },
end: { hours: 9, minutes: 30, seconds: 0 },
fill: "#999999",
opacity: 0.1,
startLine: {
stroke: '#3d7cd4',
strokeWidth: 1,
strokeOpacity: 0.8,
strokeDasharray: 'LongDash',
},
endLine: {
stroke: '#777777',
strokeWidth: 1,
strokeOpacity: 0.7,
strokeDasharray: 'ShortDash',
}
},
{
id: 'post',
start: { hours: 16, minutes: 0, seconds: 0 },
end: { hours: 20, minutes: 30, seconds: 0 },
fill: "#333333",
opacity: 0.1,
startLine: {
stroke: '#777777',
strokeWidth: 1,
strokeOpacity: 0.7,
strokeDasharray: 'ShortDash',
}
}
]}
/>
import React, { Component } from "react";
import PropTypes from "prop-types";
import GenericChartComponent from "react-stockcharts/lib/GenericChartComponent";
import { getAxisCanvas } from "react-stockcharts/lib/GenericComponent";
import { hexToRGBA, strokeDashTypes, getStrokeDasharray } from "react-stockcharts/lib/utils";
class Zone extends Component {
constructor(props) {
super(props)
this.renderSVG = this.renderSVG.bind(this)
this.drawOnCanvas = this.drawOnCanvas.bind(this)
}
getZonesBoundaries (zones, plotData){
let boundaries = {}
zones.forEach(zone => {
const start = plotData.filter((element, i) => {
let startTime = new Date(element.date)
startTime.setHours(zone.start.hours, zone.start.minutes, zone.start.seconds)
let endTime = new Date(element.date)
endTime.setHours(zone.end.hours, zone.end.minutes, zone.end.seconds)
return element.date >= startTime && element.date < endTime && plotData[i + 1] && (!plotData[i - 1] || plotData[i - 1].date < startTime)
})
const end = plotData.filter((element, i) => {
let startTime = new Date(element.date)
startTime.setHours(zone.start.hours, zone.start.minutes, zone.start.seconds)
let endTime = new Date(element.date)
endTime.setHours(zone.end.hours, zone.end.minutes, zone.end.seconds)
return element.date <= endTime && element.date > startTime && plotData[i - 1] && (!plotData[i + 1] || plotData[i + 1].date > endTime)
})
boundaries[zone.id] = start.map((v, i) => { return { start: v, end: end[i] }})
})
return boundaries
}
drawOnCanvas(ctx, moreProps) {
const { xScale, xAccessor, plotData, height, chartConfig: { yScale } } = moreProps;
const { zones } = this.props
const config = zones.reduce((obj, item) => (obj[item.id] = item, obj), {}); // Convert zones array to object id => zone
const boundaries = this.getZonesBoundaries(zones, plotData)
for (let [id, borders] of Object.entries(boundaries)) {
borders.forEach(border => {
const x1 = Math.round(xScale(xAccessor(border.start)))
const x2 = Math.round(xScale(xAccessor(border.end)))
const width = x2 - x1
ctx.fillStyle = hexToRGBA(config[id].fill, config[id].opacity)
ctx.fillRect(x1, 0, width, height)
if (config[id].startLine) this.drawCanvasLine(ctx, { x: x1, height }, config[id].startLine)
if (config[id].endLine) this.drawCanvasLine(ctx, { x: x2, height }, config[id].endLine)
})
}
}
drawCanvasLine(ctx, coordinates, d){
ctx.beginPath()
ctx.strokeStyle = hexToRGBA(d.stroke, d.strokeOpacity)
ctx.lineWidth = d.strokeWidth
ctx.setLineDash(getStrokeDasharray(d.strokeDasharray).split(","))
ctx.moveTo(coordinates.x, 0)
ctx.lineTo(coordinates.x, coordinates.height)
ctx.stroke()
}
renderSVG(moreProps) {
// TODO:
// d = {
// stroke: '#000000',
// fill: '#ffcc00',
// x: 0,
// y: 0,
// width: 100,
// opacity: 0.5,
// heigh: 2.5
// }
// return <rect key={idx} className={d.className}
// stroke={d.stroke}
// fill={d.fill}
// x={d.x}
// y={d.y}
// width={d.width}
// fillOpacity={opacity}
// height={d.height} />
}
render() {
const { clip } = this.props;
return (
<GenericChartComponent
clip={clip}
svgDraw={this.renderSVG}
canvasToDraw={getAxisCanvas}
canvasDraw={this.drawOnCanvas}
drawOn={["pan"]}
/>
)
}
}
Zone.propTypes = {
zones: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.string.isRequired,
start: PropTypes.shape({
hours: PropTypes.number.isRequired,
minutes: PropTypes.number.isRequired,
seconds: PropTypes.number.isRequired
}),
end: PropTypes.shape({
hours: PropTypes.number.isRequired,
minutes: PropTypes.number.isRequired,
seconds: PropTypes.number.isRequired
}),
fill: PropTypes.string.isRequired,
opacity: PropTypes.number.isRequired,
stroke: PropTypes.string,
strokeWidth: PropTypes.number,
strokeOpacity: PropTypes.number,
strokeDasharray: PropTypes.oneOf(strokeDashTypes),
startLine: PropTypes.shape({
stroke: PropTypes.string.isRequired,
strokeWidth: PropTypes.number.isRequired,
strokeOpacity: PropTypes.number.isRequired,
strokeDasharray: PropTypes.oneOf(strokeDashTypes),
}),
endLine: PropTypes.shape({
stroke: PropTypes.string.isRequired,
strokeWidth: PropTypes.number.isRequired,
strokeOpacity: PropTypes.number.isRequired,
strokeDasharray: PropTypes.oneOf(strokeDashTypes),
})
})
)
};
export default Zone;
@sasha-id
Copy link
Author

Screen Shot 2020-05-20 at 12 20 15 AM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment