superset集成echarts,自定义图表开发

环境

系统:centos7
python版本:3.7.6
superset版本:0.30
echarts版本:4.2.0以上

说明

因为一开始使用pip安装方法)直接安装的时候,进入安装路径下没有src目录。又是一开始接触superset,所以就用源码安装了。

源码安装方法

搭建Anaconda虚拟环境

  1. 首先下载安装文件Anaconda3-2019.10-Linux-x86_64.sh
    进入官网地址:https://www.anaconda.com/distribution/#download-section,选择对应版本下载。
  2. 安装anaconda软件sh Anaconda3-2019.10-Linux-x86_64.sh
    安装过程中需要输入yes和回车。
  3. 配置conda环境变量。
vim /etc/profile
# 添加如下几行,具体路径根据实际情况调整
export CONDA_HOME=/root/anaconda3
export PATH=$CONDA_HOME/bin:$PATH
# source 刚刚修改的文件
source /etc/profile
  1. 修改Anaconda的镜像文件
    安装Anaconda用户的家目录(需要注意的是用户的家目录,而不是CONDA_HOME目录,所以这里是/root下)下创建.condarc文件,并添加如下内容
channels:
  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
show_channel_urls: true

也可以通过如下命令修改:

# 第一次运行下面的命令时,会自动在用户的家目录下创建 `.condarc` 文件
conda config
# 查看源
conda config --show-sources
# 修改源
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
# 设置搜索时显示通道地址
conda config --set show_channel_urls yes
  1. 在系统中添加如下依赖:
yum upgrade python-setuptools
yum install gcc gcc-c++ libffi-devel python-devel python-pip python-wheel openssl-devel libsasl2-devel openldap-devel
  1. 为了避免不同版本python之前相互冲突,创建python的虚拟环境(因为之前conda环境变量已配好,所以可以直接使用如下命令)。
conda create -n superset python=3.7
# 删除的时候可以使用下面的命令
# conda remove -n superset --all
  1. 进入虚拟环境环境,使用 source activate superset,(退出时使用source deactivate superset即可)

源码安装superset

  1. 首先从github上clone源码,github代码地址:https://github.com/apache/incubator-superset.git
  2. 下载好之后切换到你所需要安装的分支,我这里选择的是0.30
  3. 利用SFTP工具将代码复制到服务器某个目录下,我选择的是/root/anaconda3/envs/superset目录
  4. 之后按照如下命令输入即可
# 进入到源码的assets目录下
cd /root/anaconda3/envs/superset/incubator-superset/superset/assets

# 进行依赖的下载安装,因为过程中可能会报权限不足的错误,所以添加参数 --unsafe-perm=true --allow-root
npm install --unsafe-perm=true --allow-root -d

# 依赖下载完成之后修改如下配置文件
vim node_modules/webpack/lib/WebpackOptionsDefaulter.js
# 将文件中maxEntrypointSize的值(250000)修改为50000000,maxAssetSize的值(250000)修改为30000000
# 修改为如下所示
# this.set("performance.maxAssetSize", 30000000);
# this.set("performance.maxEntrypointSize", 50000000);

# 安装 core-js@2 依赖
npm install core-js@2

# 然后就可以编译了
npm run build

# 返回上一级目录
cd ..
# 前端编译完后,将incubator-superset-0.28.1/superset/static/目录下的assets链接文件删掉
rm -rf static/assets
# 将整个assets文件夹移动到incubator-superset-0.28.1/superset/static/目录下
cp -r assets/ static/

# 进入源码的根目录
cd /root/anaconda3/envs/superset/incubator-superset/

# 安装 requirements.txt 中的依赖(使用国内的源,不然会很慢)。过程可能会比较长,而且有的依赖可能会卡住,所以那个依赖可以手动安装
pip install -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com/simple -r requirements.txt

# 安装numpy模块
pip install numpy -U

# 现在就可以直接安装了
python setup.py install

# 查看安装是否成功,出现下面的版本号,就安装成功了
superset version

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Superset 0.30.0rc13
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1. 安装完成之后就可以进行如下配置使用了
# 创建一个admin用户,用户名为superset,并设置密码等参数
fabmanager create-admin --app superset
# 初始化数据库
superset db upgrade
# 加载一些使用的示例
superset load_examples
# 创建默认的角色和初始化权限
superset init
# 启动superset的web server
superset runserver
# 但是superset某个版本以后就不支持上面的命令了,0.30就不支持。所以运行如下命令:
superset run -p 端口号 -h ip地址

