pyecharts源码解读(10)渲染包render之templates目录:渲染模板

冯渝
2023-12-01

当前pyecharts版本为1.9.0

概述

render包结构

render包位于pyecharts包顶级目录中,用于渲染图表。render包结构如下:

├─render # 渲染设置包
│  │  display.py # 定义HTML、JavaScript显示类,用于支持在notebook中嵌入输出结果
│  │  engine.py # 定义渲染相关类、函数
│  │  snapshot.py # 定义渲染图片函数
│  │  __init__.py # 暴露渲染图片函数
│  │
│  ├─templates # 定义渲染模板
│  │      components.html
│  │      macro
│  │      nb_components.html
│  │      nb_jupyter_globe.html
│  │      nb_jupyter_lab.html
│  │      nb_jupyter_lab_tab.html
│  │      nb_jupyter_notebook.html
│  │      nb_jupyter_notebook_tab.html
│  │      nb_nteract.html
│  │      simple_chart.html
│  │      simple_globe.html
│  │      simple_page.html
│  │      simple_tab.html

templates目录

templates目录路径为pyecharts/render/templates,作用为存放渲染模板。

pyecharts使用jinja2库的模板引擎生成HTML。

templates目录中的文件主要有两类:

  • macro:模板宏定义。宏类似常规编程语言中的函数。它们用于把常用行为作为可重用的函数,取代手动重复的工作。宏还可以传递参数,因此可以实现pyecharts对象的渲染。
  • 模板文件:模板文件分为两大类,nb开头的html文件是针对notebook的模板,其余html文件是针对普通html文档的模板。

渲染模板实例:simple_chart.html

simple_chart.html是最基础的渲染模板,一般图表类实例的render()render_embed()方法渲染的HTML文件就使用的该模板。

通过对比pyecharts/charts/base.py模块源码、simple_chart.html源码、macro源码与渲染输出后的HTML内容可验证渲染的结果。

pyecharts/charts/base.py模块源码

from ..render import engine

class Base(ChartMixin):
    """
    `Base` is the root class for all graphical class, it provides
    part of the initialization parameters and common methods
    """

    def __init__(self, init_opts: Union[InitOpts, dict] = InitOpts()):
        _opts = init_opts
        if isinstance(init_opts, InitOpts):
            _opts = init_opts.opts

    def render(
        self,
        path: str = "render.html",
        template_name: str = "simple_chart.html",
        env: Optional[Environment] = None,
        **kwargs,
    ) -> str:
        self._prepare_render()
        return engine.render(self, path, template_name, env, **kwargs)
        
    def render_embed(
        self,
        template_name: str = "simple_chart.html",
        env: Optional[Environment] = None,
        **kwargs,
    ) -> str:
        self._prepare_render()
        return engine.render_embed(self, template_name, env, **kwargs)

simple_chart.html源码:

{% import 'macro' as macro %}
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>{{ chart.page_title }}</title>
    {{ macro.render_chart_dependencies(chart) }}
</head>
<body>
    {{ macro.render_chart_content(chart) }}
</body>
</html>

macro部分源码:

{%- macro render_chart_dependencies(c) -%}
    {% for dep in c.dependencies %}
        <script type="text/javascript" src="{{ dep }}"></script>
    {% endfor %}
{%- endmacro %}

{%- macro render_chart_content(c) -%}
    <div id="{{ c.chart_id }}" class="chart-container" style="width:{{ c.width }}; height:{{ c.height }};"></div>
    <script>
        var chart_{{ c.chart_id }} = echarts.init(
            document.getElementById('{{ c.chart_id }}'), '{{ c.theme }}', {renderer: '{{ c.renderer }}'});
        {% for js in c.js_functions.items %}
            {{ js }}
        {% endfor %}
        var option_{{ c.chart_id }} = {{ c.json_contents }};
        chart_{{ c.chart_id }}.setOption(option_{{ c.chart_id }});
        {% if c._is_geo_chart %}
            var bmap = chart_{{ c.chart_id }}.getModel().getComponent('bmap').getBMap();
            {% if c.bmap_js_functions %}
                {% for fn in c.bmap_js_functions.items %}
                    {{ fn }}
                {% endfor %}
            {% endif %}
        {% endif %}
        {% if c.width.endswith('%') %}
            window.addEventListener('resize', function(){
                chart_{{ c.chart_id }}.resize();
            })
        {% endif %}
    </script>
{%- endmacro %}

实例代码:

from pyecharts.charts import Bar

bar=Bar()

print(bar.render_embed())

输出:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Awesome-pyecharts</title>
            <script type="text/javascript" src="https://assets.pyecharts.org/assets/echarts.min.js"></script>

</head>
<body>
    <div id="b3dd198f42664743af1200bacef7c9c4" class="chart-container" style="width:900px; height:500px;"></div>
    <script>
        var chart_b3dd198f42664743af1200bacef7c9c4 = echarts.init(
            document.getElementById('b3dd198f42664743af1200bacef7c9c4'), 'white', {renderer: 'canvas'});
        var option_b3dd198f42664743af1200bacef7c9c4 = {
    "animation": true,
    "animationThreshold": 2000,
    "animationDuration": 1000,
    "animationEasing": "cubicOut",
    "animationDelay": 0,
    "animationDurationUpdate": 300,
    "animationEasingUpdate": "cubicOut",
    "animationDelayUpdate": 0,
    "color": [
        "#c23531",
        "#2f4554",
        "#61a0a8",
        "#d48265",
        "#749f83",
        "#ca8622",
        "#bda29a",
        "#6e7074",
        "#546570",
        "#c4ccd3",
        "#f05b72",
        "#ef5b9c",
        "#f47920",
        "#905a3d",
        "#fab27b",
        "#2a5caa",
        "#444693",
        "#726930",
        "#b2d235",
        "#6d8346",
        "#ac6767",
        "#1d953f",
        "#6950a1",
        "#918597"
    ],
    "series": [],
    "legend": [
        {
            "data": [],
            "selected": {}
        }
    ],
    "tooltip": {
        "show": true,
        "trigger": "item",
        "triggerOn": "mousemove|click",
        "axisPointer": {
            "type": "line"
        },
        "showContent": true,
        "alwaysShowContent": false,
        "showDelay": 0,
        "hideDelay": 100,
        "textStyle": {
            "fontSize": 14
        },
        "borderWidth": 0,
        "padding": 5
    },
    "xAxis": [
        {
            "show": true,
            "scale": false,
            "nameLocation": "end",
            "nameGap": 15,
            "gridIndex": 0,
            "inverse": false,
            "offset": 0,
            "splitNumber": 5,
            "minInterval": 0,
            "splitLine": {
                "show": false,
                "lineStyle": {
                    "show": true,
                    "width": 1,
                    "opacity": 1,
                    "curveness": 0,
                    "type": "solid"
                }
            }
        }
    ],
    "yAxis": [
        {
            "show": true,
            "scale": false,
            "nameLocation": "end",
            "nameGap": 15,
            "gridIndex": 0,
            "inverse": false,
            "offset": 0,
            "splitNumber": 5,
            "minInterval": 0,
            "splitLine": {
                "show": false,
                "lineStyle": {
                    "show": true,
                    "width": 1,
                    "opacity": 1,
                    "curveness": 0,
                    "type": "solid"
                }
            }
        }
    ]
};
        chart_b3dd198f42664743af1200bacef7c9c4.setOption(option_b3dd198f42664743af1200bacef7c9c4);
    </script>
</body>
</html>
 类似资料: