higcharts3d 图

956 阅读3分钟

关于higcharts3D饼图及同心圆的实现

WechatIMG20.jpeg

最近一直在忙着做公司的数据可视化大屏项目,做了差不多有四五个的样子,今天偶然看见一篇写关于echarts的地图数据定时弹框的文章,索性自己开始写一篇关于highcharts3d的实现方法。

准备工作

  • 安装
npm install highcharts --save
  • 引入highcharts文件
import Highcharts from 'highcharts/highstock';
import Highcharts3D from 'highcharts/highcharts-3d';
Highcharts3D(Highcharts);
  • 参数公共配置文件 chartConfig.js
export function get3DPieOption(){
    let option = {
        chart: {
            type: 'pie',
            events:{
                load: function() {
                    var each = Highcharts.each,
                        points = this.series[0].points;
                    each(points, function(p, i) {
                        p.graphic.attr({
                            translateY: -p.shapeArgs.ran
                        });
                        p.graphic.side1.attr({
                            translateY: -p.shapeArgs.ran
                        });
                        p.graphic.side2.attr({
                            translateY: -p.shapeArgs.ran
                        });
                    });
                }
            },
            options3d: {
                enabled: true, // 开启3d
                alpha: 55,
                beta: 0
            }
        },
        title: {
            text:''
        },
        // 千以上的数字去掉空格
        lang: {
            thousandsSep: ''
        },
        // 隐藏版权信息
        credits:{
            enabled:false
        },
        colors:['#24BFFF', '#FCBE31', '#F74D52'],
        plotOptions: {
            pie: {
                center: [200, 71],
                size: 230,
                innerSize: 180, // 设置同心圆
                depth: 25,
                allowPointSelect: false,
                cursor: 'pointer',
                dataLabels: {
                    enabled: false
                },
                showInLegend: true,
                point: {
                    events: {
                        legendItemClick: function (event){                                    
                        return false; //return true 则表示允许切换
                        }
                    }
                }
            }
        },
        // 定时显示文本框配置, 可按照自身内容修改
        tooltip: {
            enabled: true,
            shared: true,
            backgroundColor: 'rgba(0, 33, 90, 0.8)',
            borderColor: '#4289D0',
            borderRadius: 0,
            followPointer: true,
            useHTML: true,
            style: {
                fontSize: 14,
                color: '#D9E8FF'
            },
            headerFormat: '<div style="width: auto;height: 50px;padding: 5px 2px;position: relative;">',
            pointFormat:        '<div style="position:absolute;left: -10px; top: -10px;width:15px;height: 15px;border: 2px solid #4289D0;border-bottom:none;border-right: none;"></div>'+
                '<div style="position:absolute;right: -10px; top: -10px;width:15px;height: 15px;border: 2px solid #4289D0;border-bottom:none;border-left: none;"></div>'+
                '<div style="position:absolute;left: -10px; bottom: -10px;width:15px;height: 15px;border: 2px solid #4289D0;border-top:none;border-right: none;"></div>'+
                '<div style="position:absolute;right: -10px; bottom: -10px;width:15px;height: 15px;border: 2px solid #4289D0;border-top:none;border-left: none;"></div>'+
                '<p style="padding-bottom: 3px;letter-spacing: 2px;">{point.name}:'+
                '<span style="color: #01DEFF;">{point.y}个</span></p>',
            footerFormat: '</div>',
        },
        series: [{            type: 'pie',            zIndex:1,            size:'95%', // 设置饼图的大小            center:['50%','75%'], // 设置饼图的位置
            allowPointSelect: false,
            dataLabels: {
                enabled: false,
            },
            name:'3D 饼图'
        },{
            type: 'pie',
            zIndex:0,
            depth: 15,
            center:['50%','75%'],
            name: '背景',
            colors:['#215795'],
            allowPointSelect: false,
            dataLabels: {
                enabled: false,
            },
            data:[
                {
                    name:'背景',
                    y:1,
                    h:1,
                    sliced: true,
                    selected: true
                }
            ]
        }]
    };
    return  option
}

起码

  1. 引入配置文件
import {get3DCircularDiagram} from '../chartConfig'
  1. 调用公共方法,渲染高度及参数配置
methods: {
    /***
     * 初始化图表
     */
    initChart(){
        let data = [{name: 'A', value: 30}, {name: 'B', value: 80}, {name: 'C', value: 70}]
        let f= function f(a,b) {  // 排序函数
            return (a - b);  
        }
        // 获取配置参数
        let option = get3DPieOption();
        let datas = data.map((item,index)=>{
            let formatData = {
                name: item.name,
                y: Number(item.value),
                h: 8
            }
            return {...formatData , sliced: true,selected: true }
        })
        option.series[0].data = datas;
        let charts = Highcharts.chart(chartId, option);               
        let d = charts?.series[0]?.data;
        // 实现信息弹框动态展示
        if(data.length > 0) {
            let index = 0, length = data.length - 1, k = null; // 播放所在下标
            this.timer = setInterval(function() {
                k = index === 0 ? length : index - 1;
                charts?.series?.[0]?.data[k].update({
                    h: 8
                });
                charts?.series?.[0]?.data[index].update({
                    h: 25
                });
                charts?.tooltip?.refresh([d[index]]);
                index++;
                if(index >= data.length) {
                    index = 0;
                }
            }, 5000);
        }
    }
}
  1. 在mounted中调用wrap方法、initChart方法
mounted() {
    this.initChart();
}
  1. 按数据大小实现饼图高度
methods: {
initChart(){
        let data = [{name: 'A', value: 30}, {name: 'B', value: 80}, {name: 'C', value: 70}]
        let f= function f(a,b) {  // 排序函数
            return (a - b);  
        }
        // 获取配置参数
        let option = get3DPieOption();
        // 对值进行排序
        let paixu = data.map(item=>{  
            return Number(item.value);
        });
        paixu.sort(f);
        let datas = data.map((item,index)=>{
            let h = paixu.indexOf(Number(item.value))+1
            let formatData = {
                name: item.name,
                y: Number(item.value),
                h: h*8  // 根据排序,设置高度
            }
            return {...formatData , sliced: true,selected: true }
        })
        option.series[0].data = datas;
        Highcharts.chart(chartId, option);    
    },
    /***
     * 处理  Highcharts 3D 模型
     */
    wrap(){
        let H = Object.assign({}, Highcharts)
        var each = H.each,
            round = Math.round,
            cos = Math.cos,
            sin = Math.sin,
            deg2rad = Math.deg2rad;
        H.wrap(H.seriesTypes.pie.prototype, 'translate', function(proceed) {
           proceed.apply(this, [].slice.call(arguments, 1));
            if (!this?.chart?.is3d()) {
                return;
            }
            var series = this,
                chart = series.chart,
                options = chart.options,
                seriesOptions = series.options,
                depth = seriesOptions.depth || 0,
                options3d = options.chart.options3d,
                alpha = options3d.alpha,
                beta = options3d.beta,
                z = seriesOptions.stacking ? (seriesOptions.stack || 0) * depth : series._i * depth;
            z += depth / 2;
            if (seriesOptions.grouping !== false) {
                z = 0;
            }
            each(series.data, (point)=> {
                var shapeArgs = point.shapeArgs,
                    angle;
                point.shapeType = 'arc3d';
                var ran = point.options.h;
                shapeArgs.z = z;
                shapeArgs.depth = depth * 0.75 + ran;
                shapeArgs.alpha = alpha;
                shapeArgs.beta = beta;
                shapeArgs.center = series.center;
                shapeArgs.ran = ran;
                angle = (shapeArgs.end + shapeArgs.start) / 2;
                point.slicedTranslation = {
                    translateX: round(cos(angle) * seriesOptions.slicedOffset * cos(alpha * deg2rad)),
                    translateY: round(sin(angle) * seriesOptions.slicedOffset * cos(alpha * deg2rad))
                };
            });
        });

        H.wrap(H.SVGRenderer.prototype, 'arc3dPath', function(proceed){
            let ret = proceed.apply(this, [].slice.call(arguments, 1));
            ret.zTop = (ret.zOut +1) / 100;
            return ret;
        });
    }
}
  1. 在mounted()中,在initChart()前调用wrap()方法
mounted() {
    this.wrap();
    this.initChart();
}

嗯,弄了一早上文档,摸鱼结束,现在开始上班了。请大佬们多多指正,谢谢大家!

highcharts的使用