因为我之前在别的虚拟环境中安装过别的版本的superset,所以第一步就报了个错:alembic.util.exc.CommandError: Can't locate revision identified by '4a5a7be6c05a',这个是因为superset默认使用的是SQLite数据库,默认路径是/root/.superset,所以这里直接删除这个数据库(rm -rf /root/.superset),再重新运行上面的命令即可。

  1. 打开浏览器输入刚刚设置的ip地址和端口号就可以访问了。

集成echarts中的漏斗图echarts_funnel

因为网上的教程基本都是0.28的,而0.30的superset目录结构又做了大改动,所以这一步真是走的一言难尽。一开始直接用 pip install superset 安装的,superset的目录下居然没有src,我就直接从源码中copy了src放到superset的对应目录下,不知道是我操作有问题还是这样做就是错的,没有集成成功(我也没有时间去试验了,如果有人这样安装成功了,麻烦留言告诉我一声,谢谢),所以索性就直接源码安装。皇天不负有心人,源码安装之后慢慢的就摸索出来了。虽然摸索出来了,有的步骤到底为什么这样做,还是不理解。等后面在慢慢了解吧。废话说了这么多,下面开始进入正题吧。
下面以漏斗图echarts_funnel为例,介绍如何在superset中集成echarts图表

修改viz.py文件

修改viz.py文件,文件路径为:/root/anaconda3/envs/superset/lib/python3.7/site-packages/superset-0.30.0rc13-py3.7.egg/superset,注册echarts_funnel图表类型。
找到TableViz,在上面添加EchartsFunnelViz

    def get_csv(self):
        df = self.get_df()
        include_index = not isinstance(df.index, pd.RangeIndex)
        return df.to_csv(index=include_index, **config.get('CSV_EXPORT'))

    def get_data(self, df):
        return df.to_dict(orient='records')

    @property
    def json_data(self):
        return json.dumps(self.data)

# 下面一段是添加的代码
class EchartsFunnelViz(BaseViz):

    viz_type = 'echarts_funnel'
    is_timeseries = False

    def get_data(self, df):
        fd = self.form_data
        metric = self.metric_labels[0]
        columns = fd.get('groupby')
        print(metric)
        df = df.pivot_table(
            index=self.groupby,
            values=[metric]
        )
        df.sort_values(by=metric, ascending=False, inplace=True)
        df = df.reset_index()
        df.columns = ['name', 'value']
        return df.to_dict(orient='records')


class TableViz(BaseViz):

    """A basic html table that is sortable and searchable"""

    viz_type = 'table'
    verbose_name = _('Table View')
    credits = 'a <a href="https://github.com/airbnb/superset">Superset</a> original'
    is_timeseries = False
    enforce_numerical_metrics = False

添加echarts依赖

进入static/assets目录,vim package.json。在dependencies中增加echarts的依赖"echarts": "^4.2.0",版本号可以根据实际情况改变,我这里使用的是4.2.0以上的版本。

添加图表的controlPanelSections

这一步添加的就是图表的DataVisual Properties等配置。如下图所示:
在这里插入图片描述
进入src/explore/controlPanels路径下,创建EchartsFunnel.js文件。文件内容如下:

import { t } from '@superset-ui/translation';
export default {
    controlPanelSections: [
        {
        label: t('Query'),
        expanded: true,
        controlSetRows: [
            ['metrics', 'groupby'],
            ['limit'],
        ],
        },
        {
        label: t('Chart Options'),
        controlSetRows: [
            ['color_scheme'],
        ],
        },
    ],
};

然后在该目录下的index.js中注册刚刚写的这个js文件。

  1. 引入:import EchartsFunnel from './EchartsFunnel';
  2. controlPanelConfigs中配置,添加echarts_funnel: EchartsFunnel,

绘制图表模板

  1. 进入assets目录下的src/visualizations目录,创建EchartsFunnel文件夹。
  2. EchartsFunnel文件夹下创建images文件夹,然后进入echarts官网,截取或者下载一张漏斗图的图片放到images文件夹下,命名为thumbnail.png
  3. 创建EchartsFunnel.js文件,文件内容如下:
import echarts from 'echarts';
import {getColorFromScheme} from '../../modules/colors';

