Skip to content

Instantly share code, notes, and snippets.

@davo

davo/LineChart.tsx

Created Aug 6, 2018
Embed
What would you like to do?
LineChart Component for Framer X (based on VX)

LineChart Component for Framer X (based on VX)

Install via Yarn

"dependencies": { "@vx/mock-data": "^0.0.165", "@vx/shape": "^0.0.170", "@vx/curve": "^0.0.165", "@vx/gradient": "^0.0.165", "@vx/grid": "^0.0.170", "@vx/scale": "latest", "@vx/tooltip": "latest", "@vx/event": "latest", "d3-array": "^1.2.1", "d3-time-format": "^2.1.1" }

import * as React from 'react'
import { Frame, Size, PropertyControls, ControlType } from 'framer'
import { AreaClosed, Line, Bar } from '@vx/shape'
import { appleStock } from '@vx/mock-data'
import { curveMonotoneX } from '@vx/curve'
import { LinearGradient } from '@vx/gradient'
// import { GridRows, GridColumns } from '@vx/grid'
import { scaleTime, scaleLinear } from '@vx/scale'
// import { withTooltip, Tooltip } from '@vx/tooltip'
import { localPoint } from '@vx/event'
import { extent, max, bisector } from 'd3-array'
import { timeFormat } from 'd3-time-format'
const stock = appleStock.slice(800)
const formatDate = timeFormat("%b %d, '%y")
const xStock = d => new Date(d.date)
const yStock = d => d.close
const bisectDate = bisector(d => new Date(d.date)).left
export class LineChart extends React.Component {
constructor(props) {
super(props)
this.handleTooltip = this.handleTooltip.bind(this)
}
handleTooltip({ event, data, xStock, xScale, yScale }) {
const { showTooltip } = this.props
const { x } = localPoint(event)
const x0 = xScale.invert(x)
const index = bisectDate(data, x0, 1)
const d0 = data[index - 1]
const d1 = data[index]
let d = d0
if (d1 && d1.date) {
d = x0 - xStock(d0.date) > xStock(d1.date) - x0 ? d1 : d0
}
showTooltip({
tooltipData: d,
tooltipLeft: x,
tooltipTop: yScale(d.close)
})
}
static defaultProps = {
width: 343,
height: 457,
margin: { top: 0, right: 0, bottom: 0, left: 0 },
surname: '',
region: 'United States',
photo: '',
background: '#fff',
color: '#000',
randomRegion: '',
title: 15,
subtitle: 13,
avatar: 50,
mode: true
}
render() {
const {
width,
height,
margin,
background,
showTooltip,
hideTooltip,
tooltipData,
tooltipTop,
tooltipLeft,
events
} = this.props
if (width < 10) return null
console.log(this.props)
// Bounds
const xMax = width - margin.left - margin.right
const yMax = height - margin.top - margin.bottom
// scales
const xScale = scaleTime({
range: [0, xMax],
domain: extent(stock, xStock)
})
const yScale = scaleLinear({
range: [yMax, 0],
domain: [0, max(stock, yStock) + yMax / 3],
nice: true
})
return (
<Frame
width={this.props.width}
height={this.props.height}
background={this.props.background}
style={{
borderRadius: 8
}}
>
<svg ref={s => (this.svg = s)} width={width} height={height}>
<rect
x={0}
y={0}
width={width}
height={height}
fill="#1ED2FC"
rx={14}
/>
<defs>
<linearGradient
id="gradient"
x1="0%"
y1="0%"
x2="0%"
y2="100%"
>
<stop
offset="0%"
stopColor="#FFFFFF"
stopOpacity={0.5}
/>
<stop
offset="100%"
stopColor="#FFFFFF"
stopOpacity={0.2}
/>
</linearGradient>
</defs>
<AreaClosed
data={stock}
xScale={xScale}
yScale={yScale}
x={xStock}
y={yStock}
strokeWidth={1}
stroke={'url(#gradient)'}
fill={'url(#gradient)'}
curve={curveMonotoneX}
/>
</svg>
</Frame>
)
}
}
{
"main": "build/index.js",
"license": "MIT",
"devDependencies": {
"@types/react": "^16.0.31",
"framer": "^0.1.27"
},
"peerDependencies": {
"framer": "^0.1.27",
"react": "^16.3.0",
"react-dom": "^16.3.0"
},
"framer": {
"id": "296fe9eb-d6bd-43f8-967f-d596ec1c4a7a"
},
"author": "Davo Galavotti",
"dependencies": {
"@framer/framer.device-skin-apple-iphone-x-space-gray": "^1.0.0",
"@vx/mock-data": "^0.0.165",
"@vx/shape": "^0.0.170",
"@vx/curve": "^0.0.165",
"@vx/gradient": "^0.0.165",
"@vx/grid": "^0.0.170",
"@vx/scale": "latest",
"@vx/tooltip": "latest",
"@vx/event": "latest",
"d3-array": "^1.2.1",
"d3-time-format": "^2.1.1"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment