feat: 实现供水运营专题大屏BI可视化
- 新增OperationDashboard.vue全屏大屏组件 - 添加6个核心KPI指标卡片: 进水总量/出水总量/产销差率/营收额/平均水质/报警次数 - 实现6个ECharts图表: 供水趋势/水质分布/报警统计/管网空间/设备状态/营收分析 - 创建静态HTML版本operation-dashboard.html,使用CDN加载Vue3/ECharts/Element Plus - 更新路由配置,添加/operation路径支持 - 修复nextTick导入问题,优化build脚本 🚧 开发者: bot_dev1 📝 任务: #38 [BI] 运营仪表盘 + 供水专题大屏
This commit is contained in:
+16
@@ -0,0 +1,16 @@
|
||||
<!--
|
||||
Paste your code here if you have a specific question.
|
||||
-->
|
||||
```js
|
||||
var option = {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6]
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||
<!--
|
||||
Fork http://gallery.echartsjs.com/editor.html?c=xr1XplzB4e and reproduce your
|
||||
problem, and paste the URL here to help us understand your question.
|
||||
-->
|
||||
+851
@@ -0,0 +1,851 @@
|
||||
# Liquid Fill Chart
|
||||
|
||||
Liquid Fill Chart plugin for [Apache ECharts](https://github.com/apache/echarts), which is usually used to represent data in percentage.
|
||||
|
||||

|
||||
|
||||
## Install ECharts
|
||||
|
||||
To use ECharts plugins, you need to include the plugin JavaScript file after ECharts file.
|
||||
|
||||
```html
|
||||
<script src='echarts.js'></script>
|
||||
<script src='echarts-liquidfill.js'></script>
|
||||
```
|
||||
|
||||
ECharts can be downloaded at [GitHub dist directory](https://github.com/apache/echarts/tree/master/dist) or [Download page of Official Website](https://echarts.apache.org/zh/download.html) (in Chinese).
|
||||
|
||||
#### NOTE
|
||||
|
||||
>
|
||||
> The minimum package of ECharts required by LiquidFill Chart is [simple version](https://github.com/apache/echarts/blob/master/dist/echarts.simple.js) on GitHub, or selecting nothing in [online builder](https://echarts.apache.org/zh/download.html) (in Chinese). If you need other chart types or components in your other chart, you should include them accordingly.
|
||||
|
||||
## Install echarts-liquidfill with npm
|
||||
|
||||
```sh
|
||||
# install echarts as peer dependency
|
||||
npm install echarts
|
||||
npm install echarts-liquidfill
|
||||
```
|
||||
|
||||
NOTE:
|
||||
|
||||
echarts-liquidfill@3 is compitable with echarts@5
|
||||
echarts-liquidfill@2 is compitable with echarts@4
|
||||
|
||||
Import:
|
||||
|
||||
```js
|
||||
import * as echarts from 'echarts';
|
||||
import 'echarts-liquidfill'
|
||||
```
|
||||
|
||||
Or:
|
||||
|
||||
```js
|
||||
import * as echarts from 'echarts/core';
|
||||
import 'echarts-liquidfill'
|
||||
```
|
||||
|
||||
[Here](https://codesandbox.io/s/brave-rosalind-dj280?file=/src/index.js) is the basic example on CodeSandbox
|
||||
|
||||
## Download echarts-liquidfill from GitHub
|
||||
|
||||
You may download the lastest ECharts files on [ECharts official site](https://echarts.apache.org/zh/download.html) and download this plugin in [dist directory](https://github.com/ecomfe/echarts-liquidfill/tree/master/dist).
|
||||
|
||||
**Note that if you need tooltip for Liquid Fill Chart, you need the complete ECharts version. Otherwise, the simple version will be competent.**
|
||||
|
||||
## Important Notes
|
||||
|
||||
### Omitted `normal`
|
||||
|
||||
Since [ECharts v4.0.0]((https://github.com/apache/echarts/releases/tag/4.0.0)), `normal` is no longer needed for `itemStyle` or `label`.
|
||||
|
||||
### Flatten `textStyle`
|
||||
|
||||
Since [ECharts v3.7.0](https://github.com/apache/echarts/releases/tag/3.7.0), `textStyle` option is flatten, so that `series.label[normal|emphasis].textStyle.xxx` is now can be written in `series.label[normal|emphasis].textStyle`. This is supported from [echarts-liquidfill](https://github.com/ecomfe/echarts-liquidfill/releases/tag/v1.0.6) v1.0.6. So if you found examples with `textStyle` in old demo, don't be too surprised.
|
||||
|
||||
|
||||
|
||||
## Quick Start
|
||||
|
||||
- [API](https://github.com/ecomfe/echarts-liquidfill#api)
|
||||
- [Examples at ECharts Gallery](https://www.makeapie.com/explore.html#tags=liquidFill~sort=rank~timeframe=all~author=all)
|
||||
|
||||
Here are some common uses:
|
||||
|
||||
- [Use multiple waves in a chart](https://github.com/ecomfe/echarts-liquidfill#multiple-waves)
|
||||
- [Change waves color and opacity](https://github.com/ecomfe/echarts-liquidfill#color-and-opacity)
|
||||
- [Make waves static](https://github.com/ecomfe/echarts-liquidfill#static-waves)
|
||||
- [Water with no waves](https://github.com/ecomfe/echarts-liquidfill#still-water)
|
||||
- [Set attributes for a single wave](https://github.com/ecomfe/echarts-liquidfill#change-a-single-wave)
|
||||
- [Change background and border style](https://github.com/ecomfe/echarts-liquidfill#background-style)
|
||||
- [Hide outline in chart](https://github.com/ecomfe/echarts-liquidfill#outline-style)
|
||||
- [Change shape with SVG](https://github.com/ecomfe/echarts-liquidfill#shape)
|
||||
- [Setup animation](https://github.com/ecomfe/echarts-liquidfill#animation)
|
||||
- [Change text content and style](https://github.com/ecomfe/echarts-liquidfill#change-text)
|
||||
- [Change shadow style](https://github.com/ecomfe/echarts-liquidfill#shadow)
|
||||
- [Setup tooltip](https://github.com/ecomfe/echarts-liquidfill#tooltip)
|
||||
- [Click event](https://github.com/ecomfe/echarts-liquidfill#click-event)
|
||||
- [Make an element non-interactable](https://github.com/ecomfe/echarts-liquidfill#non-interactable)
|
||||
|
||||
To ask a question, you may fork [Liquid Fill Chart Example on Gallery](https://www.makeapie.com/editor.html?c=xr1XplzB4e) and copy your code there. Then you may [open an issue](https://github.com/ecomfe/echarts-liquidfill/issues/new) in this project.
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
### A Simple Example
|
||||
|
||||
To create a Liquid Fill Chart, you need to have a series with type of `'liquidFill'`. A basic option may be:
|
||||
|
||||
```js
|
||||
var option = {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6]
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||

|
||||
|
||||
[Run](https://www.makeapie.com/editor.html?c=xr1XplzB4e)
|
||||
|
||||
|
||||
### Multiple Waves
|
||||
|
||||
It is easy to create a liquid fill chart will multiple waves, either to represent multiple data, or to improve the visual effect of the chart.
|
||||
|
||||
```js
|
||||
var option = {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, 0.5, 0.4, 0.3]
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||
This creates a chart wit waves at position of 60%, 50%, 40%, and 30%.
|
||||
|
||||

|
||||
|
||||
[Run](https://www.makeapie.com/editor.html?c=xSyIEWMBNl)
|
||||
|
||||
|
||||
### Color and Opacity
|
||||
|
||||
To set colors for liquid fill chart series, set `color` to be an array of colors. To set opacity, use `itemStyle.opacity` and `itemStyle.emphasis.opacity` for normal style and hover style.
|
||||
|
||||
```js
|
||||
var option = {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.5, 0.4, 0.3],
|
||||
color: ['red', '#0f0', 'rgb(0, 0, 255)'],
|
||||
itemStyle: {
|
||||
opacity: 0.6
|
||||
},
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
opacity: 0.9
|
||||
}
|
||||
}
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||