function echartsFunnelVis(payload, slice) {
    const div = d3.select(payload);
    var html = '<div id="main" style="width: ' + slice.width + ''
        + 'px;height:' + slice.height + 'px;">haha</div>';
    div.html(html);
    var myChart = echarts.init(document.getElementById('main'));
    var option = {
        title: {
            text: '',
            subtext: '纯属虚构',
            left: 'left',
            top: 'bottom'
        },
        tooltip: {
            trigger: 'item',
            formatter: "{a} <br/>{b} : {c}%"
        },
        toolbox: {
            show: true,
            orient: 'vertical',
            top: 'center',
            feature: {
                dataView: {readOnly: false},
                restore: {},
                saveAsImage: {}
            }
        },
        legend: {
            orient: 'vertical',
            left: 'left',
            data: []
        },
        calculable: true,
        series: [
            {
                name: '漏斗图',
                type: 'funnel',
                width: '40%',
                height: '45%',
                left: '5%',
                top: '50%',
                funnelAlign: 'right',
                center: ['25%', '25%'],  // for pie
                data: []
            },
            {
                name: '金字塔',
                type: 'funnel',
                width: '40%',
                height: '45%',
                left: '5%',
                top: '5%',
                sort: 'ascending',
                funnelAlign: 'right',
                center: ['25%', '75%'],  // for pie
                data: []
            },
            {
                name: '漏斗图',
                type: 'funnel',
                width: '40%',
                height: '45%',
                left: '55%',
                top: '5%',
                funnelAlign: 'left',
                center: ['75%', '25%'],  // for pie
                data: []
            },
            {
                name: '金字塔',
                type: 'funnel',
                width: '40%',
                height: '45%',
                left: '55%',
                top: '50%',
                sort: 'ascending',
                funnelAlign: 'left',
                center: ['75%', '75%'],  // for pie
                data: []
            }
        ]
    };
    myChart.setOption(option);

    const json = slice.data;
    var data_name = [];
    var max_value = 0;
    const data = json;
    data.forEach(function (item, index, array) {
        data_name.push(item['name']);
        if (item['value'] > max_value) {
            max_value = item['value'];
        }
    });
    var tmp_series = [];
    for (var i = 1; i < 5; i++) {
        tmp_series.push({
            data: data
        });
    }
    var option2 = {
        legend: {data: data_name},
        series: tmp_series
    };

    myChart.setOption(option2);
}

export default echartsFunnelVis;
  1. 创建transformProps.js文件(用来处理接收参数的数据内容及格式),文件内容如下:
export default function transformProps(chartProps) {
  const { width, height, payload } = chartProps;
  console.log(chartProps); //可以用来验证数据是否正确
    return {
        data: payload.data,
        width,
        height,
    };
}
  1. 创建ReactEchartsFunnel.js文件(这个文件是干啥的我也不知道—_— !),文件内容如下:
import reactify from '../../utils/reactify';
import Component from './EchartsFunnel';

export default reactify(Component);
  1. 创建EchartsFunnelChartPlugin.js文件,文件内容如下:
import { t } from '@superset-ui/translation';
import { ChartMetadata, ChartPlugin } from '@superset-ui/chart';
import transformProps from './transformProps';
import thumbnail from './images/thumbnail.png';
import { ANNOTATION_TYPES } from '../../modules/AnnotationTypes';

const metadata = new ChartMetadata({
  name: t('echarts funnel'),
  description: '',
  canBeAnnotationTypes: [
    ANNOTATION_TYPES.EVENT,
    ANNOTATION_TYPES.INTERVAL,
  ],
  thumbnail,
});

export default class EchartsFunnelChartPlugin extends ChartPlugin {
  constructor() {
    super({
      metadata,
      transformProps,
      loadChart: () => import('./ReactEchartsFunnel.js'),
    });
  }
}
  1. 注册刚刚创建的plugin
    进入cd ../presets/,在CommonChartPreset.js文件中引入import EchartsFunnelChartPlugin from '../EchartsFunnel/EchartsFunnelChartPlugin';,并注册new EchartsFunnelChartPlugin().configure({ key: 'echarts_funnel' }),
  2. 进入assets目录下,npm install,然后npm run dev即可。
  3. 运行supersetsuperset run -h IP地址 -p 端口号

然后就大功告成了。

发布了26 篇原创文章 · 获赞 1 · 访问量 6963

猜你喜欢

转载自blog.csdn.net/qq_39800434/article/details/103808139