stories/chart.map.stories.js (661 lines of code) (raw):
import React, { useState, useEffect, useRef } from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { Wcontainer, Wmap, Wplaceholder } from '@alicloud/cloud-charts';
import adcodeMap from './data/adcode.json';
const areaData = [
{
name: '一',
data: [
{
name: '北京',
value: 10,
},
{
name: '天津',
value: 18,
},
{
name: '上海',
value: 22,
},
{
name: '重庆',
value: 39,
},
{
name: '内蒙古',
value: 22,
},
{
name: '广西',
value: 43,
},
],
},
{
name: '二',
data: [
{
name: '西藏',
value: 56,
},
{
name: '宁夏',
value: 65,
},
{
name: '新疆',
value: 69,
},
{
name: '香港',
value: 22,
},
{
name: '澳门',
value: 36,
},
{
name: '江西',
value: 95,
},
],
},
{
name: '三',
data: [
{
name: '河南',
value: 23,
},
{
name: '四川',
value: 105,
},
{
name: '贵州',
value: 141,
},
{
name: '辽宁',
value: 33,
},
{
name: '山东',
value: 135,
},
{
name: '山西',
value: 115,
},
],
},
{
name: '四',
data: [
{
name: '浙江',
value: 160,
},
{
name: '海南',
value: 49,
},
{
name: '陕西',
value: 140,
},
{
name: '福建',
value: 134,
},
{
name: '青海',
value: 197,
},
{
name: '湖北',
value: 202,
},
],
},
{
name: '五',
data: [
{
name: '甘肃',
value: 31,
},
{
name: '安徽',
value: 224,
},
{
name: '台湾',
value: 126,
},
{
name: '云南',
value: 235,
},
{
name: '黑龙江',
value: 72,
},
{
name: '广东',
value: 91,
},
],
},
{
name: '六',
data: [
{
name: '湖南',
value: 212,
},
{
name: '河北',
value: 27,
},
{
name: '吉林',
value: 22,
},
{
name: '江苏',
value: 295,
},
],
},
];
const pointData = [
{
name: '正常',
data: [
{ name: '北京', lng: 116.4551, lat: 40.2539, value: 20 },
{ name: '杭州', lng: 119.5313, lat: 29.8773, value: 10 },
],
},
{
name: '异常',
data: [
{ name: '上海', lng: 121.4648, lat: 31.2891, value: 40 },
{ name: '广州', lng: 113.5107, lat: 23.2196, value: 30 },
],
},
];
const customPointData = [
{ name: '北京', lng: 116.4551, lat: 40.2539, value: 20 },
{ name: '杭州', lng: 119.5313, lat: 29.8773, value: 10 },
{ name: '上海', lng: 121.4648, lat: 31.2891, value: 40 },
{ name: '广州', lng: 113.5107, lat: 23.2196, value: 30 },
{ name: '哈尔滨', lng: 127.9688, lat: 45.368, value: 50 },
{ name: '三亚', lng: 109.3716, lat: 18.3698, value: 60 },
{ name: '喀什', lng: 77.168, lat: 37.8534, value: 36 },
{ name: '自定义点', x: 20, y: 20, value: 36 },
];
const stories = storiesOf('Wmap', module);
stories.add('基础地图', () => (
<Wcontainer className="demos" height={400}>
<Wmap config={{}} />
</Wcontainer>
));
stories.add('带标签基础地图', () => (
<Wcontainer className="demos" height={400}>
<Wmap
config={{
label: true,
background: {
fill: 'rgba(200,200,200,0.2)',
},
}}
/>
</Wcontainer>
));
stories.add('区块地图', () => (
<Wcontainer className="demos" height={400}>
<Wmap
config={{
tooltip: {
nameFormatter(n, ...args) {
console.log(args);
return n;
},
},
}}
>
<Wmap.Area data={areaData} />
</Wmap>
</Wcontainer>
));
const baseAreaData = [
{
name: '一',
data: [
{
name: '浙江',
value: 43,
},
{
name: '陕西',
value: 43,
},
{
name: '青海',
value: 43,
},
],
},
];
const outAreaData = [
{
name: '二',
data: [
{
name: '浙江',
value: 43,
},
{
name: '陕西',
value: 43,
},
{
name: '青海',
value: 43,
},
],
},
];
stories.add('区块凸起地图', () => {
const ref = useRef();
useEffect(() => {
console.log(ref.current);
ref.current.bgMapView.interaction('brush');
ref.current.chart.on('pan', (ev) => {
// const { points } = ev;
console.log('pan', ev);
});
}, []);
return (
<Wcontainer className="demos" height={400}>
<Wmap
config={{
tooltip: false,
legend: false,
}}
ref={ref}
>
<Wmap.Area data={baseAreaData} />
<Wmap.Area
config={{
// 45ffff - 109eff
padding: [0, 0, 8, 0],
areaColors() {
return 'l(90) 0:#45ffff 1:#109eff';
},
}}
data={outAreaData}
/>
</Wmap>
</Wcontainer>
);
});
stories.add('散点地图', () => (
<Wcontainer className="demos" height={400}>
<Wmap config={{}}>
<Wmap.Point data={pointData} />
</Wmap>
</Wcontainer>
));
function Resize() {
const [width, useWidth] = useState(800);
return (
<Wcontainer
className="demos"
width={width}
height={600}
title="动态改变大小"
operation={
<button
onClick={() => {
const w = width > 700 ? 600 : 800;
useWidth(w);
action('resize')(w);
window.dispatchEvent(new Event('resize'));
}}
>
resize
</button>
}
>
<Wmap
config={
{
// labels: true,
}
}
>
<Wmap.Area data={areaData} />
<Wmap.Point data={pointData} />
<Wmap.Custom
data={customPointData}
render={(point, index) => (
<span>
{index} : {point.name}
</span>
)}
/>
</Wmap>
</Wcontainer>
);
}
stories.add('动态改变大小', () => <Resize />);
stories.add('混合使用', () => (
<Wcontainer className="demos" height={600}>
<Wmap
config={
{
// labels: true,
}
}
>
<Wmap.Area data={areaData} />
<Wmap.Point data={pointData} />
<Wmap.Custom
data={customPointData}
render={(point, index) => (
<span>
{index} : {point.name}
</span>
)}
/>
</Wmap>
</Wcontainer>
));
class Dynamic extends React.Component {
state = {
data: pointData,
};
componentDidMount() {
setTimeout(() => {
action('setData')([
{
name: '正常',
data: [
{ name: '北京', lng: 116.4551, lat: 40.2539, value: 20 },
{ name: '杭州', lng: 119.5313, lat: 29.8773, value: 10 },
{ name: '上海', lng: 121.4648, lat: 31.2891, value: 40 },
],
},
]);
this.setState({
data: [
{
name: '正常',
data: [
{ name: '北京', lng: 116.4551, lat: 40.2539, value: 20 },
{ name: '杭州', lng: 119.5313, lat: 29.8773, value: 10 },
{ name: '上海', lng: 121.4648, lat: 31.2891, value: 40 },
],
},
// {
// name: '异常',
// data: [
// ,
// { name: '广州', lng: 113.5107, lat: 23.2196, value: 30 },
// ]
// },
],
});
}, 2000);
}
render() {
return (
<Wcontainer className="demos" height={400}>
<Wmap config={{}}>
<Wmap.Point data={this.state.data} />
</Wmap>
</Wcontainer>
);
}
}
stories.add('动态数据', () => <Dynamic />);
const shootData = [
{ name: '北京', lng: 116.4551, lat: 40.2539 },
{ name: '杭州', lng: 119.5313, lat: 29.8773 },
{ name: '上海', lng: 121.4648, lat: 31.2891 },
{ name: '广州', lng: 113.5107, lat: 23.2196 },
{ name: '四川省' },
{ name: '西安' },
{ name: '哈尔滨', lng: 127.9688, lat: 45.368 },
{ name: '三亚', lng: 109.3716, lat: 18.3698 },
{ name: '喀什', lng: 77.168, lat: 37.8534 },
{ name: '自定义点1', x: -120, y: -120 },
// { name: '自定义点2', x: 140, y: -120 },
// { name: '自定义点3', x: 140, y: 120 },
// { name: '自定义点4', x: -120, y: 120 },
];
function ShootDemo() {
const log = action('setData');
const [width, useWidth] = useState(800);
const [data, setData] = useState([]);
useEffect(() => {
const dataLen = shootData.length;
const changeData = () => {
const newData = [];
const len = Math.round(Math.random() * 10) + 10;
for (let i = 0; i < len; i++) {
let fIndex = Math.round(Math.random() * (dataLen - 1));
let tIndex = (fIndex + Math.round(Math.random() * (dataLen / 2)) + 1) % dataLen;
if (fIndex === tIndex) {
tIndex = (fIndex + 1) % dataLen;
}
newData.push({
from: Object.assign({}, shootData[fIndex]),
to: Object.assign({}, shootData[tIndex]),
});
}
log(newData);
setData(newData);
};
changeData();
const timer = setInterval(() => {
changeData();
}, 8000);
return () => clearInterval(timer);
}, []);
return (
<Wcontainer
className="demos"
width={width}
height={600}
title="点击右侧测试改变大小"
operation={
<button
onClick={() => {
const w = width > 700 ? 600 : 800;
useWidth(w);
action('resize')(w);
window.dispatchEvent(new Event('resize'));
}}
>
resize
</button>
}
>
<Wmap>
<Wmap.Shoot data={data} />
<Wmap.Custom
data={shootData}
render={(point, index) => (
<span>
{index} : {point.name}
</span>
)}
/>
</Wmap>
</Wcontainer>
);
}
stories.add('飞线地图', () => <ShootDemo />);
function DoubleShootDemo() {
const log = action('setData');
const log2 = action('setDoubleData');
const shootConfig = {
maxFps: 30,
};
const [data, setData] = useState([]);
const [doubleData, setDoubleData] = useState([]);
useEffect(() => {
const dataLen = shootData.length;
const changeData = () => {
const newData = [];
const newDoubleData = [];
const len = Math.round(Math.random() * 10) + 10;
for (let i = 0; i < len; i++) {
let fIndex = Math.round(Math.random() * (dataLen - 1));
let tIndex = (fIndex + Math.round(Math.random() * (dataLen / 2)) + 1) % dataLen;
if (fIndex === tIndex) {
tIndex = fIndex + 1;
}
newData.push({
from: Object.assign({}, shootData[fIndex]),
to: Object.assign({}, shootData[tIndex]),
});
newDoubleData.push({
from: Object.assign({}, shootData[fIndex]),
to: Object.assign({}, shootData[tIndex]),
});
}
log(newData);
setData(newData);
setTimeout(() => {
setDoubleData(newDoubleData);
log2(newDoubleData);
}, 4000);
};
changeData();
const timer = setInterval(() => {
changeData();
}, 8000);
return () => clearInterval(timer);
}, []);
return (
<Wcontainer className="demos" height={600}>
<Wmap>
<Wmap.Shoot data={data} config={shootConfig} debug={1} />
<Wmap.Shoot data={doubleData} config={shootConfig} debug={2} />
<Wmap.Custom
data={shootData}
render={(point, index) => (
<span>
{index} : {point.name}
</span>
)}
/>
</Wmap>
</Wcontainer>
);
}
stories.add('双层飞线地图', () => <DoubleShootDemo />);
// let maxDepth = 0;
// function getTreeDepth(data, depth) {
// if (depth > maxDepth) {
// maxDepth = depth;
// }
// data.forEach((d) => {
// if (Array.isArray(d)) {
// getTreeDepth(d, depth + 1);
// }
// });
// }
// getTreeDepth(taiwanData60.features[0].geometry.coordinates, 0);
// taiwanData60.features[0].geometry.coordinates.forEach((polygon) => {
// polygon[0].reverse();
// });
// console.log(maxDepth);
stories.add('自定义地图数据', () => {
const [loading, setLoading] = React.useState(false);
const [geoData, setGeoData] = React.useState(undefined);
React.useEffect(() => {
setLoading(true);
// 示例中使用 DataV.GeoAtlas 工具作为数据源:https://datav.aliyun.com/tools/atlas/
// 实际使用请使用静态化数据保证稳定性。
fetch('https://geo.datav.aliyun.com/areas_v2/bound/330000_full.json')
.then((res) => res.json())
.then((res) => {
setGeoData(res);
setLoading(false);
})
.catch((e) => {
setGeoData(undefined);
setLoading(false);
});
}, []);
return (
<Wcontainer>
{loading ? (
<Wplaceholder loading />
) : (
<Wmap
height={500}
geoData={geoData}
config={{
label: true,
showSouthChinaSea: false,
}}
/>
)}
</Wcontainer>
);
});
stories.add('地图数据选择器', () => {
const [code, setCode] = React.useState('');
const [loading, setLoading] = React.useState(false);
const [geoData, setGeoData] = React.useState(undefined);
const historyRef = React.useRef([]);
React.useEffect(() => {
if (code) {
setLoading(true);
// 示例中使用 DataV.GeoAtlas 工具作为数据源:https://datav.aliyun.com/tools/atlas/
// 实际使用请使用静态化数据保证稳定性。
fetch(`https://geo.datav.aliyun.com/areas_v2/bound/${code}_full.json`)
.then((res) => res.json())
.then((res) => {
setGeoData(res);
setLoading(false);
})
.catch((e) => {
setCode('');
setGeoData(undefined);
setLoading(false);
});
} else {
setLoading(true);
setGeoData(undefined);
requestAnimationFrame(() => {
setLoading(false);
});
}
}, [code]);
function handleGetChart(chart) {
if (chart) {
chart.interaction('element-highlight');
chart.on('polygon:click', function (e) {
const name = e && e.data && e.data.data && e.data.data.name;
if (name && adcodeMap[name]) {
historyRef.current.push({
name,
adcode: adcodeMap[name],
});
setCode(adcodeMap[name]);
}
});
}
}
return (
<Wcontainer>
{loading ? (
<Wplaceholder loading />
) : (
<Wmap
height={500}
geoData={geoData}
config={{
label: true,
showSouthChinaSea: false,
background: {
cursor: 'pointer',
},
}}
getChartInstance={handleGetChart}
/>
)}
{code && (
<div>
当前区域:{historyRef.current[historyRef.current.length - 1].name}
<button
onClick={() => {
historyRef.current.pop();
if (historyRef.current.length === 0) {
setCode('');
} else {
setCode(historyRef.current[historyRef.current.length - 1].adcode);
}
}}
>
返回上一级
</button>
<a href={`https://geo.datav.aliyun.com/areas_v2/bound/${code}_full.json`} target="_blank">
下载数据
</a>
</div>
)}
</Wcontainer>
);
});