Echarts案例:使用極坐標加柱狀圖實現類似Apple Watch上的運動環形效果


分享自己公司項目類似的一個案例,用Echarts中的Polar(極坐標或稱為平面直角坐標系)和Bar(柱狀圖)實現的

大致效果是這樣的

參照的是AntV中的https://antv-f2.gitee.io/zh/examples/gallery/fitness-ring的效果,只不過我是用Echarts實現的
首先需要引入Echarts.js,推薦用npm下載:npm install echarts
或直接用cdn托管:https://www.bootcdn.cn/echarts/
源碼:https://gitee.com/DieHunter/myCode/tree/master/Echart/AppleWatch
以下是全部代碼:

HTML:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .chart_box {
            width: 300px;
            height: 300px;
            margin: 100px auto 0;
            background: #000;
        }
    </style>
    <script src="./echarts.js"></script>
</head>

<body>
    <div id="chart_box" class="chart_box"></div>
    <script type="module">
        import MyChart from './MyChart.js'
        MyChart.getInstance(echarts,chart_box).createChart()//初始化入口函數
    </script>
</body>

</html>

JS:

export default class MyChart {
    constructor(_echart, _ele) {
        this.timeTickId = null //定時器id
        this.timer = 1.5 //更新數據頻率
        this.option = null //當前echarts實例的屬性
        this._echart = _echart //引入Echarts
        this._ele = _ele //案例的父元素
        this.myChart = null //當前echarts實例
        this.colorList = ['#14A5AB', '#88D903', '#E90B3A'] //上層環背景
        this.bgList = ['#183C3D', '#324214', '#40131D'] //下層環背景
        this.maxCount = 100 //圓環最大值,即轉一圈的值
    }
    static getInstance() { //單例模式
        if (!MyChart._instance) {
            Object.defineProperty(MyChart, "_instance", {
                value: new MyChart(...arguments)
            })
        }
        return MyChart._instance;
    }
    createChart = () => {
        this.disposeChart() //創建前初始化chart實例,若有,則銷毀
        this.myChart = this._echart.init(this._ele)
        this.option = {
            angleAxis: {
                show: false, //隱藏角度軸(圓心角)
                max: this.maxCount,
                startAngle: 90, //極坐標從第一象限開始,即平面直角坐標系,用時鍾理解,0就是三點鍾方向,這里我們從12點鍾方向開始,也就是3點鍾方向加90度
                splitLine: {
                    show: false //隱藏分隔線
                },
            },
            barMaxWidth: 50, //設置圓環最大寬度
            radiusAxis: {
                show: false, //隱藏徑向軸(半徑)
                type: 'category',
                data: ['A', 'B', 'C'] //傳入每條圓環的徑向值
            },
            polar: {
                radius: [30, 150] //總體的最小半徑,最大半徑
            },
            series: [{ //上層的圓環
                    type: 'bar',
                    data: [1, 2, 3], //初始值
                    coordinateSystem: 'polar', //設置類型為極坐標
                    roundCap: true, //柱狀圖末端呈現圓角
                    itemStyle: { //設置每一個圓環的顏色
                        color: (params) => {
                            return this.colorList[params.dataIndex]
                        }
                    },
                    animationEasing: 'bounceOut', //初始動畫
                    barGap: '-100%', //柱間距離,用來將上下兩種圓環重合
                    z: 200, //圓環層級,和zindex相似
                },
                { //下層的圓環
                    type: 'bar',
                    data: [this.maxCount, this.maxCount, this.maxCount],
                    coordinateSystem: 'polar',
                    roundCap: true,
                    itemStyle: { //設置每一個圓環的顏色
                        color: (params) => {
                            return this.bgList[params.dataIndex]
                        }
                    },
                    z: 100,
                    barGap: '-100%', //柱間距離,用來將上下兩種圓環重合
                }
            ]
        };
        this.timeTick() //定時器入口
    }
    setOption = () => { //隨機數刷新數據
        if (this.option) {
            this.option.series[0].data = this.option.series[0].data.map(item => {
                return Math.random() * this.maxCount
            })
        }
        this.myChart.setOption(this.option, true)
    }
    disposeChart = () => { //初始化chart實例
        if (this.myChart) {
            this.myChart.dispose()
            this.myChart = null
            this.option = null
        }
    }
    timeTick = () => { //定時器,最好用延時加遞歸,如果用setInterval,容易造成堵塞
        if (this.timeTickId) {
            clearTimeout(this.timeTickId)
            this.timeTickId = 0
        }
        this.setOption()
        this.timeTickId = setTimeout(this.timeTick, 1000 * this.timer || 5000)
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM