UNPKG

recharts

Version:
257 lines (234 loc) 18.4 kB
import React, {PropTypes} from 'react'; import {BarChart, BarItem, Brush, CartesianGrid, ReferenceLine, XAxis, YAxis, Tooltip} from 'recharts'; import ColorUtil from 'recharts-color-utils'; let colors = ColorUtil.Palette('#ffc658', 'rectangle'); //colors = ['#ccc', '#ccc', '#ccc', '#ccc']; const CustomBar = React.createClass({ getPath () { const {x, y, width, height} = this.props; return `M${x},${y + height} C${x + width / 3},${y + height} ${x + width / 2},${y + height / 3} ${x + width / 2}, ${y} C${x + width / 2},${y + height / 3} ${x + 2 * width / 3},${y + height} ${x + width}, ${y + height} Z`; }, render () { const {fill} = this.props; return <path d={this.getPath()} stroke='none' fill={fill}/>; } }); const BarTwo = React.createClass({ getPath () { const {x, y, width, height} = this.props; const extend = width * 0.2; return `M${x - extend},${y + height} C${x - extend + width / 3},${y + height} ${x + width / 6},${y} ${x + width / 2}, ${y} C${x + 5 * width / 6},${y} ${x + extend + 2 * width / 3},${y + height} ${x + width + extend}, ${y + height} Z`; }, render () { const {fill, fillOpacity} = this.props; return <path d={this.getPath()} stroke='none' fillOpacity={fillOpacity} fill={fill}/>; } }); const CustomAxis = React.createClass({ getIcon () { const {x, y, value} = this.props; let icon; switch(value) { case '美食': icon = ( <svg x={x - 10} y={y} width={20} height={20} version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> <path fill={colors[0]} d="M960 682.666667c-8.533333 0-21.333333 0-21.333333 0l-85.333333 0c-23.466667 0-42.666667-19.2-42.666667-42.666667 0-8.533333 0-21.333333 0-21.333333 0-6.4 0-14.933333 0-21.333333 0-164.266667-134.4-298.666667-298.666667-298.666667s-298.666667 134.4-298.666667 298.666667c0 6.4 0 14.933333 2.133333 21.333333 0 0-2.133333 12.8-2.133333 21.333333 0 23.466667-19.2 42.666667-42.666667 42.666667L85.333333 682.666667c0 0-12.8 0-21.333333 0-23.466667 0-42.666667-19.2-42.666667-42.666667s19.2-42.666667 42.666667-42.666667c8.533333 0 21.333333 0 21.333333 0l42.666667 0c0-189.866667 138.666667-347.733333 320-377.6 0-2.133333 0-4.266667 0-6.4 0-36.266667 27.733333-64 64-64s64 27.733333 64 64c0 2.133333 0 4.266667 0 6.4 181.333333 29.866667 320 187.733333 320 377.6l42.666667 0c0 0 12.8 0 21.333333 0 23.466667 0 42.666667 19.2 42.666667 42.666667S983.466667 682.666667 960 682.666667zM469.333333 384 469.333333 384c0 0 6.4 0 10.666667 0 17.066667 0 32 14.933333 32 32S497.066667 448 480 448c-4.266667 0-10.666667 0-10.666667 0l0 0c-70.4 0-128 57.6-128 128 0 0 0 6.4 0 10.666667 0 17.066667-14.933333 32-32 32S277.333333 603.733333 277.333333 586.666667c0-4.266667 0-10.666667 0-10.666667C277.333333 469.333333 362.666667 384 469.333333 384zM64 789.333333l896 0c23.466667 0 42.666667 19.2 42.666667 42.666667s-19.2 42.666667-42.666667 42.666667L64 874.666667c-23.466667 0-42.666667-19.2-42.666667-42.666667S40.533333 789.333333 64 789.333333z" /> </svg> ); break; case '美妆': icon = ( <svg x={x - 10} y={y} width={20} height={20} version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> <path fill={colors[1]} d="M874.666667 940.8 149.333333 940.8c-23.466667 0-42.666667-19.2-42.666667-42.666667s19.2-42.666667 42.666667-42.666667l42.666667 0 0-170.666667c0-23.466667 19.2-42.666667 42.666667-42.666667l64 0 0-512c0-23.466667 17.066667-42.666667 38.4-46.933333 8.533333-2.133333 19.2 2.133333 19.2 2.133333S680.533333 256 682.666667 258.133333c25.6 8.533333 42.666667 25.6 42.666667 42.666667l0 341.333333 64 0c23.466667 0 42.666667 19.2 42.666667 42.666667l0 170.666667 42.666667 0c23.466667 0 42.666667 19.2 42.666667 42.666667S898.133333 940.8 874.666667 940.8zM640 334.933333 384 196.266667l0 445.866667 256 0L640 334.933333zM746.666667 727.466667l-21.333333 0-85.333333 0L384 727.466667l-85.333333 0-21.333333 0 0 128 469.333333 0L746.666667 727.466667z" /> </svg> ); break; case '收纳': icon = ( <svg x={x - 10} y={y} width={20} height={20} version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> <path fill={colors[2]} d="M896 928.234667 128 928.234667C104.426667 928.234667 85.333333 909.141333 85.333333 885.568L85.333333 629.568C85.333333 605.994667 104.426667 586.901333 128 586.901333L163.52 586.901333 434.837333 116.970667C446.613333 96.554667 472.704 89.578667 493.12 101.354667L714.816 229.354667C735.232 241.130667 742.208 267.221333 730.432 287.637333L714.176 315.797333 864.426667 402.56C884.842667 414.336 891.84 440.426667 880.042667 460.842667L807.274667 586.901333 896 586.901333C919.573333 586.901333 938.666667 605.994667 938.666667 629.568L938.666667 885.568C938.666667 909.141333 919.573333 928.234667 896 928.234667ZM487.402667 196.586667 262.058667 586.901333 459.114667 586.901333 635.2 281.92 487.402667 196.586667ZM557.653333 586.901333 708.736 586.901333 784.810667 455.125333 671.509333 389.696 557.653333 586.901333ZM853.333333 672.234667 170.666667 672.234667 170.666667 842.901333 853.333333 842.901333 853.333333 672.234667Z" /> </svg> ); break; case '数码': icon = ( <svg x={x - 10} y={y} width={20} height={20} version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> <path fill={colors[3]} d="M896 896 128 896C104.426667 896 85.333333 876.906667 85.333333 853.333333L85.333333 298.666667C85.333333 275.093333 104.426667 256 128 256L896 256C919.573333 256 938.666667 275.093333 938.666667 298.666667L938.666667 853.333333C938.666667 876.906667 919.573333 896 896 896ZM853.333333 341.333333 170.666667 341.333333 170.666667 810.666667 853.333333 810.666667 853.333333 341.333333ZM512 405.333333C606.250667 405.333333 682.666667 481.749333 682.666667 576 682.666667 670.250667 606.250667 746.666667 512 746.666667 417.749333 746.666667 341.333333 670.250667 341.333333 576 341.333333 481.749333 417.749333 405.333333 512 405.333333ZM512 661.333333C559.125333 661.333333 597.333333 623.125333 597.333333 576 597.333333 528.874667 559.125333 490.666667 512 490.666667 464.874667 490.666667 426.666667 528.874667 426.666667 576 426.666667 623.125333 464.874667 661.333333 512 661.333333ZM448 213.333333 234.666667 213.333333C211.093333 213.333333 192 194.24 192 170.666667 192 147.093333 211.093333 128 234.666667 128L448 128C471.573333 128 490.666667 147.093333 490.666667 170.666667 490.666667 194.24 471.573333 213.333333 448 213.333333Z" /> </svg> ); break; case '养生': icon = ( <svg x={x - 10} y={y} width={20} height={20} version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> <path fill="#89ca82" d="M762.752 714.389333C547.072 900.373333 343.274667 847.274667 285.226667 826.325333 252.010667 881.194667 227.050667 927.018667 222.933333 939.178667 222.933333 939.178667 197.226667 977.642667 166.4 965.845333 131.946667 952.661333 141.12 912.746667 141.12 912.746667 143.808 912.661333 165.269333 859.84 209.109333 784.448 186.389333 750.485333 101.333333 605.269333 178.005333 434.218667 255.488 261.312 431.146667 245.44 515.2 211.712 642.048 160.810667 693.482667 53.077333 764.8 55.978667 835.285333 58.837333 995.882667 513.365333 762.752 714.389333ZM748.181333 163.178667C742.869333 157.077333 659.050667 260.757333 551.466667 292.778667 488.149333 311.616 325.589333 349.354667 263.466667 455.978667 202.837333 560.042667 243.008 673.472 257.621333 707.114667 285.312 665.984 318.144 622.016 356.821333 578.197333 548.629333 361.002667 665.301333 341.077333 651.733333 343.978667 651.733333 343.978667 696.32 331.882667 708.266667 365.312 720.213333 398.741333 677.333333 423.978667 677.333333 423.978667 677.333333 423.978667 491.797333 540.586667 408.021333 645.141333 384.085333 674.986667 357.909333 712.362667 332.970667 750.421333 394.837333 766.378667 541.866667 781.845333 704.256 652.458667 872.789333 518.208 783.125333 203.2 748.181333 163.178667Z" /> </svg> ); break; case '音乐': icon = ( <svg x={x - 10} y={y} width={20} height={20} version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> <path fill="#8dd1e1" d="M896 896 725.333333 896C701.76 896 682.666667 876.906667 682.666667 853.333333L682.666667 576C682.666667 552.426667 701.76 533.333333 725.333333 533.333333L853.333333 533.333333 853.333333 512C853.333333 323.477333 700.522667 170.666667 512 170.666667 323.477333 170.666667 170.666667 323.477333 170.666667 512L170.666667 533.333333 298.666667 533.333333C322.24 533.333333 341.333333 552.426667 341.333333 576L341.333333 853.333333C341.333333 876.906667 322.24 896 298.666667 896L128 896C104.426667 896 85.333333 876.906667 85.333333 853.333333L85.333333 512C85.333333 276.352 276.352 85.333333 512 85.333333 747.648 85.333333 938.666667 276.352 938.666667 512L938.666667 853.333333C938.666667 876.906667 919.573333 896 896 896ZM170.666667 810.666667 256 810.666667 256 618.666667 170.666667 618.666667 170.666667 810.666667ZM853.333333 618.666667 768 618.666667 768 810.666667 853.333333 810.666667 853.333333 618.666667Z" /> </svg> ); break; case '游戏': icon = ( <svg x={x - 10} y={y} width={20} height={20} version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> <path fill="#9cacf1" d="M832 608C832 631.573333 812.906667 650.666667 789.333333 650.666667 765.76 650.666667 746.666667 631.573333 746.666667 608 746.666667 584.426667 765.76 565.333333 789.333333 565.333333 812.906667 565.333333 832 584.426667 832 608ZM725.333333 906.666667 725.333333 821.333333C843.157333 821.333333 938.666667 725.824 938.666667 608 938.666667 490.176 843.157333 394.666667 725.333333 394.666667L725.333333 330.666667 725.333333 330.666667 725.333333 394.666667 298.666667 394.666667 298.666667 309.333333 640 309.333333 640 160C640 136.426667 659.093333 117.333333 682.666667 117.333333 706.24 117.333333 725.333333 136.426667 725.333333 160L725.333333 309.333333C890.282667 309.333333 1024 443.050667 1024 608 1024 772.949333 890.282667 906.666667 725.333333 906.666667ZM85.333333 608C85.333333 725.824 180.842667 821.333333 298.666667 821.333333L298.666667 906.666667C133.717333 906.666667 0 772.949333 0 608 0 443.050667 133.717333 309.333333 298.666667 309.333333L298.666667 394.666667C180.842667 394.666667 85.333333 490.176 85.333333 608ZM192 608C192 584.426667 211.093333 565.333333 234.666667 565.333333L298.666667 565.333333 298.666667 501.333333C298.666667 477.76 317.76 458.666667 341.333333 458.666667 364.906667 458.666667 384 477.76 384 501.333333L384 565.333333 448 565.333333C471.573333 565.333333 490.666667 584.426667 490.666667 608 490.666667 631.573333 471.573333 650.666667 448 650.666667L384 650.666667 384 714.666667C384 738.24 364.906667 757.333333 341.333333 757.333333 317.76 757.333333 298.666667 738.24 298.666667 714.666667L298.666667 650.666667 234.666667 650.666667C211.093333 650.666667 192 631.573333 192 608ZM576 608C576 584.426667 595.093333 565.333333 618.666667 565.333333 642.24 565.333333 661.333333 584.426667 661.333333 608 661.333333 631.573333 642.24 650.666667 618.666667 650.666667 595.093333 650.666667 576 631.573333 576 608ZM725.333333 906.666667 298.666667 906.666667 298.666667 821.333333 725.333333 821.333333 725.333333 906.666667Z" /> </svg> ); break; case '阅读': icon = ( <svg x={x - 10} y={y} width={20} height={20} version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> <path fill="#9390df" d="M917.333333 795.733333l-405.333333 110.933333 0-2.133333 0 2.133333L106.666667 795.733333c0 0-21.333333-14.933333-21.333333-38.4l0-597.333333c0-23.466667 19.2-42.666667 42.666667-42.666667 0 0 0 0 0 0l0 0 2.133333 0c6.4 0 12.8 2.133333 17.066667 4.266667L512 221.866667l364.8-98.133333c4.266667-2.133333 10.666667-4.266667 17.066667-4.266667l2.133333 0 0 0c0 0 0 0 0 0 23.466667 0 42.666667 19.2 42.666667 42.666667l0 597.333333C938.666667 782.933333 917.333333 795.733333 917.333333 795.733333zM469.333333 298.666667 170.666667 217.6 170.666667 725.333333l298.666667 81.066667L469.333333 298.666667zM853.333333 217.6 554.666667 298.666667l0 509.866667L853.333333 725.333333 853.333333 217.6z" /> </svg> ); break; } return icon; }, render () { const {x, y, value} = this.props; return ( <g> {this.getIcon()} <text textAnchor='middle' x={x} y={y} dy={34}>{value}</text> </g> ) } }); export default React.createClass({ displayName: 'BarChartDemo', render () { const data = [ {name: '美食', uv: 400, pv: 2400, fill: colors[0]}, {name: '美妆', uv: 300, pv: 4567, fill: colors[1]}, {name: '收纳', uv: 300, pv: 1398, fill: colors[2]}, {name: '数码', uv: 200, pv: 9800, fill: colors[3]} ]; const data2 = [ {name: '201102', uv: -6.11, pv: 0}, {name: '201103', uv: 0.39, pv: 0}, {name: '201104', uv: -1.37, pv: 0}, {name: '201105', uv: 1.16, pv: 0}, {name: '201106', uv: 1.29, pv: 0}, {name: '201107', uv: 0.09, pv: 0}, {name: '201108', uv: 0.53, pv: 0}, {name: '201109', uv: 2.52, pv: 0}, {name: '201110', uv: 0.79, pv: 0}, {name: '201111', uv: 2.94, pv: 0}, {name: '201112', uv: 4.3, pv: 0}, {name: '201201', uv: 7.41, pv: 14.21}, {name: '201202', uv: -7.1, pv: 13.01}, {name: '201203', uv: -1.17, pv: 11.26}, {name: '201204', uv: -1.86, pv: 10.7}, {name: '201205', uv: -0.16, pv: 9.26}, {name: '201206', uv: -1.25, pv: 6.53}, {name: '201207', uv: 0.22, pv: 6.66}, {name: '201208', uv: 0.72, pv: 6.86}, {name: '201209', uv: 1.82, pv: 6.12}, {name: '201210', uv: 1.64, pv: 7.02}, {name: '201211', uv: 3.16, pv: 7.25}, {name: '201212', uv: 1.31, pv: 4.17}, {name: '201301', uv: 2.91, pv: -0.19}, {name: '201302', uv: -0.47, pv: 6.94}, {name: '201303', uv: -4.15, pv: 3.71}, {name: '201304', uv: -1.82, pv: 3.76}, {name: '201305', uv: -0.93, pv: 2.95}, {name: '201306', uv: -0.99, pv: 3.22}, {name: '201307', uv: -0.52, pv: 2.46}, {name: '201308', uv: 1.54, pv: 3.3}, {name: '201309', uv: 2.05, pv: 3.54}, {name: '201310', uv: 0.7, pv: 2.58}, {name: '201311', uv: 2.25, pv: 1.59}, {name: '201312', uv: 3.59, pv: 3.92}, {name: '201401', uv: 3.63, pv: 4.64}, {name: '201402', uv: -4.91, pv: -0.02}, {name: '201403', uv: -2.66, pv: 1.54}, {name: '201404', uv: -1.50, pv: 1.86}, {name: '201405', uv: -0.19, pv: 2.62}, {name: '201406', uv: -0.22, pv: 3.42}, {name: '201407', uv: -0.58, pv: 3.35}, {name: '201408', uv: 0.89, pv: 2.69}, {name: '201409', uv: 2.22, pv: 2.86}, {name: '201410', uv: 0.61, pv: 2.77}, {name: '201411', uv: 2.37, pv: 2.97}, {name: '201412', uv: 3.06, pv: 2.41}, {name: '201501', uv: 1.07, pv: -0.13}, {name: '201502', uv: 4.04, pv: 9.27}, {name: '201503', uv: -5.14, pv: 6.48}, {name: '201504', uv: -1.69, pv: 6.28}, {name: '201505', uv: 0.51, pv: 7.03}, {name: '201506', uv: 1.03, pv: 8.37}, {name: '201507', uv: -1.14, pv: 7.76}, {name: '201508', uv: 0.53, pv: 7.38}, {name: '201509', uv: 1.51, pv: 6.63}, {name: '201510', uv: -0.16, pv: 5.81}, {name: '201511', uv: 3.27, pv: 6.74}, ]; // <p>最简单的柱图</p> // <div className='bar-chart-wrapper'> // <BarChart width={400} height={400} data={data}> // <XAxis dataKey='name'/> // <YAxis/> // <CartesianGrid vertical={false}/> // <BarItem dataKey='uv' fill='#ff7300'/> // <BarItem dataKey='pv' fill='#387908'/> // </BarChart> // </div> // <p>水平朝向的柱图</p> // <div className='bar-chart-wrapper'> // <BarChart width={400} height={400} data={data} layout='vertical'> // <XAxis type='number'/> // <YAxis dataKey='name' type='category'/> // <CartesianGrid horizontal={false}/> // <BarItem dataKey='uv' fill='#ff7300'/> // <BarItem dataKey='pv' fill='#387908'/> // </BarChart> // </div> // <p>微型图表-柱图</p> // <div className='bar-chart-wrapper'> // <BarChart width={150} height={40} data={data}> // <BarItem dataKey='uv' fill='#ff7300'/> // </BarChart> // </div> return ( <div className='bar-charts'> <p>有正负的柱图</p> <div className='bar-chart-wrapper'> <BarChart width={1100} height={250} barGap={2} barSize={6} data={data2} margin={{top: 20, right: 20, bottom: 0, left: 20}}> <XAxis dataKey='name'/> <YAxis tickCount={7}/> <BarItem dataKey='uv' name='月环比' fill='#8884d8'/> <BarItem dataKey='pv' name='年同比' fill='#82ca9d'/> <Tooltip/> <CartesianGrid/> <Brush dataKey='name' height={30}/> <ReferenceLine type='horizontal' value={0} stroke='#666'/> </BarChart> </div> <p>变形的柱图(一)</p> <div className='bar-chart-wrapper'> <BarChart width={500} height={250} barOffset={0} data={data} margin={{top: 20, right: 20, bottom: 0, left: 20}}> <XAxis dataKey='name'/> <BarItem dataKey='uv' barGap={0} fill='#ff7300' customContent={<CustomBar/>}/> </BarChart> </div> <p>变形的柱图(二)</p> <div className='bar-chart-wrapper'> <BarChart width={500} height={250} barOffset={0} data={data} margin={{top: 20, right: 20, bottom: 20, left: 20}}> <XAxis hasAxis={false} hasTick={false} dataKey='name' customContent={<CustomAxis />}/> <BarItem dataKey='uv' barGap={0} customContent={<BarTwo/>} label/> </BarChart> </div> </div> ); } });