|
||||
|
||||
[Run](https://www.makeapie.com/editor.html?c=xrJpDC704l)
|
||||
|
||||
You may also set the color and opacity of a single data item by:
|
||||
|
||||
```js
|
||||
var option = {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.5, 0.4, {
|
||||
value: 0.3,
|
||||
itemStyle: {
|
||||
color: 'red',
|
||||
opacity: 0.6
|
||||
},
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
opacity: 0.9
|
||||
}
|
||||
}
|
||||
}]
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||

|
||||
|
||||
[Run](https://www.makeapie.com/editor.html?c=xBJPCRXR4l)
|
||||
|
||||
|
||||
### Static Waves
|
||||
|
||||
To provent the waves from moving left or right, you may simply set `waveAnimation` to be `false`. To disable the animation of waves raising, set `animationDuration` and `animationDurationUpdate` to be 0.
|
||||
|
||||
```js
|
||||
var option = {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
waveAnimation: false,
|
||||
animationDuration: 0,
|
||||
animationDurationUpdate: 0,
|
||||
data: [0.6, 0.5, 0.4, 0.3]
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||

|
||||
|
||||
[Run](https://www.makeapie.com/editor.html?c=xH1VfVVREx)
|
||||
|
||||
|
||||
### Still Water
|
||||
|
||||
You may set the `amplitude` to be 0 to make still waves.
|
||||
|
||||
```js
|
||||
var option = {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, 0.5, 0.4, 0.3],
|
||||
amplitude: 0,
|
||||
waveAnimation: 0
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||
It is recommended to set `waveAnimation` to be false in this case to disable animation for performance consideration.
|
||||
|
||||

|
||||
|
||||
[Run](https://www.makeapie.com/editor.html?c=xHy1NHVCNx)
|
||||
|
||||
### Change A Single Wave
|
||||
|
||||
To change a single wave, overwrite the options in data item.
|
||||
|
||||
```js
|
||||
var option = {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, {
|
||||
value: 0.5,
|
||||
direction: 'left',
|
||||
itemStyle: {
|
||||
color: 'red'
|
||||
}
|
||||
}, 0.4, 0.3]
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||

|
||||
|
||||
[Run](https://www.makeapie.com/editor.html?c=xry6CHNCVl)
|
||||
|
||||
### Background Style
|
||||
|
||||
You can use backgroundStyle option to set the stroke, fill style of background shape.
|
||||
|
||||
```js
|
||||
var option = {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, 0.5, 0.4, 0.3],
|
||||
backgroundStyle: {
|
||||
borderWidth: 5,
|
||||
borderColor: 'red',
|
||||
color: 'yellow'
|
||||
}
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||

|
||||
|
||||
[Run](https://www.makeapie.com/editor.html?c=xSkJoa_kBx)
|
||||
|
||||
### Outline Style
|
||||
|
||||
To hide the outline, just set `outline.show` to be `false`.
|
||||
|
||||
```js
|
||||
var option = {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, 0.5, 0.4, 0.3],
|
||||
outline: {
|
||||
show: false
|
||||
}
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||

|
||||
|
||||
[Run](https://www.makeapie.com/editor.html?c=xSySxR_JBg)
|
||||
|
||||
|
||||
### Shape
|
||||
|
||||
Shape of water fill chart. It can be:
|
||||
|
||||
- one of the default symbols: `'circle'`, `'rect'`, `'roundRect'`, `'triangle'`, `'diamond'`, `'pin'`, `'arrow'`;
|
||||
- `'container'`: a shape that fully fills the container.
|
||||
- an SVG path starting with `'path://'`.
|
||||
|
||||
```js
|
||||
var options = [{
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, 0.5, 0.4, 0.3],
|
||||
shape: 'diamond'
|
||||
}]
|
||||
}];
|
||||
```
|
||||
|
||||

|
||||
|
||||
[Run](https://www.makeapie.com/editor.html?c=xry0tUfcBe)
|
||||
|
||||
```
|
||||
option = {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.5, 0.4, 0.3, 0.2],
|
||||
shape: 'container',
|
||||
outline: {
|
||||
show: false
|
||||
}
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||

|
||||
|
||||
[Run](https://www.makeapie.com/editor.html?c=xrko4E9zKb&v=1)
|
||||
|
||||
```js
|
||||
var option = {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, 0.55, 0.4, 0.25],
|
||||
radius: '60%',
|
||||
outline: {
|
||||
show: false
|
||||
},
|
||||
backgroundStyle: {
|
||||
borderColor: '#156ACF',
|
||||
borderWidth: 1,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.4)',
|
||||
shadowBlur: 20
|
||||
},
|
||||
shape: 'path://M367.855,428.202c-3.674-1.385-7.452-1.966-11.146-1.794c0.659-2.922,0.844-5.85,0.58-8.719 c-0.937-10.407-7.663-19.864-18.063-23.834c-10.697-4.043-22.298-1.168-29.902,6.403c3.015,0.026,6.074,0.594,9.035,1.728 c13.626,5.151,20.465,20.379,15.32,34.004c-1.905,5.02-5.177,9.115-9.22,12.05c-6.951,4.992-16.19,6.536-24.777,3.271 c-13.625-5.137-20.471-20.371-15.32-34.004c0.673-1.768,1.523-3.423,2.526-4.992h-0.014c0,0,0,0,0,0.014 c4.386-6.853,8.145-14.279,11.146-22.187c23.294-61.505-7.689-130.278-69.215-153.579c-61.532-23.293-130.279,7.69-153.579,69.202 c-6.371,16.785-8.679,34.097-7.426,50.901c0.026,0.554,0.079,1.121,0.132,1.688c4.973,57.107,41.767,109.148,98.945,130.793 c58.162,22.008,121.303,6.529,162.839-34.465c7.103-6.893,17.826-9.444,27.679-5.719c11.858,4.491,18.565,16.6,16.719,28.643 c4.438-3.126,8.033-7.564,10.117-13.045C389.751,449.992,382.411,433.709,367.855,428.202z',
|
||||
label: {
|
||||
position: ['38%', '40%'],
|
||||
formatter: function() {
|
||||
return 'ECharts\nLiquid Fill';
|
||||
},
|
||||
fontSize: 40,
|
||||
color: '#D94854'
|
||||
}
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||

|
||||
|
||||
[Run](https://www.makeapie.com/editor.html?c=xH1HouM9Sl)
|
||||
|
||||
|
||||
### Animation
|
||||
|
||||
Generally speaking, there are two types of animations in liquid fill charts.
|
||||
|
||||
The first type is initial animation, which has the effect of wave raising. The easing method of this animation is controlled with `animationEasing` and its duration with `animationDuration`.
|
||||
|
||||
The second type is the update animation, which is usually used when data changes and wave height changes. They are controlled with `animationEasingUpdate` and `animationDurationUpdate`.
|
||||
|
||||
For example, to disable the raising animation and set update animation time to be two seconds with `cubicOut` easing, you can use the following option:
|
||||
|
||||
```js
|
||||
var option = {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, 0.5, 0.4, 0.3],
|
||||
animationDuration: 0,
|
||||
animationDurationUpdate: 2000,
|
||||
animationEasingUpdate: 'cubicOut'
|
||||
}]
|
||||
};
|
||||
chart.setOption(option);
|
||||
setTimeout(function () {
|
||||
chart.setOption({
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.8, 0.6, 0.4, 0.2]
|
||||
}]
|
||||
})
|
||||
}, 3000);
|
||||
```
|
||||
|
||||

|
||||
|
||||
[Run](https://www.makeapie.com/editor.html?c=xSk8I5JcHe)
|
||||
|
||||
### Change Text
|
||||
|
||||
By default, the text label of liquid fill chart displays percentage of the first data. For example, for a chart with data `[0.6, 0.5, 0.4, 0.3]`, default text is `60%`.
|
||||
|
||||
To change the text, you may use `label.formatter`, which can be set to a string or function.
|
||||
|
||||
If it is a string, `{a}` refers to series name, `{b}` to data name, and `{c}` to data value.
|
||||
|
||||
```js
|
||||
var option = {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
name: 'Liquid Fill',
|
||||
data: [{
|
||||
name: 'First Data',
|
||||
value: 0.6
|
||||
}, 0.5, 0.4, 0.3],
|
||||
label: {
|
||||
formatter: '{a}\n{b}\nValue: {c}',
|
||||
fontSize: 28
|
||||
}
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||
Label text of this example is `'Liquid Fill\nFirst Data\nValue: 0.6'`.
|
||||
|
||||

|
||||
|
||||
[Run](https://www.makeapie.com/editor.html?c=xrkwSn1qHx)
|
||||
|
||||
This has the same result as using `formatter` as a function:
|
||||
|
||||
```js
|
||||
var option = {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
name: 'Liquid Fill',
|
||||
data: [{
|
||||
name: 'First Data',
|
||||
value: 0.6
|
||||
}, 0.5, 0.4, 0.3],
|
||||
label: {
|
||||
formatter: function(param) {
|
||||
return param.seriesName + '\n'
|
||||
+ param.name + '\n'
|
||||
+ 'Value:' + param.value;
|
||||
},
|
||||
fontSize: 28
|
||||
}
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||
[Run](https://www.makeapie.com/editor.html?c=xHk5831cHg)
|
||||
|
||||
Text position is at the center by default. `label.position` can be set to be `'inside'`, `'left'`, `'right'`, `'top'`, `'bottom'`, or horizontal and vertical positions like `['10%', '20%']`, which means `'10%'` to the left (controlled by `label.align`, which can be `'left'`, `'center'`, or `'right'`) and `'20%'` to the top (controlled by `label.baseline`, which can be `'top'`, `'middle'`, or `'bottom'`).
|
||||
|
||||
|
||||
### Shadow
|
||||
|
||||
By default, waves and outline have shadow on them. Here's how to change them.
|
||||
|
||||
```js
|
||||
var option = {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, 0.5, 0.4, 0.3],
|
||||
itemStyle: {
|
||||
shadowBlur: 0
|
||||
},
|
||||
outline: {
|
||||
borderDistance: 0,
|
||||
itemStyle: {
|
||||
borderWidth: 5,
|
||||
borderColor: '#156ACF',
|
||||
shadowBlur: 20,
|
||||
shadowColor: 'rgba(255, 0, 0, 1)'
|
||||
}
|
||||
}
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||

|
||||
|
||||
[Run](https://www.makeapie.com/editor.html?c=xrJO4CyqSl)
|
||||
|
||||
### Tooltip
|
||||
|
||||
To add tooltip:
|
||||
|
||||
```js
|
||||
var option = {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6],
|
||||
name: 'Liquid Fill'
|
||||
}],
|
||||
tooltip: {
|
||||
show: true
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||

|
||||
|
||||
[Run](https://www.makeapie.com/editor.html?c=xSJqXeg5He)
|
||||
|
||||
### Click Event
|
||||
|
||||
To add click event on waves:
|
||||
|
||||
```js
|
||||
chart.setOption(option);
|
||||
chart.on('click', function() {
|
||||
console.log(arguments);
|
||||
// do something useful here
|
||||
});
|
||||
```
|
||||
|
||||
Like any other chart types, the above code will only trigger events on waves. If you want to track events on the whole canvas or specific elements, you may add listener to zrender like:
|
||||
|
||||
```js
|
||||
chart.getZr().on('click', function() {
|
||||
console.log(arguments);
|
||||
});
|
||||
```
|
||||
|
||||
### Non-interactable
|
||||
|
||||
To make an element (e.g., a wave) non-interactable, simply set `silent` to be `true`.
|
||||
|
||||
```js
|
||||
var option = {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, 0.5, 0.4, 0.3],
|
||||
silent: true
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||
[Run](https://www.makeapie.com/editor.html?c=xSJqev71Jb)
|
||||
|
||||
|
||||
## API
|
||||
|
||||
Default option for liquid fill charts are:
|
||||
|
||||
```js
|
||||
{
|
||||
data: [],
|
||||
|
||||
color: ['#294D99', '#156ACF', '#1598ED', '#45BDFF'],
|
||||
center: ['50%', '50%'],
|
||||
radius: '50%',
|
||||
amplitude: '8%',
|
||||
waveLength: '80%',
|
||||
phase: 'auto',
|
||||
period: 'auto',
|
||||
direction: 'right',
|
||||
shape: 'circle',
|
||||
|
||||
waveAnimation: true,
|
||||
animationEasing: 'linear',
|
||||
animationEasingUpdate: 'linear',
|
||||
animationDuration: 2000,
|
||||
animationDurationUpdate: 1000,
|
||||
|
||||
outline: {
|
||||
show: true,
|
||||
borderDistance: 8,
|
||||
itemStyle: {
|
||||
color: 'none',
|
||||
borderColor: '#294D99',
|
||||
borderWidth: 8,
|
||||
shadowBlur: 20,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.25)'
|
||||
}
|
||||
},
|
||||
|
||||
backgroundStyle: {
|
||||
color: '#E3F7FF'
|
||||
},
|
||||
|
||||
itemStyle: {
|
||||
opacity: 0.95,
|
||||
shadowBlur: 50,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.4)'
|
||||
},
|
||||
|
||||
label: {
|
||||
show: true,
|
||||
color: '#294D99',
|
||||
insideColor: '#fff',
|
||||
fontSize: 50,
|
||||
fontWeight: 'bold',
|
||||
|
||||
align: 'center',
|
||||
baseline: 'middle'
|
||||
position: 'inside'
|
||||
},
|
||||
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
opacity: 0.8
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### data {(number|Object)[]}
|
||||
|
||||
Value of each data item should be between 0 and 1.
|
||||
|
||||
The data item can also be an object to configure the option for a single item.
|
||||
|
||||
```js
|
||||
var option = {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, {
|
||||
value: 0.5,
|
||||
itemStyle: {
|
||||
color: 'red'
|
||||
}
|
||||
}, 0.4, 0.3]
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||
This defines a chart with the second wave of red color.
|
||||
|
||||
|
||||
### color {string[]}
|
||||
|
||||
Wave colors.
|
||||
|
||||
|
||||
### shape {string}
|
||||
|
||||
Shape of water fill chart. It can be one of the default symbols: `'circle'`, `'rect'`, `'roundRect'`, `'triangle'`, `'diamond'`, `'pin'`, `'arrow'`. Or, an SVG path starting with `'path://'`.
|
||||
|
||||
|
||||
### center {string[]}
|
||||
|
||||
Position of the chart. The first value is x position, the second one is the y position. Each of the values can be a relative value like `'50%'`, which is relative to the smaller value of container width and height, or an absolute value like `100px`.
|
||||
|
||||
|
||||
### radius {string}
|
||||
|
||||
Radius of the chart, which can be a relative value like `'50%'`, which is relative to the smaller value of container width and height, or an absolute value like `100px`.
|
||||
|
||||
|
||||
### amplitude {number}
|
||||
|
||||
Amplitude of the wave, in pixels or percentage. If it is in percentage, it's relative to the diameter.
|
||||
|
||||
|
||||
### waveLength {string|number}
|
||||
|
||||
Wave length of the wave, which can be a relative value like `'50%'`, which is relative to the diameter, or an absolute value like `'100px'` or `100`.
|
||||
|
||||
|
||||
### phase {number}
|
||||
|
||||
Phase of wave, in radian system. By default, it is set to be `'auto'`, when each wave has a phase of `Math.PI / 4` larger than the previous one.
|
||||
|
||||
|
||||
### period {number|'auto'|function}
|
||||
|
||||
Milliseconds that it takes to move forward a wave-length. By default, it is set to be `'auto'`, when the wave at the front has a greater speed.
|
||||
|
||||
It can also be a formatter function.
|
||||
|
||||
```js
|
||||
var option = {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, 0.5, 0.4, 0.3],
|
||||
radius: '70%',
|
||||
phase: 0,
|
||||
period: function (value, index) {
|
||||
// This function is called four times, each for a data item in series.
|
||||
// `value` is 0.6, 0.5, 0.4, 0.3, and `index` is 0, 1, 2, 3.
|
||||
return 2000 * index + 1000;
|
||||
}
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### direction {string}
|
||||
|
||||
Direction that the waves moving in, which should either be `'right'`, or `'left'`.
|
||||
|
||||
|
||||
### waveAnimation {boolean}
|
||||
|
||||
Whether to enable wave from moving left or right.
|
||||
|
||||
|
||||
### animationEasing {string}
|
||||
|
||||
Easing methods for initial animation, when waves raise from the bottom at the beginning.
|
||||
|
||||
|
||||
### animationEasingUpdate {string}
|
||||
|
||||
Easing methods for other animation, for example, when data value changes and wave position changes.
|
||||
|
||||
|
||||
### animationDuration {number}
|
||||
|
||||
Initial animation duration, in milliseconds.
|
||||
|
||||
### animationDurationUpdate {number}
|
||||
|
||||
Other animation duration, in milliseconds.
|
||||
|
||||
|
||||
### outline.show {boolean}
|
||||
|
||||
Whether to display outline.
|
||||
|
||||
|
||||
### outline.borderDistance {number}
|
||||
|
||||
Distance between border and inner circle.
|
||||
|
||||
|
||||
### outline.itemStyle.borderColor {string}
|
||||
|
||||
Border color.
|
||||
|
||||
|
||||
### outline.itemStyle.borderWidth {number}
|
||||
|
||||
Border width.
|
||||
|
||||
|
||||
### outline.itemStyle.shadowBlur {number}
|
||||
|
||||
Outline shadow blur size.
|
||||
|
||||
|
||||
### outline.itemStyle.shadowColor {string}
|
||||
|
||||
Outline shadow color.
|
||||
|
||||
### backgroundStyle.color {string}
|
||||
|
||||
Background fill color.
|
||||
|
||||
### backgroundStyle.borderWidth {string}
|
||||
|
||||
Background stroke line width.
|
||||
|
||||
### backgroundStyle.borderColor {string}
|
||||
|
||||
Background stroke line width.
|
||||
|
||||
### backgroundStyle.itemStyle.shadowBlur {number}
|
||||
|
||||
Background shadow blur size.
|
||||
|
||||
### backgroundStyle.itemStyle.shadowColor {string}
|
||||
|
||||
Background shadow color.
|
||||
|
||||
### backgroundStyle.itemStyle.opacity {number}
|
||||
|
||||
Background opacity.
|
||||
|
||||
|
||||
### itemStyle.opacity {number}
|
||||
|
||||
Wave opacity.
|
||||
|
||||
|
||||
### itemStyle.shadowBlur {number}
|
||||
|
||||
Wave shadow width.
|
||||
|
||||
|
||||
### itemStyle.shadowColor {string}
|
||||
|
||||
Wave shadow color.
|
||||
|
||||
|
||||
### emphasis.itemStyle.opacity {number}
|
||||
|
||||
Wave opacity when hover.
|
||||
|
||||
|
||||
### label.show {boolean}
|
||||
|
||||
Whether to display label text.
|
||||
|
||||
|
||||
### label.color {string}
|
||||
|
||||
Color of text when display on background.
|
||||
|
||||
|
||||
### label.insideColor {string}
|
||||
|
||||
Color of text when display on wave.
|
||||
|
||||
|
||||
### label.fontSize {number}
|
||||
|
||||
Label font size.
|
||||
|
||||
|
||||
### label.fontWeight {string}
|
||||
|
||||
Label font weight.
|
||||
|
||||
|
||||
### label.align {string}
|
||||
|
||||
Text align, which should be `'left'`, `'center'`, or `'right'`.
|
||||
|
||||
|
||||
### label.baseline {string}
|
||||
|
||||
Text vertical align, which should be `'top'`, `'middle'`, or `'bottom'`.
|
||||
|
||||
|
||||
### label.position {string|string[]}
|
||||
|
||||
Text position is at the center by default. `label.position` can be set to be `'inside'`, `'left'`, `'right'`, `'top'`, `'bottom'`, or horizontal and vertical positions like `['10%', '20%']`, which means `'10%'` to the left and `'20%'` to the top.
|
||||
|
||||
|
||||
## Build
|
||||
|
||||
For development:
|
||||
```
|
||||
$ webpack
|
||||
```
|
||||
|
||||
For release:
|
||||
|
||||
```
|
||||
$ webpack -p
|
||||
```
|
||||
+1688
File diff suppressed because it is too large
Load Diff
+1
File diff suppressed because one or more lines are too long
+2
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+93
@@ -0,0 +1,93 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link href="https://fonts.googleapis.com/css?family=Lobster+Two:700i" rel="stylesheet">
|
||||
|
||||
<script src='https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js'></script>
|
||||
<script src='../dist/echarts-liquidfill.js'></script>
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
html, body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
background: #F1F7FF;
|
||||
}
|
||||
|
||||
#main {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 20px;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
color: #D94854;
|
||||
}
|
||||
|
||||
.chart {
|
||||
width: 80%;
|
||||
margin: 20px auto;
|
||||
height: 300px;
|
||||
border: 1px solid #D94854;
|
||||
}
|
||||
|
||||
p {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
<h1>ECharts LiquidFill Example</h1>
|
||||
<p>This is an example showing liquidFill chart that fills the container.</p>
|
||||
<div id='main'>
|
||||
<div class="chart"></div>
|
||||
<div class="chart"></div>
|
||||
</div>
|
||||
<script>
|
||||
var bgColor = '#E3F7FF';
|
||||
var containers = document.getElementsByClassName('chart');
|
||||
var options = [{
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, 0.5, 0.4, 0.3],
|
||||
outline: {
|
||||
show: false
|
||||
},
|
||||
shape: 'container'
|
||||
}]
|
||||
}, {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, 0.5, 0.4, 0.3],
|
||||
amplitude: '10%',
|
||||
waveLength: '200%',
|
||||
shape: 'container'
|
||||
}]
|
||||
}];
|
||||
|
||||
var charts = [];
|
||||
for (var i = 0; i < options.length; ++i) {
|
||||
var chart = echarts.init(containers[i]);
|
||||
chart.setOption(options[i]);
|
||||
charts.push(chart);
|
||||
}
|
||||
|
||||
window.onresize = function () {
|
||||
for (var i = 0; i < charts.length; ++i) {
|
||||
charts[i].resize();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<script>
|
||||
var _hmt = _hmt || [];
|
||||
(function() {
|
||||
var hm = document.createElement('script');
|
||||
hm.src = '//hm.baidu.com/hm.js?4bad1df23f079e0d12bdbef5e65b072f';
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
+366
@@ -0,0 +1,366 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link href="https://fonts.googleapis.com/css?family=Lobster+Two:700i" rel="stylesheet">
|
||||
|
||||
<script src='https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js'></script>
|
||||
<script src='../dist/echarts-liquidfill.js'></script>
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
html, body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
background: #F1F7FF;
|
||||
}
|
||||
|
||||
#main {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
#main:after {
|
||||
display: block;
|
||||
content: ' ';
|
||||
clear: both;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 20px;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
color: #D94854;
|
||||
}
|
||||
|
||||
.chart {
|
||||
width: 25%;
|
||||
height: 300px;
|
||||
float: left;
|
||||
}
|
||||
@media (max-width: 980px) {
|
||||
.chart {
|
||||
height: 200px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 750px) {
|
||||
.chart {
|
||||
width: 33.333333%;
|
||||
}
|
||||
}
|
||||
@media (max-width: 500px) {
|
||||
.chart {
|
||||
width: 50%;
|
||||
height: 180px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.main-chart {
|
||||
width: 100%;
|
||||
height: 400px;
|
||||
float: none;
|
||||
margin: -50px 0;
|
||||
}
|
||||
|
||||
.nav {
|
||||
text-align: center;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
background-color: #294D99;
|
||||
transition: 0.5s;
|
||||
color: white;
|
||||
padding: 6px 18px;
|
||||
border-radius: 20px;
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background-color: #1598ED;
|
||||
}
|
||||
|
||||
#view-more {
|
||||
text-align: center;
|
||||
margin: 20px 0 80px 0;
|
||||
}
|
||||
</style>
|
||||
<div id='main'>
|
||||
<div class="chart main-chart"></div>
|
||||
<h1>Liquid Fill Chart (ECharts Extension)</h1>
|
||||
<div class="nav">
|
||||
<a href="https://github.com/ecomfe/echarts-liquidfill">GitHub (Doc & API)</a>
|
||||
<a href="http://gallery.echartsjs.com/explore.html?u=bd-4013131402&type=work#tags=liquidFill">More Examples</a>
|
||||
<a href="http://echarts.baidu.com">ECharts</a>
|
||||
</div>
|
||||
<div class="chart"></div>
|
||||
<div class="chart"></div>
|
||||
<div class="chart"></div>
|
||||
<div class="chart"></div>
|
||||
<div class="chart"></div>
|
||||
<div class="chart"></div>
|
||||
<div class="chart"></div>
|
||||
<div class="chart"></div>
|
||||
<div class="chart"></div>
|
||||
<div class="chart"></div>
|
||||
<div class="chart"></div>
|
||||
<div class="chart"></div>
|
||||
</div>
|
||||
<script>
|
||||
var _hmt = _hmt || [];
|
||||
(function() {
|
||||
var hm = document.createElement('script');
|
||||
hm.src = '//hm.baidu.com/hm.js?4bad1df23f079e0d12bdbef5e65b072f';
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
|
||||
var bgColor = '#E3F7FF';
|
||||
var containers = document.getElementsByClassName('chart');
|
||||
var options = [{
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, 0.55, 0.4, 0.25],
|
||||
radius: '70%',
|
||||
outline: {
|
||||
show: false
|
||||
},
|
||||
backgroundStyle: {
|
||||
borderColor: '#156ACF',
|
||||
borderWidth: 1,
|
||||
color: bgColor,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.4)',
|
||||
shadowBlur: 20
|
||||
},
|
||||
shape: 'path://M367.855,428.202c-3.674-1.385-7.452-1.966-11.146-1.794c0.659-2.922,0.844-5.85,0.58-8.719 c-0.937-10.407-7.663-19.864-18.063-23.834c-10.697-4.043-22.298-1.168-29.902,6.403c3.015,0.026,6.074,0.594,9.035,1.728 c13.626,5.151,20.465,20.379,15.32,34.004c-1.905,5.02-5.177,9.115-9.22,12.05c-6.951,4.992-16.19,6.536-24.777,3.271 c-13.625-5.137-20.471-20.371-15.32-34.004c0.673-1.768,1.523-3.423,2.526-4.992h-0.014c0,0,0,0,0,0.014 c4.386-6.853,8.145-14.279,11.146-22.187c23.294-61.505-7.689-130.278-69.215-153.579c-61.532-23.293-130.279,7.69-153.579,69.202 c-6.371,16.785-8.679,34.097-7.426,50.901c0.026,0.554,0.079,1.121,0.132,1.688c4.973,57.107,41.767,109.148,98.945,130.793 c58.162,22.008,121.303,6.529,162.839-34.465c7.103-6.893,17.826-9.444,27.679-5.719c11.858,4.491,18.565,16.6,16.719,28.643 c4.438-3.126,8.033-7.564,10.117-13.045C389.751,449.992,382.411,433.709,367.855,428.202z',
|
||||
label: {
|
||||
position: ['38%', '40%'],
|
||||
formatter: function () {
|
||||
return 'ECharts\nLiquid Fill';
|
||||
},
|
||||
fontSize: 40,
|
||||
fontFamily: 'Lobster Two',
|
||||
color: '#D94854',
|
||||
insideColor: bgColor
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, 0.5, 0.4, 0.3],
|
||||
radius: '70%',
|
||||
outline: {
|
||||
show: false
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, 0.5, 0.4, 0.3],
|
||||
radius: '70%',
|
||||
phase: 0,
|
||||
period: 5000,
|
||||
outline: {
|
||||
show: false
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, {
|
||||
value: 0.5,
|
||||
direction: 'left'
|
||||
}, 0.4, {
|
||||
value: 0.3,
|
||||
direction: 'left'
|
||||
}],
|
||||
radius: '70%',
|
||||
outline: {
|
||||
show: false
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, 0.5, {
|
||||
value: 0.4,
|
||||
amplitude: 15
|
||||
}, {
|
||||
value: 0.3,
|
||||
amplitude: 20,
|
||||
waveLength: 100
|
||||
}],
|
||||
radius: '70%',
|
||||
amplitude: 10,
|
||||
outline: {
|
||||
show: false
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6],
|
||||
radius: '70%'
|
||||
}]
|
||||
}, {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6],
|
||||
radius: '70%',
|
||||
amplitude: 0,
|
||||
waveAnimation: false,
|
||||
silent: true
|
||||
}]
|
||||
}, {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [1, 0.9, 0.8, 0.7],
|
||||
radius: '70%',
|
||||
label: {
|
||||
formatter: 'I\'m full.',
|
||||
textStyle: {
|
||||
fontSize: 35,
|
||||
fontFamily: 'Lobster Two'
|
||||
}
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0, 0, 0, 0],
|
||||
radius: '70%',
|
||||
label: {
|
||||
formatter: 'I\'m empty.',
|
||||
fontSize: 25,
|
||||
fontFamily: 'Lobster Two',
|
||||
baseline: 'bottom',
|
||||
position: ['50%', '86%']
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, 0.5, 0.4, 0.3],
|
||||
waveAnimation: false,
|
||||
radius: '70%',
|
||||
backgroundStyle: {
|
||||
borderWidth: 2,
|
||||
borderColor: '#156ACF'
|
||||
},
|
||||
outline: {
|
||||
show: false
|
||||
},
|
||||
shape: 'diamond'
|
||||
}]
|
||||
}, {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, 0.5, 0.4, 0.3],
|
||||
radius: '70%',
|
||||
amplitude: 0,
|
||||
waveAnimation: false,
|
||||
backgroundStyle: {
|
||||
borderWidth: 2,
|
||||
borderColor: '#156ACF'
|
||||
},
|
||||
outline: {
|
||||
show: false
|
||||
},
|
||||
shape: 'triangle',
|
||||
label: {
|
||||
position: ['50%', '65%']
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, 0.5, 0.4, 0.3],
|
||||
radius: '90%',
|
||||
itemStyle: {
|
||||
shadowBlur: 0
|
||||
},
|
||||
backgroundStyle: {
|
||||
borderWidth: 2,
|
||||
borderColor: '#156ACF'
|
||||
},
|
||||
outline: {
|
||||
show: false
|
||||
},
|
||||
label: {
|
||||
shadowBlur: 0,
|
||||
position: ['50%', '45%']
|
||||
},
|
||||
shape: 'pin',
|
||||
center: ['50%', '40%']
|
||||
}]
|
||||
}, {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
data: [0.6, 0.5, 0.4, 0.3],
|
||||
radius: '70%',
|
||||
|
||||
backgroundStyle: {
|
||||
borderWidth: 2,
|
||||
borderColor: '#156ACF'
|
||||
},
|
||||
outline: {
|
||||
show: false
|
||||
},
|
||||
shape: 'rect'
|
||||
}]
|
||||
}];
|
||||
|
||||
var charts = [];
|
||||
for (var i = 0; i < options.length; ++i) {
|
||||
var chart = echarts.init(containers[i]);
|
||||
|
||||
if (i > 0) {
|
||||
options[i].series[0].silent = true;
|
||||
}
|
||||
chart.setOption(options[i]);
|
||||
chart.setOption({
|
||||
baseOption: options[i],
|
||||
media: [{
|
||||
query: {
|
||||
maxWidth: 300
|
||||
},
|
||||
option: {
|
||||
series: [{
|
||||
label: {
|
||||
fontSize: 26
|
||||
}
|
||||
}]
|
||||
}
|
||||
}]
|
||||
});
|
||||
|
||||
charts.push(chart);
|
||||
}
|
||||
|
||||
window.onresize = function () {
|
||||
for (var i = 0; i < charts.length; ++i) {
|
||||
charts[i].resize();
|
||||
}
|
||||
};
|
||||
|
||||
setInterval(update, 3000);
|
||||
|
||||
function update() {
|
||||
var data = [];
|
||||
var last = 1;
|
||||
for (var i = 0; i < 4; ++i) {
|
||||
last = Math.floor(last * (Math.random() * 0.5 + 0.5)
|
||||
* 100) / 100;
|
||||
data.push(last);
|
||||
}
|
||||
charts[1].setOption({
|
||||
series: [{
|
||||
data: data
|
||||
}]
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link href="https://fonts.googleapis.com/css?family=Lobster+Two:700i" rel="stylesheet">
|
||||
|
||||
<script src='https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js'></script>
|
||||
<script src='../dist/echarts-liquidfill.js'></script>
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
html, body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
background: #F1F7FF;
|
||||
}
|
||||
|
||||
#main {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 20px;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
color: #D94854;
|
||||
}
|
||||
|
||||
.chart {
|
||||
width: 30%;
|
||||
margin: 20px auto;
|
||||
height: 300px;
|
||||
border: 1px solid #D94854;
|
||||
}
|
||||
|
||||
p {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
<h1>ECharts LiquidFill Example</h1>
|
||||
<p>This is an example showing liquidFill chart that fills the container.</p>
|
||||
<div id='main'>
|
||||
<div class="chart" id="chart"></div>
|
||||
</div>
|
||||
<script>
|
||||
var options = {
|
||||
series: [{
|
||||
type: 'liquidFill',
|
||||
waveAnimation: false,
|
||||
animation: false,
|
||||
data: [{
|
||||
value: 0.7
|
||||
}]
|
||||
}]
|
||||
};
|
||||
|
||||
var chart = echarts.init(document.getElementById('chart'));
|
||||
chart.setOption(options);
|
||||
|
||||
window.onresize = function () {
|
||||
chart.resize();
|
||||
};
|
||||
</script>
|
||||
|
||||
<script>
|
||||
var _hmt = _hmt || [];
|
||||
(function() {
|
||||
var hm = document.createElement('script');
|
||||
hm.src = '//hm.baidu.com/hm.js?4bad1df23f079e0d12bdbef5e65b072f';
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
+1
@@ -0,0 +1 @@
|
||||
import './src/liquidFill';
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2020, Baidu Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "echarts-liquidfill",
|
||||
"version": "3.1.0",
|
||||
"description": "ECharts liquid fill extension",
|
||||
"main": "dist/echarts-liquidfill.js",
|
||||
"module": "index.js",
|
||||
"scripts": {
|
||||
"dev": "webpack --mode development --watch",
|
||||
"build": "webpack --mode development",
|
||||
"release": "webpack --mode production && webpack --mode development"
|
||||
},
|
||||
"author": {
|
||||
"name": "Ovilia",
|
||||
"email": "me@zhangwenli.com",
|
||||
"url": "http://zhangwenli.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"echarts": "^5.0.1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ecomfe/echarts-liquidfill"
|
||||
},
|
||||
"devDependencies": {
|
||||
"echarts": "^5.2.0",
|
||||
"webpack": "^5.11.1",
|
||||
"webpack-cli": "^4.3.1"
|
||||
}
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
import './liquidFillSeries';
|
||||
import './liquidFillView';
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
import * as echarts from 'echarts/lib/echarts';
|
||||
|
||||
echarts.extendSeriesModel({
|
||||
|
||||
type: 'series.liquidFill',
|
||||
|
||||
optionUpdated: function () {
|
||||
var option = this.option;
|
||||
option.gridSize = Math.max(Math.floor(option.gridSize), 4);
|
||||
},
|
||||
|
||||
getInitialData: function (option, ecModel) {
|
||||
var dimensions = echarts.helper.createDimensions(option.data, {
|
||||
coordDimensions: ['value']
|
||||
});
|
||||
var list = new echarts.List(dimensions, this);
|
||||
list.initData(option.data);
|
||||
return list;
|
||||
},
|
||||
|
||||
defaultOption: {
|
||||
color: ['#294D99', '#156ACF', '#1598ED', '#45BDFF'],
|
||||
center: ['50%', '50%'],
|
||||
radius: '50%',
|
||||
amplitude: '8%',
|
||||
waveLength: '80%',
|
||||
phase: 'auto',
|
||||
period: 'auto',
|
||||
direction: 'right',
|
||||
shape: 'circle',
|
||||
|
||||
waveAnimation: true,
|
||||
animationEasing: 'linear',
|
||||
animationEasingUpdate: 'linear',
|
||||
animationDuration: 2000,
|
||||
animationDurationUpdate: 1000,
|
||||
|
||||
outline: {
|
||||
show: true,
|
||||
borderDistance: 8,
|
||||
itemStyle: {
|
||||
color: 'none',
|
||||
borderColor: '#294D99',
|
||||
borderWidth: 8,
|
||||
shadowBlur: 20,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.25)'
|
||||
}
|
||||
},
|
||||
|
||||
backgroundStyle: {
|
||||
color: '#E3F7FF'
|
||||
},
|
||||
|
||||
itemStyle: {
|
||||
opacity: 0.95,
|
||||
shadowBlur: 50,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.4)'
|
||||
},
|
||||
|
||||
label: {
|
||||
show: true,
|
||||
color: '#294D99',
|
||||
insideColor: '#fff',
|
||||
fontSize: 50,
|
||||
fontWeight: 'bold',
|
||||
|
||||
align: 'center',
|
||||
baseline: 'middle',
|
||||
position: 'inside'
|
||||
},
|
||||
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
opacity: 0.8
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
import * as echarts from 'echarts/lib/echarts';
|
||||
|
||||
export default echarts.graphic.extendShape({
|
||||
type: 'ec-liquid-fill',
|
||||
|
||||
shape: {
|
||||
waveLength: 0,
|
||||
radius: 0,
|
||||
radiusY: 0,
|
||||
cx: 0,
|
||||
cy: 0,
|
||||
waterLevel: 0,
|
||||
amplitude: 0,
|
||||
phase: 0,
|
||||
inverse: false
|
||||
},
|
||||
|
||||
buildPath: function (ctx, shape) {
|
||||
if (shape.radiusY == null) {
|
||||
shape.radiusY = shape.radius;
|
||||
}
|
||||
|
||||
/**
|
||||
* We define a sine wave having 4 waves, and make sure at least 8 curves
|
||||
* is drawn. Otherwise, it may cause blank area for some waves when
|
||||
* wave length is large enough.
|
||||
*/
|
||||
var curves = Math.max(
|
||||
Math.ceil(2 * shape.radius / shape.waveLength * 4) * 2,
|
||||
8
|
||||
);
|
||||
|
||||
// map phase to [-Math.PI * 2, 0]
|
||||
while (shape.phase < -Math.PI * 2) {
|
||||
shape.phase += Math.PI * 2;
|
||||
}
|
||||
while (shape.phase > 0) {
|
||||
shape.phase -= Math.PI * 2;
|
||||
}
|
||||
var phase = shape.phase / Math.PI / 2 * shape.waveLength;
|
||||
|
||||
var left = shape.cx - shape.radius + phase - shape.radius * 2;
|
||||
|
||||
/**
|
||||
* top-left corner as start point
|
||||
*
|
||||
* draws this point
|
||||
* |
|
||||
* \|/
|
||||
* ~~~~~~~~
|
||||
* | |
|
||||
* +------+
|
||||
*/
|
||||
ctx.moveTo(left, shape.waterLevel);
|
||||
|
||||
/**
|
||||
* top wave
|
||||
*
|
||||
* ~~~~~~~~ <- draws this sine wave
|
||||
* | |
|
||||
* +------+
|
||||
*/
|
||||
var waveRight = 0;
|
||||
for (var c = 0; c < curves; ++c) {
|
||||
var stage = c % 4;
|
||||
var pos = getWaterPositions(c * shape.waveLength / 4, stage,
|
||||
shape.waveLength, shape.amplitude);
|
||||
ctx.bezierCurveTo(pos[0][0] + left, -pos[0][1] + shape.waterLevel,
|
||||
pos[1][0] + left, -pos[1][1] + shape.waterLevel,
|
||||
pos[2][0] + left, -pos[2][1] + shape.waterLevel);
|
||||
|
||||
if (c === curves - 1) {
|
||||
waveRight = pos[2][0];
|
||||
}
|
||||
}
|
||||
|
||||
if (shape.inverse) {
|
||||
/**
|
||||
* top-right corner
|
||||
* 2. draws this line
|
||||
* |
|
||||
* +------+
|
||||
* 3. draws this line -> | | <- 1. draws this line
|
||||
* ~~~~~~~~
|
||||
*/
|
||||
ctx.lineTo(waveRight + left, shape.cy - shape.radiusY);
|
||||
ctx.lineTo(left, shape.cy - shape.radiusY);
|
||||
ctx.lineTo(left, shape.waterLevel);
|
||||
}
|
||||
else {
|
||||
/**
|
||||
* top-right corner
|
||||
*
|
||||
* ~~~~~~~~
|
||||
* 3. draws this line -> | | <- 1. draws this line
|
||||
* +------+
|
||||
* ^
|
||||
* |
|
||||
* 2. draws this line
|
||||
*/
|
||||
ctx.lineTo(waveRight + left, shape.cy + shape.radiusY);
|
||||
ctx.lineTo(left, shape.cy + shape.radiusY);
|
||||
ctx.lineTo(left, shape.waterLevel);
|
||||
}
|
||||
|
||||
ctx.closePath();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Using Bezier curves to fit sine wave.
|
||||
* There is 4 control points for each curve of wave,
|
||||
* which is at 1/4 wave length of the sine wave.
|
||||
*
|
||||
* The control points for a wave from (a) to (d) are a-b-c-d:
|
||||
* c *----* d
|
||||
* b *
|
||||
* |
|
||||
* ... a * ..................
|
||||
*
|
||||
* whose positions are a: (0, 0), b: (0.5, 0.5), c: (1, 1), d: (PI / 2, 1)
|
||||
*
|
||||
* @param {number} x x position of the left-most point (a)
|
||||
* @param {number} stage 0-3, stating which part of the wave it is
|
||||
* @param {number} waveLength wave length of the sine wave
|
||||
* @param {number} amplitude wave amplitude
|
||||
*/
|
||||
function getWaterPositions(x, stage, waveLength, amplitude) {
|
||||
if (stage === 0) {
|
||||
return [
|
||||
[x + 1 / 2 * waveLength / Math.PI / 2, amplitude / 2],
|
||||
[x + 1 / 2 * waveLength / Math.PI, amplitude],
|
||||
[x + waveLength / 4, amplitude]
|
||||
];
|
||||
}
|
||||
else if (stage === 1) {
|
||||
return [
|
||||
[x + 1 / 2 * waveLength / Math.PI / 2 * (Math.PI - 2),
|
||||
amplitude],
|
||||
[x + 1 / 2 * waveLength / Math.PI / 2 * (Math.PI - 1),
|
||||
amplitude / 2],
|
||||
[x + waveLength / 4, 0]
|
||||
]
|
||||
}
|
||||
else if (stage === 2) {
|
||||
return [
|
||||
[x + 1 / 2 * waveLength / Math.PI / 2, -amplitude / 2],
|
||||
[x + 1 / 2 * waveLength / Math.PI, -amplitude],
|
||||
[x + waveLength / 4, -amplitude]
|
||||
]
|
||||
}
|
||||
else {
|
||||
return [
|
||||
[x + 1 / 2 * waveLength / Math.PI / 2 * (Math.PI - 2),
|
||||
-amplitude],
|
||||
[x + 1 / 2 * waveLength / Math.PI / 2 * (Math.PI - 1),
|
||||
-amplitude / 2],
|
||||
[x + waveLength / 4, 0]
|
||||
]
|
||||
}
|
||||
}
|
||||
+507
@@ -0,0 +1,507 @@
|
||||
import * as echarts from 'echarts/lib/echarts';
|
||||
import * as numberUtil from 'echarts/lib/util/number';
|
||||
import LiquidShape from './liquidFillShape';
|
||||
|
||||
var parsePercent = numberUtil.parsePercent;
|
||||
|
||||
function isPathSymbol(symbol) {
|
||||
return symbol && symbol.indexOf('path://') === 0
|
||||
}
|
||||
|
||||
echarts.extendChartView({
|
||||
|
||||
type: 'liquidFill',
|
||||
|
||||
render: function (seriesModel, ecModel, api) {
|
||||
var self = this;
|
||||
var group = this.group;
|
||||
group.removeAll();
|
||||
|
||||
var data = seriesModel.getData();
|
||||
|
||||
var itemModel = data.getItemModel(0);
|
||||
|
||||
var center = itemModel.get('center');
|
||||
var radius = itemModel.get('radius');
|
||||
|
||||
var width = api.getWidth();
|
||||
var height = api.getHeight();
|
||||
var size = Math.min(width, height);
|
||||
// itemStyle
|
||||
var outlineDistance = 0;
|
||||
var outlineBorderWidth = 0;
|
||||
var showOutline = seriesModel.get('outline.show');
|
||||
|
||||
if (showOutline) {
|
||||
outlineDistance = seriesModel.get('outline.borderDistance');
|
||||
outlineBorderWidth = parsePercent(
|
||||
seriesModel.get('outline.itemStyle.borderWidth'), size
|
||||
);
|
||||
}
|
||||
|
||||
var cx = parsePercent(center[0], width);
|
||||
var cy = parsePercent(center[1], height);
|
||||
|
||||
var outterRadius;
|
||||
var innerRadius;
|
||||
var paddingRadius;
|
||||
|
||||
var isFillContainer = false;
|
||||
|
||||
var symbol = seriesModel.get('shape');
|
||||
if (symbol === 'container') {
|
||||
// a shape that fully fills the container
|
||||
isFillContainer = true;
|
||||
|
||||
outterRadius = [
|
||||
width / 2,
|
||||
height / 2
|
||||
];
|
||||
innerRadius = [
|
||||
outterRadius[0] - outlineBorderWidth / 2,
|
||||
outterRadius[1] - outlineBorderWidth / 2
|
||||
];
|
||||
paddingRadius = [
|
||||
parsePercent(outlineDistance, width),
|
||||
parsePercent(outlineDistance, height)
|
||||
];
|
||||
|
||||
radius = [
|
||||
Math.max(innerRadius[0] - paddingRadius[0], 0),
|
||||
Math.max(innerRadius[1] - paddingRadius[1], 0)
|
||||
];
|
||||
}
|
||||
else {
|
||||
outterRadius = parsePercent(radius, size) / 2;
|
||||
innerRadius = outterRadius - outlineBorderWidth / 2;
|
||||
paddingRadius = parsePercent(outlineDistance, size);
|
||||
|
||||
radius = Math.max(innerRadius - paddingRadius, 0);
|
||||
}
|
||||
|
||||
if (showOutline) {
|
||||
var outline = getOutline();
|
||||
outline.style.lineWidth = outlineBorderWidth;
|
||||
group.add(getOutline());
|
||||
}
|
||||
|
||||
var left = isFillContainer ? 0 : cx - radius;
|
||||
var top = isFillContainer ? 0 : cy - radius;
|
||||
|
||||
var wavePath = null;
|
||||
|
||||
group.add(getBackground());
|
||||
|
||||
// each data item for a wave
|
||||
var oldData = this._data;
|
||||
var waves = [];
|
||||
data.diff(oldData)
|
||||
.add(function (idx) {
|
||||
var wave = getWave(idx, false);
|
||||
|
||||
var waterLevel = wave.shape.waterLevel;
|
||||
wave.shape.waterLevel = isFillContainer ? height / 2 : radius;
|
||||
echarts.graphic.initProps(wave, {
|
||||
shape: {
|
||||
waterLevel: waterLevel
|
||||
}
|
||||
}, seriesModel);
|
||||
|
||||
wave.z2 = 2;
|
||||
setWaveAnimation(idx, wave, null);
|
||||
|
||||
group.add(wave);
|
||||
data.setItemGraphicEl(idx, wave);
|
||||
waves.push(wave);
|
||||
})
|
||||
.update(function (newIdx, oldIdx) {
|
||||
var waveElement = oldData.getItemGraphicEl(oldIdx);
|
||||
|
||||
// new wave is used to calculate position, but not added
|
||||
var newWave = getWave(newIdx, false, waveElement);
|
||||
|
||||
// changes with animation
|
||||
var shape = {};
|
||||
var shapeAttrs = ['amplitude', 'cx', 'cy', 'phase', 'radius', 'radiusY', 'waterLevel', 'waveLength'];
|
||||
for (var i = 0; i < shapeAttrs.length; ++i) {
|
||||
var attr = shapeAttrs[i];
|
||||
if (newWave.shape.hasOwnProperty(attr)) {
|
||||
shape[attr] = newWave.shape[attr];
|
||||
}
|
||||
}
|
||||
|
||||
var style = {};
|
||||
var styleAttrs = ['fill', 'opacity', 'shadowBlur', 'shadowColor'];
|
||||
for (var i = 0; i < styleAttrs.length; ++i) {
|
||||
var attr = styleAttrs[i];
|
||||
if (newWave.style.hasOwnProperty(attr)) {
|
||||
style[attr] = newWave.style[attr];
|
||||
}
|
||||
}
|
||||
|
||||
if (isFillContainer) {
|
||||
shape.radiusY = height / 2;
|
||||
}
|
||||
|
||||
// changes with animation
|
||||
echarts.graphic.updateProps(waveElement, {
|
||||
shape: shape,
|
||||
x: newWave.x,
|
||||
y: newWave.y
|
||||
}, seriesModel);
|
||||
|
||||
if (seriesModel.isUniversalTransitionEnabled && seriesModel.isUniversalTransitionEnabled()) {
|
||||
echarts.graphic.updateProps(waveElement, {
|
||||
style: style
|
||||
}, seriesModel);
|
||||
}
|
||||
else {
|
||||
waveElement.useStyle(style);
|
||||
}
|
||||
|
||||
// instant changes
|
||||
var oldWaveClipPath = waveElement.getClipPath();
|
||||
var newWaveClipPath = newWave.getClipPath();
|
||||
|
||||
waveElement.setClipPath(newWave.getClipPath());
|
||||
waveElement.shape.inverse = newWave.inverse;
|
||||
|
||||
if (oldWaveClipPath && newWaveClipPath
|
||||
&& self._shape === symbol
|
||||
// TODO use zrender morphing to apply complex symbol animation.
|
||||
&& !isPathSymbol(symbol)
|
||||
) {
|
||||
// Can be animated.
|
||||
echarts.graphic.updateProps(newWaveClipPath, {
|
||||
shape: oldWaveClipPath.shape
|
||||
}, seriesModel, { isFrom: true });
|
||||
}
|
||||
|
||||
setWaveAnimation(newIdx, waveElement, waveElement);
|
||||
group.add(waveElement);
|
||||
data.setItemGraphicEl(newIdx, waveElement);
|
||||
waves.push(waveElement);
|
||||
})
|
||||
.remove(function (idx) {
|
||||
var wave = oldData.getItemGraphicEl(idx);
|
||||
group.remove(wave);
|
||||
})
|
||||
.execute();
|
||||
|
||||
if (itemModel.get('label.show')) {
|
||||
group.add(getText(waves));
|
||||
}
|
||||
|
||||
this._shape = symbol;
|
||||
this._data = data;
|
||||
|
||||
/**
|
||||
* Get path for outline, background and clipping
|
||||
*
|
||||
* @param {number} r outter radius of shape
|
||||
* @param {boolean|undefined} isForClipping if the shape is used
|
||||
* for clipping
|
||||
*/
|
||||
function getPath(r, isForClipping) {
|
||||
if (symbol) {
|
||||
// customed symbol path
|
||||
if (isPathSymbol(symbol)) {
|
||||
var path = echarts.graphic.makePath(symbol.slice(7), {});
|
||||
var bouding = path.getBoundingRect();
|
||||
var w = bouding.width;
|
||||
var h = bouding.height;
|
||||
if (w > h) {
|
||||
h = r * 2 / w * h;
|
||||
w = r * 2;
|
||||
}
|
||||
else {
|
||||
w = r * 2 / h * w;
|
||||
h = r * 2;
|
||||
}
|
||||
|
||||
var left = isForClipping ? 0 : cx - w / 2;
|
||||
var top = isForClipping ? 0 : cy - h / 2;
|
||||
path = echarts.graphic.makePath(
|
||||
symbol.slice(7),
|
||||
{},
|
||||
new echarts.graphic.BoundingRect(left, top, w, h)
|
||||
);
|
||||
if (isForClipping) {
|
||||
path.x = -w / 2;
|
||||
path.y = -h / 2;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
else if (isFillContainer) {
|
||||
// fully fill the container
|
||||
var x = isForClipping ? -r[0] : cx - r[0];
|
||||
var y = isForClipping ? -r[1] : cy - r[1];
|
||||
return echarts.helper.createSymbol(
|
||||
'rect', x, y, r[0] * 2, r[1] * 2
|
||||
);
|
||||
}
|
||||
else {
|
||||
var x = isForClipping ? -r : cx - r;
|
||||
var y = isForClipping ? -r : cy - r;
|
||||
if (symbol === 'pin') {
|
||||
y += r;
|
||||
}
|
||||
else if (symbol === 'arrow') {
|
||||
y -= r;
|
||||
}
|
||||
return echarts.helper.createSymbol(symbol, x, y, r * 2, r * 2);
|
||||
}
|
||||
}
|
||||
|
||||
return new echarts.graphic.Circle({
|
||||
shape: {
|
||||
cx: isForClipping ? 0 : cx,
|
||||
cy: isForClipping ? 0 : cy,
|
||||
r: r
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Create outline
|
||||
*/
|
||||
function getOutline() {
|
||||
var outlinePath = getPath(outterRadius);
|
||||
outlinePath.style.fill = null;
|
||||
|
||||
outlinePath.setStyle(seriesModel.getModel('outline.itemStyle')
|
||||
.getItemStyle());
|
||||
|
||||
return outlinePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create background
|
||||
*/
|
||||
function getBackground() {
|
||||
// Seperate stroke and fill, so we can use stroke to cover the alias of clipping.
|
||||
var strokePath = getPath(radius);
|
||||
strokePath.setStyle(seriesModel.getModel('backgroundStyle')
|
||||
.getItemStyle());
|
||||
strokePath.style.fill = null;
|
||||
|
||||
// Stroke is front of wave
|
||||
strokePath.z2 = 5;
|
||||
|
||||
var fillPath = getPath(radius);
|
||||
fillPath.setStyle(seriesModel.getModel('backgroundStyle')
|
||||
.getItemStyle());
|
||||
fillPath.style.stroke = null;
|
||||
|
||||
var group = new echarts.graphic.Group();
|
||||
group.add(strokePath);
|
||||
group.add(fillPath);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
/**
|
||||
* wave shape
|
||||
*/
|
||||
function getWave(idx, isInverse, oldWave) {
|
||||
var radiusX = isFillContainer ? radius[0] : radius;
|
||||
var radiusY = isFillContainer ? height / 2 : radius;
|
||||
|
||||
var itemModel = data.getItemModel(idx);
|
||||
var itemStyleModel = itemModel.getModel('itemStyle');
|
||||
var phase = itemModel.get('phase');
|
||||
var amplitude = parsePercent(itemModel.get('amplitude'),
|
||||
radiusY * 2);
|
||||
var waveLength = parsePercent(itemModel.get('waveLength'),
|
||||
radiusX * 2);
|
||||
|
||||
var value = data.get('value', idx);
|
||||
var waterLevel = radiusY - value * radiusY * 2;
|
||||
phase = oldWave ? oldWave.shape.phase
|
||||
: (phase === 'auto' ? idx * Math.PI / 4 : phase);
|
||||
var normalStyle = itemStyleModel.getItemStyle();
|
||||
if (!normalStyle.fill) {
|
||||
var seriesColor = seriesModel.get('color');
|
||||
var id = idx % seriesColor.length;
|
||||
normalStyle.fill = seriesColor[id];
|
||||
}
|
||||
|
||||
var x = radiusX * 2;
|
||||
var wave = new LiquidShape({
|
||||
shape: {
|
||||
waveLength: waveLength,
|
||||
radius: radiusX,
|
||||
radiusY: radiusY,
|
||||
cx: x,
|
||||
cy: 0,
|
||||
waterLevel: waterLevel,
|
||||
amplitude: amplitude,
|
||||
phase: phase,
|
||||
inverse: isInverse
|
||||
},
|
||||
style: normalStyle,
|
||||
x: cx,
|
||||
y: cy,
|
||||
});
|
||||
wave.shape._waterLevel = waterLevel;
|
||||
|
||||
var hoverStyle = itemModel.getModel('emphasis.itemStyle')
|
||||
.getItemStyle();
|
||||
hoverStyle.lineWidth = 0;
|
||||
|
||||
wave.ensureState('emphasis').style = hoverStyle;
|
||||
echarts.helper.enableHoverEmphasis(wave);
|
||||
|
||||
// clip out the part outside the circle
|
||||
var clip = getPath(radius, true);
|
||||
// set fill for clipPath, otherwise it will not trigger hover event
|
||||
clip.setStyle({
|
||||
fill: 'white'
|
||||
});
|
||||
wave.setClipPath(clip);
|
||||
|
||||
return wave;
|
||||
}
|
||||
|
||||
function setWaveAnimation(idx, wave, oldWave) {
|
||||
var itemModel = data.getItemModel(idx);
|
||||
|
||||
var maxSpeed = itemModel.get('period');
|
||||
var direction = itemModel.get('direction');
|
||||
|
||||
var value = data.get('value', idx);
|
||||
|
||||
var phase = itemModel.get('phase');
|
||||
phase = oldWave ? oldWave.shape.phase
|
||||
: (phase === 'auto' ? idx * Math.PI / 4 : phase);
|
||||
|
||||
var defaultSpeed = function (maxSpeed) {
|
||||
var cnt = data.count();
|
||||
return cnt === 0 ? maxSpeed : maxSpeed *
|
||||
(0.2 + (cnt - idx) / cnt * 0.8);
|
||||
};
|
||||
var speed = 0;
|
||||
if (maxSpeed === 'auto') {
|
||||
speed = defaultSpeed(5000);
|
||||
}
|
||||
else {
|
||||
speed = typeof maxSpeed === 'function'
|
||||
? maxSpeed(value, idx) : maxSpeed;
|
||||
}
|
||||
|
||||
// phase for moving left/right
|
||||
var phaseOffset = 0;
|
||||
if (direction === 'right' || direction == null) {
|
||||
phaseOffset = Math.PI;
|
||||
}
|
||||
else if (direction === 'left') {
|
||||
phaseOffset = -Math.PI;
|
||||
}
|
||||
else if (direction === 'none') {
|
||||
phaseOffset = 0;
|
||||
}
|
||||
else {
|
||||
console.error('Illegal direction value for liquid fill.');
|
||||
}
|
||||
|
||||
// wave animation of moving left/right
|
||||
if (direction !== 'none' && itemModel.get('waveAnimation')) {
|
||||
wave
|
||||
.animate('shape', true)
|
||||
.when(0, {
|
||||
phase: phase
|
||||
})
|
||||
.when(speed / 2, {
|
||||
phase: phaseOffset + phase
|
||||
})
|
||||
.when(speed, {
|
||||
phase: phaseOffset * 2 + phase
|
||||
})
|
||||
.during(function () {
|
||||
if (wavePath) {
|
||||
wavePath.dirty(true);
|
||||
}
|
||||
})
|
||||
.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* text on wave
|
||||
*/
|
||||
function getText(waves) {
|
||||
var labelModel = itemModel.getModel('label');
|
||||
|
||||
function formatLabel() {
|
||||
var formatted = seriesModel.getFormattedLabel(0, 'normal');
|
||||
var defaultVal = (data.get('value', 0) * 100);
|
||||
var defaultLabel = data.getName(0) || seriesModel.name;
|
||||
if (!isNaN(defaultVal)) {
|
||||
defaultLabel = defaultVal.toFixed(0) + '%';
|
||||
}
|
||||
return formatted == null ? defaultLabel : formatted;
|
||||
}
|
||||
|
||||
var textRectOption = {
|
||||
z2: 10,
|
||||
shape: {
|
||||
x: left,
|
||||
y: top,
|
||||
width: (isFillContainer ? radius[0] : radius) * 2,
|
||||
height: (isFillContainer ? radius[1] : radius) * 2
|
||||
},
|
||||
style: {
|
||||
fill: 'transparent'
|
||||
},
|
||||
textConfig: {
|
||||
position: labelModel.get('position') || 'inside'
|
||||
},
|
||||
silent: true
|
||||
};
|
||||
var textOption = {
|
||||
style: {
|
||||
text: formatLabel(),
|
||||
textAlign: labelModel.get('align'),
|
||||
textVerticalAlign: labelModel.get('baseline')
|
||||
}
|
||||
};
|
||||
Object.assign(textOption.style, echarts.helper.createTextStyle(labelModel));
|
||||
|
||||
var outsideTextRect = new echarts.graphic.Rect(textRectOption);
|
||||
var insideTextRect = new echarts.graphic.Rect(textRectOption);
|
||||
insideTextRect.disableLabelAnimation = true;
|
||||
outsideTextRect.disableLabelAnimation = true;
|
||||
|
||||
var outsideText = new echarts.graphic.Text(textOption);
|
||||
var insideText = new echarts.graphic.Text(textOption);
|
||||
outsideTextRect.setTextContent(outsideText);
|
||||
|
||||
insideTextRect.setTextContent(insideText);
|
||||
var insColor = labelModel.get('insideColor');
|
||||
insideText.style.fill = insColor;
|
||||
|
||||
var group = new echarts.graphic.Group();
|
||||
group.add(outsideTextRect);
|
||||
group.add(insideTextRect);
|
||||
|
||||
// clip out waves for insideText
|
||||
var boundingCircle = getPath(radius, true);
|
||||
|
||||
wavePath = new echarts.graphic.CompoundPath({
|
||||
shape: {
|
||||
paths: waves
|
||||
},
|
||||
x: cx,
|
||||
y: cy
|
||||
});
|
||||
|
||||
wavePath.setClipPath(boundingCircle);
|
||||
insideTextRect.setClipPath(wavePath);
|
||||
|
||||
return group;
|
||||
}
|
||||
},
|
||||
|
||||
dispose: function () {
|
||||
// dispose nothing here
|
||||
}
|
||||
});
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
module.exports = (env, options) => {
|
||||
return {
|
||||
entry: {
|
||||
'echarts-liquidfill': __dirname + '/index.js'
|
||||
},
|
||||
output: {
|
||||
libraryTarget: 'umd',
|
||||
library: ['echarts-liquidfill'],
|
||||
path: __dirname + '/dist',
|
||||
filename: options.mode === 'production' ? '[name].min.js' : '[name].js'
|
||||
},
|
||||
optimization: {
|
||||
concatenateModules: true
|
||||
},
|
||||
externals: {
|
||||
'echarts/lib/echarts': 'echarts'
|
||||
},
|
||||
devtool: 'source-map',
|
||||
resolve: {
|
||||
alias: {
|
||||
'echarts/lib/echarts': 'echarts'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user