Skip to content

Commit

Permalink
docs: echarts使用
Browse files Browse the repository at this point in the history
  • Loading branch information
wang1xiang committed Jun 14, 2024
1 parent 152a81c commit cb687bc
Show file tree
Hide file tree
Showing 7 changed files with 628 additions and 0 deletions.
2 changes: 2 additions & 0 deletions docs/flutter/flutter-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,8 @@ open -a Simulator

## 第一个 flutter 应用

阅读[给 Web 开发者的 Flutter 指南](https://docs.flutter.cn/get-started/flutter-for/web-devs)

使用 Flutter 应用模板创建第一个 flutter 应用

1. `cmd + shift + p` 输入 `flutter` 选择 `Flutter: New Project` 创建一个项目`,首次需要设置 flutter SDK 位置
Expand Down
8 changes: 8 additions & 0 deletions docs/node/express-mysql2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
date: 2024-6-14
title: express-mysql2
tags:
- node
describe: express-mysql2
---

368 changes: 368 additions & 0 deletions docs/work/echarts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,368 @@
---
date: 2024-6-14
title: vue3 项目使用Echarts使用记录
tags:
- work
describe: Echarts使用记录
---

## 按需引入 ECharts 图表和组件

项目中只需要使用 ECharts 中的柱状图、折线图和饼图等基本图表类型,全量引入过大。考虑使用按需引入的方式,仅导入我们用到的图表组件:

1. 添加 echarts 依赖

```bash
npm install echarts --save
```

2. 生成 echarts.js 文件,按需加载的文件

```js
import * as echarts from 'echarts/core'
import { BarChart, LineChart, PieChart } from 'echarts/charts'
import {
TitleComponent,
TooltipComponent,
GridComponent,
// 数据集组件
DatasetComponent,
// 内置数据转换器组件 (filter, sort)
TransformComponent,
// legend图例
LegendComponent,
// 工具栏。内置有导出图片,数据视图,动态类型切换,数据区域缩放,重置五个工具。
ToolboxComponent,
} from 'echarts/components'
import { LabelLayout, UniversalTransition } from 'echarts/features'
import { CanvasRenderer } from 'echarts/renderers'
import type {
// 系列类型的定义后缀都为 SeriesOption
BarSeriesOption,
LineSeriesOption,
PieSeriesOption,
} from 'echarts/charts'
import type {
// 组件类型的定义后缀都为 ComponentOption
TitleComponentOption,
TooltipComponentOption,
GridComponentOption,
DatasetComponentOption,
LegendComponentOption,
ToolboxComponentOption,
} from 'echarts/components'
import type { ComposeOption } from 'echarts/core'

// 通过 ComposeOption 来组合出一个只有必须组件和图表的 Option 类型
export type ECOption = ComposeOption<
| BarSeriesOption
| LineSeriesOption
| PieSeriesOption
| TitleComponentOption
| LegendComponentOption
| ToolboxComponentOption
| TooltipComponentOption
| GridComponentOption
| DatasetComponentOption
>

// 注册必须的组件
echarts.use([
TitleComponent,
LegendComponent,
ToolboxComponent,
TooltipComponent,
GridComponent,
DatasetComponent,
TransformComponent,
BarChart,
LineChart,
PieChart,
LabelLayout,
UniversalTransition,
CanvasRenderer,
])

export { echarts }
```

这样在 vue 文件中需要使用 ECharts 时可以直接引入封装好的 echarts.ts ,当增加了新的图表类型(如雷达图、热力图、桑基图等)时直接修改 echarts.ts 文件就可以,提高使用按需引入的便捷性

## 组件封装

### Hooks

封装一个统一的 useEChart Hook 函数,主要功能:

1. 统一绘制图表方法
2. 监听 props 变化,重新绘制
3. 监听 resize 变化,执行 resize 事件
4. 修改默认图表颜色,用 Antv G2 的配色方案(没话说,就是好看 😄)
5. 函数接收 customOptions 修改默认配置,这样方便所有图表共同使用

```js
import type { ShallowRef } from 'vue'
import { onMounted, ref } from 'vue'
import { debounce } from 'lodash'
import type { EChartsType } from 'echarts/types/dist/core'
import { type ECOption, echarts } from '@/utils/echarts'
import type {
DataZoomComponentOption,
LegendComponentOption,
LineSeriesOption,
XAXisOption,
YAXisOption,
} from 'echarts/types/dist/shared'
/** category 默认配色 来源:https://github.com/antvis/G2/blob/v5/src/theme/light.ts */
export const CATEGORY_COLORS: string[] = [
'#1783FF',
'#F0884D',
'#D580FF',
'#7863FF',
'#60C42D',
'#BD8F24',
'#FF80CA',
'#2491B3',
'#17C76F',
]

export default function useChart(props, customOptions?: ECOption) {
/** 所有图表的默认配置 */
const DEFAULT_OPTIONS: ECOption = {
series: [
{
name: '数量',
type: 'line',
emphasis: {
focus: 'self',
},
label: {
show: true,
position: 'inside',
color: '#fff',
},
data: props.data,
},
],
xAxis: [
{
type: 'category',
axisTick: {
show: false,
},
data: props.xAxisData,
},
],
yAxis: [
{
type: 'value',
minInterval: 1,
},
],
legend: {
show: true,
type: 'scroll',
orient: 'horizontal',
top: 25,
left: 'center',
},
}
// 要渲染的Dom元素
const chartDom: Ref<HTMLDivElement | null> = ref(null)
// 渲染的chart对象要用shallowRef
const chart: ShallowRef<EChartsType | null | undefined> = shallowRef(null)

const getHeight = computed(() => {
return typeof props.height === 'number' ? `${props.height}px` : props.height
})

watch(() => props, drawChart, {
deep: true,
})

// 绘制
function drawChart() {
const getSingleOption = (type) =>
props[type] ? props[type] : customOptions?.[type] || DEFAULT_OPTIONS[type]

const series: LineSeriesOption[] = getSingleOption('series')
const xAxis: XAXisOption[] = getSingleOption('xAxis')
const yAxis: YAXisOption[] = getSingleOption('yAxis')
const legend: LegendComponentOption = getSingleOption('legend')
const dataZoom: DataZoomComponentOption[] = getSingleOption('dataZoom')

const options: ECOption = {
// category自定义颜色
// https://echarts.apache.org/zh/option.html#color
color: CATEGORY_COLORS,
backgroundColor: 'transparent',
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
},
legend,
grid: {
left: 10,
right: 10,
bottom: props.dataZoom ? 40 : 10,
containLabel: true,
},
// 右上角工具栏
toolbox: {
show: false,
feature: {
magicType: {
type: ['line', 'bar'],
},
dataView: {
readOnly: false,
},
saveAsImage: {},
},
},
dataset: {
source: props.datasetSource,
},
xAxis,
yAxis,
dataZoom,
series,
}
// 开启notMerge保证配置数据不会叠加
chart.value?.setOption(options, {
notMerge: true,
})
}

// 使用防抖debounce函数,减少resize的次数
const chartResizeHandler = debounce(() => chart.value?.resize(), 100)
onMounted(() => window.addEventListener('resize', chartResizeHandler))
onBeforeUnmount(() =>
window.removeEventListener('resize', chartResizeHandler)
)

onMounted(() => {
chart.value = echarts.init(chartDom.value)
drawChart()
})

return {
chartDom,
getHeight,
}
}
```
### 组件
```vue
// BarChart.vue
<template>
<div ref="chartDom" :style="{ height: getHeight }"></div>
</template>

