stories/chart.line.stories.js (834 lines of code) (raw):

import React, { useEffect, useState } from 'react'; import { storiesOf } from '@storybook/react'; import { action } from '@storybook/addon-actions'; import { withKnobs, select } from '@storybook/addon-knobs'; import { Wcontainer, Wline } from '@alicloud/cloud-charts'; const data = [ { name: '机房A', data: [ [1483372800000, 4092], [1483459200000, 1592], [1483545600000, 3714], [1483632000000, 4854], [1483718400000, 6514], [1483804800000, 9022], [1483891200000, 6023], [1483977600000, 4018], ], }, { name: '机房B', yAxis: 1, // visible: false, data: [ [1483372800000, 6051], [1483459200000, 3278], [1483545600000, 5175], [1483632000000, 6548], [1483718400000, 9048], [1483804800000, 11394], [1483891200000, 8597], [1483977600000, 6588], ], }, ]; const stories = storiesOf('Wline', module); stories.addDecorator(withKnobs); stories.add('折线图', () => ( <Wline height="300" data={data} config={{ yAxis: [ { grouping: true, }, ], }} /> )); stories.add('平滑曲线图', () => ( <Wcontainer className="demos"> <Wline height="300" config={{ spline: true, }} data={data} /> </Wcontainer> )); stories.add('带点折线图', () => ( <Wcontainer className="demos"> <Wline height="300" config={{ symbol: true, }} data={data} /> </Wcontainer> )); stories.add('面积折线图', () => ( <Wcontainer className="demos"> <Wline height="300" config={{ area: true, }} data={data} /> </Wcontainer> )); stories.add('面积曲线图', () => ( <Wcontainer className="demos"> <Wline height="300" config={{ area: true, spline: true, guide: { line: [ { top: true, text: { title: '水平线', position: 'start', // align: 'start', }, // status: 'warning', axis: 'y', value: 7000, // 自定义样式,可设置为虚线 style: { lineDash: [4, 4], }, }, { top: true, text: { title: '垂直线', position: 'end', align: 'center', }, status: 'none', axis: 'x', value: 1483718400000, }, ], filter: { status: 'error', // normal | success | warning | error // 区域位置 axis: 'x', value: [1483718400000, 'max'], }, }, }} data={data} /> </Wcontainer> )); stories.add('堆叠面积图', () => ( <Wcontainer className="demos"> <Wline height="300" config={{ area: true, stack: true, }} data={data} /> </Wcontainer> )); stories.add('带网格线', () => ( <Wcontainer className="demos"> <Wline height="300" config={{ grid: true, }} data={data} /> </Wcontainer> )); stories.add('双轴折线图', () => ( <Wcontainer className="demos"> <Wline height="300" config={{ yAxis: [{}, {}], area: true, guide: { line: [ { // 显示标题相关 text: { title: '警戒线', autoRotate: false, }, status: 'error', // normal | success | warning | error // 线位置 axis: 'y1', value: 5000, }, ], }, }} data={data} /> </Wcontainer> )); stories.add('拖拽缩放', () => ( <Wcontainer className="demos"> <Wline height="300" config={{ zoom: true, }} data={data} event={{ 'zoom:start': (s) => { action('zoom:start')(s); }, 'zoom:end': (s) => { action('zoom:end')(s); }, 'zoom:reset': (s) => { action('zoom:reset')(s); }, }} /> </Wcontainer> )); const stepOptions = { 关闭: null, 默认: true, '水平-垂直': 'hv', '垂直-水平': 'vh', '水平-垂直-水平': 'hvh', '垂直-水平-垂直': 'vhv', }; stories.add('阶梯折线图', () => ( <Wcontainer className="demos"> <Wline height="300" config={{ // step: select('阶梯形状', stepOptions, null), step: true, }} data={data} /> </Wcontainer> )); const singleData = [ { name: '机房A', data: [[1483632000000, 4854]], }, { name: '机房B', yAxis: 1, data: [[1483632000000, 6548]], }, ]; stories.add('单个点折线图', () => ( <Wcontainer className="demos"> <Wline height="300" data={singleData} force /> </Wcontainer> )); stories.add('Tooltip 设置', () => ( <Wcontainer className="demos"> <Wline height="300" config={{ tooltip: { titleFormatter: function (v) { return 'title: ' + v; }, nameFormatter: function (v) { return 'name: ' + v; }, valueFormatter: function (v) { return 'value: ' + v; }, }, }} data={data} /> </Wcontainer> )); const data1 = []; const data2 = []; let now = Date.now(); for (var i = 0; i < 30; i++) { let t = now - (30 - i) * 1000; data1.push([t, Math.round(Math.random() * 60) + 300]); data2.push([t, Math.round(Math.random() * 60) + 300]); } class NewData extends React.Component { state = { data: [ { name: '机房A', data: data1, }, { name: '机房B', data: data2, }, ], }; componentDidMount() { setInterval(() => { let t = Date.now(); data1.push([t, Math.round(Math.random() * 60) + 300]); data2.push([t, Math.round(Math.random() * 60) + 300]); data1.shift(); data2.shift(); this.setState({ data: [ { name: '机房A', data: data1, }, { name: '机房B', data: data2, }, ], }); }, 1000); } render() { return ( <Wcontainer className="demos"> <Wline height="300" config={{}} data={this.state.data} /> </Wcontainer> ); } } stories.add('动态数据', () => <NewData />); stories.add('修改shape', () => ( <Wcontainer className="demos"> <Wline height="300" config={{ // guide: { // line: { // top: true, // text: '80%', // status: 'error', // axis: 'x', // value: 1483718400000, // }, // filter: { // status: 'error', // normal | success | warning | error // // 区域位置 // axis: 'x', // value: [1483718400000, 'max'], // }, // }, area: true, // 还要考虑选中状态样式 symbol: { // shape支持函数? shape: 'square', // 内置图形, 'circle', 'diamond', 'square', 'triangle', 'triangle-down' size: 6, // 大小 geomStyle: { // 样式 // stroke: 'red', fill: 'red', lineWidth: 1, }, }, }} data={data} /> </Wcontainer> )); stories.add('数据从有到无', () => { const [d, setD] = useState(data); useEffect(() => { const timer = setTimeout(() => { setD([]); }, 2000); return () => clearTimeout(timer); }, []); return ( <Wcontainer className="demos"> <Wline height="300" config={{ area: true, legend: { nameFormatter: function (v, data) { return 'name:' + v; }, valueFormatter: function (v, data) { return v + '%'; }, }, }} data={d} /> </Wcontainer> ); }); // // 齐全度展示图 // const attendData = [ // { // x: 1483372800000, // y: 1, // type: 'normal', // }, // { // x: 1483459200000, // y: 1, // type: 'normal', // }, // { // x: 1483545600000, // y: 1, // type: 'normal', // }, // { // x: 1483632000000, // y: 1, // type: 'error', // }, // { // x: 1483718400000, // y: 1, // type: 'normal', // }, // { // x: 1483804800000, // y: 1, // type: 'normal', // }, // { // x: 1483891200000, // y: 1, // type: 'normal', // }, // { // x: 1483977600000, // y: 1, // type: 'error' // } // ].map(d => { // return { // ...d, // detail: [ // { name: 'all', value: 100 }, // { name: '111', value: 80 }, // { name: '222', value: 20 }, // ], // }; // }); // // const attendCustomChart = { // // 不转换格式 // convertData: false, // init(chart, config, data) { // chart.source(data, { // x: { // type: 'timeCat', // mask: 'YYYY-MM-DD HH:mm:ss', // }, // // 柱高度为 0~1,设置 Y 轴跨度为 -1~2,保证柱高度占中心三分之一 // y: { // min: -1, // max: 2, // } // }); // // // 关闭坐标轴 // chart.axis(false); // // // 关闭图例 // chart.legend(false); // // chart.tooltip({ // crosshairs: { // type: 'y' // }, // inPlot: false, // }); // // // 自定义 tooltip 展示 // chart.on('tooltip:change', function(ev) { // const items = ev.items; // tooltip显示的项 // const origin = items[0]; // 将一条数据改成多条数据 // const detail = origin.point._origin.detail; // items.splice(0); // 清空 // detail.forEach((d) => { // const color = d.value < 100 ? Util.getStatusColor('error') : Util.getStatusColor('success'); // items.push(Object.assign({}, origin, { // name: d.name, // value: d.value, // color: color, // marker: { // ...origin.marker, // fill: color, // }, // })); // }); // }); // // // 柱图模拟多色直线 // chart.interval() // .position('x*y') // .shape('funnel') // .color('type', (type) => { // if (type === 'error') { // return Util.getStatusColor('error'); // } // return Util.getStatusColor('success'); // }); // // chart.render(); // } // }; // // function Attend() { // return ( // <Wcontainer> // <Wline height="24" data={attendData} customChart={attendCustomChart} /> // </Wcontainer> // ); // } // stories.add('齐全度展示图', () => ( // <Attend /> // )); const rangeAreaData = [ { name: '平均值', data: [ [1483372800000, 3592], [1483459200000, 6092], [1483545600000, 5714], [1483632000000, 5984], [1483718400000, 8514], [1483804800000, 8666], [1483891200000, 8023], [1483977600000, 6018], ], }, { name: '范围', data: [ [1483372800000, [1592, 5135]], [1483459200000, [4092, 8341]], [1483545600000, [3714, 7561]], [1483632000000, [3984, 8321]], [1483718400000, [6514, 10000]], [1483804800000, [6666, 10000]], [1483891200000, [6023, 10000]], [1483977600000, [4018, 8654]], ], }, ]; stories.add('区域面积图', () => ( <Wcontainer className="demos"> <Wline height="300" config={{ area: { geomStyle(x, y, type, extra) { if (type === '平均值') { return { opacity: 0, fill: 'transparent', }; } return {}; }, }, geomStyle(x, y, type, extra) { if (type === '范围') { return { opacity: 0, fill: 'transparent', stroke: 'transparent', }; } return {}; }, }} data={rangeAreaData} /> </Wcontainer> )); stories.add('带虚线图', () => ( <Wcontainer className="demos"> <Wline height="300" config={{ geomStyle: { lineDash(x, y, type) { console.log('dash', x, y, type); if (type === '机房B') { return [4, 4]; } return null; }, lineWidth(x, y, type) { // console.log('width', x, y, type); if (type === '异常点') { return 0; } return 2; }, }, symbol: { size: (type) => { if (type === '异常点') { return 4; } else { return 0; } }, }, // geomStyle(x, y, type) { // if (type === '机房B') { // return { // lineDash: [4,4], // } // } // return {}; // } }} data={data} /> </Wcontainer> )); stories.add('带区域渲染折线 changeSize', () => { const c = { // "padding": [ // 10, // 20, // 30, // 30 // ], yAxis: { min: 0, }, xAxis: { type: 'time', mask: 'YYYY-MM-DD', }, tooltip: {}, guide: { area: { axis: 'y', value: [51, 70], status: 'warning', }, filter: { axis: 'y', value: [51, 70], status: 'warning', }, }, colors: ['#A5B0BD'], symbol: true, legend: false, }; return ( <Wline config={c} data={[ { name: '资源健康度', data: [ [1649174400000, 79], [1650038400000, 0], [1650902400000, 79.56], [1651766400000, 79.62], [1652198400000, 0], ], }, ]} /> ); }); const multipleData = [ { name: '', data: [ [1483372800000, 1592], [1483459200000, 1092], [1483545600000, 1714], [1483632000000, 2984], [1483718400000, 3514], [1483804800000, 3666], [1483891200000, 3023], [1483977600000, 3018], ], }, { name: '', data: [ [1483372800000, 2592], [1483459200000, 2092], [1483545600000, 3714], [1483632000000, 4984], [1483718400000, 7514], [1483804800000, 7666], [1483891200000, 7023], [1483977600000, 5018], ], }, { name: '机房C', data: [ [1483372800000, 7592], [1483459200000, 9092], [1483545600000, 8714], [1483632000000, 8984], [1483718400000, 11514], [1483804800000, 11666], [1483891200000, 11023], [1483977600000, 9018], ], }, ]; stories.add('不指定name', () => <Wline height="300" data={multipleData} />); const zeroData = [ { name: '机房A', data: [ [1483372800000, 4092], [1483459200000, 1592], [1483545600000, 3714], [1483632000000, 4854], [1483718400000, 6514], [1483804800000, 9022], [1483891200000, 6023], [1483977600000, 4018], ], }, { name: '机房B', yAxis: 1, // visible: false, data: [ [1483372800000, 0], [1483459200000, 0], [1483545600000, 0], [1483632000000, 0], [1483718400000, 0], [1483804800000, 0], [1483891200000, 0], [1483977600000, 0], ], }, { name: '机房C', data: [ [1483372800000, 1592], [1483459200000, 1092], [1483545600000, 1714], [1483632000000, 2984], [1483718400000, 3514], [1483804800000, 3666], [1483891200000, 3023], [1483977600000, 3018], ], }, { name: '机房D', data: [ [1483372800000, 2592], [1483459200000, 2092], [1483545600000, 3714], [1483632000000, 4984], [1483718400000, 7514], [1483804800000, 7666], [1483891200000, 7023], [1483977600000, 5018], ], }, { name: '机房Es', data: [ [1483372800000, 7592], [1483459200000, 9092], [1483545600000, 8714], [1483632000000, 8984], [1483718400000, 11514], [1483804800000, 11666], [1483891200000, 11023], [1483977600000, 9018], ], }, ]; stories.add('可筛选出全为0的线图', () => <Wline height="300" data={zeroData} />); stories.add('极端数据场景(少)', () => { const [d, setD] = useState([ { name: '浏览器占比', data: [ [1483459200000, 1592], [1483545600000, 3714], [1483632000000, 4854], [1483718400000, 6514], ], }, ]); const [d2, setD2] = useState(data); const [d3, setD3] = useState(data); useEffect(() => { const timer = setTimeout(() => { setD(data); setD2([ { name: '浏览器占比', data: [ [1483459200000, 1592], [1483545600000, 3714], [1483632000000, 4854], [1483718400000, 6514], ], }, ]); }, 2000); setD3(); return () => clearTimeout(timer); }, []); return ( <> <Wcontainer className="demos" title="极端少-不极端"> <Wline height="300" config={{ area: true, legend: { nameFormatter: function (v, data) { return 'name:' + v; }, valueFormatter: function (v, data) { return v + '%'; }, }, }} data={d} // force // 测试强制开关 /> </Wcontainer> <Wcontainer title="不极端-极端少"> <Wline height="300" config={{ area: true, legend: { nameFormatter: function (v, data) { return 'name:' + v; }, valueFormatter: function (v, data) { return v + '%'; }, }, }} data={d2} /> </Wcontainer> <Wcontainer className="demos" title="不极端-大数据"> <Wline height="300" config={{ area: true, legend: { nameFormatter: function (v, data) { return 'name:' + v; }, valueFormatter: function (v, data) { return v + '%'; }, }, }} data={d} /> </Wcontainer> </> ); }); const timeData = { year_1: [ // 跨年,间隔大于一年 { name: '机房A', data: [ [1483372800000, 1592], [1583372800000, 1592], [1683561600000, 4092], ], }, ], year_2: [ // 跨年,间隔小于半年,大于1个月 { name: '机房A2222222222222222222222222222222222231231231fwefq141331231231fwefq1413', data: [ [1670515200000, 1592], // [1673193600000, 2222], // [1673280000000, 4092], ], }, ], year_3: [ // 跨年,间隔为1个月 { name: '机房A', data: [ [1670515200000, 2222], [1673193600000, 2222], [1675872000000, 2222], [1678291200000, 2222], [1680969600000, 1592], [1683561600000, 4092], ], }, ], }; stories.add('测试跨度', () => ( <div style={{ display: 'flex', }} > <div style={{ flex: '0 0 calc(50% - 10px)', }} > <Wline height="300" data={timeData.year_1} config={ { // xAxis: { // nice: false // } } } /> </div> <div style={{ flex: '0 0 calc(50% - 10px)', }} > <Wline height="300" data={timeData.year_2} config={{}} /> </div> </div> )); const onePoint = [ { name: '浏览器占比', data: [[1483459200000, 1592]], }, ]; const twoPoint = [ { name: '浏览器占比', data: [ [1670515200000, 2222], [1683561600000, 4092], ], }, ]; const twoLine = [ { name: 'A', data: [[1670515200000, 2222]], }, { name: 'B', data: [[1683561600000, 4092]], }, ]; stories.add('极端数据测试', () => ( <div style={{ display: 'flex', flexDirection: 'column' }}> <Wline height="300" data={onePoint} config={{ label: { labelFormatter: () => 'test' } }} /> <Wline height="300" data={twoPoint} config={{}} /> <Wline height="300" data={twoLine} config={{}} /> </div> )); stories.add('带标签折线图', () => ( <Wcontainer className="demos"> <Wline height="300" config={{ symbol: true, label: true, }} data={data} /> </Wcontainer> )); stories.add('legend单选', () => ( <Wline height="300" data={data} config={{ legend: { useReverseChecked: false } }} /> )); const labelData = [ { name: '小数', data: [[1741055716000, 0.04166666666666667]], }, ]; const labelData2 = [ { name: '进位', data: [[1741055716000, -100000]], }, ]; stories.add('label格式化', () => ( <Wline height="300" data={labelData2} config={{ yAxis: { // valueType: 'disk_1000', // unit: 'B', needUnitTransform: true, valueType: 'custom', customCarryUnits: ",k,m", // ['k', 'm'], // customCarryThreshold: 2000, addonTextAfter: '/s' }, tooltip: { // customTooltip: true, // lockable: true }, legend: { table: { statistics: ['min', 'max', 'current'] } } }} /> ));