<script setup lang="ts">
import type {
BarSeriesOption,
DataZoomComponentOption,
LegendComponentOption,
XAXisOption,
YAXisOption,
} from 'echarts/types/dist/shared'
const props = withDefaults(
defineProps<{
/** 数据 */
data?: string | number[]
/** x轴数据 */
xAxisData?: string[]
/** 系列配置 */
series?: BarSeriesOption[]
/** x轴配置 */
xAxis?: XAXisOption[]
/** y轴配置 */
yAxis?: YAXisOption[]
/** 图例配置 */
legend?: LegendComponentOption
/** 区域缩放配置 */
dataZoom?: DataZoomComponentOption[]
/** 图形高度 */
height?: number | string
/** 数据集 */
datasetSource?: any[]
}>(),
{
data: () => [],
xAxisData: () => [],
}
)
const { getHeight, chartDom } = useEChart(props)
</script>
```
```vue
// PieChart.vue
<template>
<div ref="chartDom" :style="{ height: getHeight }"></div>
</template>

<script setup lang="ts">
import type {
DataZoomComponentOption,
LegendComponentOption,
PieSeriesOption,
} from 'echarts/types/dist/shared'
import type { ECOption } from '@/utils/echarts'

const DEFAULT_OPTIONS: ECOption = {
tooltip: {
trigger: 'item',
},
legend: {
orient: 'vertical',
left: 'left',
},
}
const props = withDefaults(
defineProps<{
/** 数据 */
data?: { name: string; value: number }[]
/** 系列配置 */
series?: PieSeriesOption[]
/** 图例配置 */
legend?: LegendComponentOption
/** 区域缩放配置 */
dataZoom?: DataZoomComponentOption[]
/** 图形高度 */
height?: number | string
/** 数据集 */
datasetSource?: any[]
}>(),
{
data: () => [],
}
)
const { chartDom, getHeight } = useEChart(props, DEFAULT_OPTIONS)
</script>
```
扇形图默认的配置与 useEChart hooks 中提供的默认配置不通用,通过传入 DEFAULT_OPTIONS 传入扇形图的默认配置
### 使用
```html
<pie-chart
:height="400"
:x-axis="[{ type: 'category' }]"
:dataset-source="dataset"
:series="pieSeries"
/>

<line-chart
:height="400"
:x-axis="[{ type: 'category' }]"
:dataset-source="dataset"
:series="lineSeries"
/>
```
Loading

0 comments on commit cb687bc

Please sign in to comment.