pyecharts源码解读(9)渲染包render之engine模块:渲染引擎

当前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

engine模块

engine模块,路径为pyecharts/render/engine.py,作用为提供渲染接口(HTML和notebook)。

engine模块的结构如下图所示。

  • write_utf8_html_file(file_name: str, html_content: str)函数:根据HTML字符串生成HTML文件。
  • RenderEngine(env: Optional[Environment] = None)类:根据jinja2的环境变量提供渲染抽象接口。
  • render(chart, path: str, template_name: str, env: Optional[Environment], **kwargs) -> str函数:封装RenderEngine(env: Optional[Environment] = None)render_chart_to_file方法输出HTML文件。返回值为输出的HTML文件的路径。
  • render_embed(chart, template_name: str, env: Optional[Environment], **kwargs) -> str函数:封装RenderEngine(env: Optional[Environment] = None)render_chart_to_template方法输出HTML字符串。返回值为字符串。
  • render_notebook(self, notebook_template, lab_template)函数:将图表嵌入到notebook中,针对不同notebook类型提供不同输出方式。notebook和jupyter lab封装RenderEngine(env: Optional[Environment] = None)render_chart_to_notebook方法实现。返回值为pyecharts.render.display.HTML类对象。
  • load_javascript(chart)函数:为jupyter lab提供JavaScript支持,根据chart对象的JavaScript依赖库生成JavaScript代码。返回值为pyecharts.render.display.Javascript类对象。

在这里插入图片描述

engine模块的应用

根据图表对象基类Base的源码可知,图表类的渲染方法底层底层由engine模块的相应类、函数实现。

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)

    def render_notebook(self):
        self.chart_id = uuid.uuid4().hex
        self._prepare_render()
        return engine.render_notebook(
            self, "nb_jupyter_notebook.html", "nb_jupyter_lab.html"
        )

pyecharts/render/engine.py模块源码

import os
from collections import Iterable

from jinja2 import Environment

from ..commons import utils
from ..datasets import EXTRA, FILENAMES
from ..globals import CurrentConfig, NotebookType
from ..types import Any, Optional
from .display import HTML, Javascript


def write_utf8_html_file(file_name: str, html_content: str):
    with open(file_name, "w+", encoding="utf-8") as html_file:
        html_file.write(html_content)


class RenderEngine:
    def __init__(self, env: Optional[Environment] = None):
        self.env = env or CurrentConfig.GLOBAL_ENV

    @staticmethod
    def generate_js_link(chart: Any) -> Any:
        if not chart.js_host:
            chart.js_host = CurrentConfig.ONLINE_HOST
        links = []
        for dep in chart.js_dependencies.items:
            # TODO: if?
            if dep.startswith("https://api.map.baidu.com"):
                links.append(dep)
            if dep in FILENAMES:
                f, ext = FILENAMES[dep]
                links.append("{}{}.{}".format(chart.js_host, f, ext))
            else:
                for url, files in EXTRA.items():
                    if dep in files:
                        f, ext = files[dep]
                        links.append("{}{}.{}".format(url, f, ext))
                        break
        chart.dependencies = links
        return chart

    def render_chart_to_file(self, template_name: str, chart: Any, path: str, **kwargs):
        """
        Render a chart or page to local html files.

        :param chart: A Chart or Page object
        :param path: The destination file which the html code write to
        :param template_name: The name of template file.
        """
        tpl = self.env.get_template(template_name)
        html = utils.replace_placeholder(
            tpl.render(chart=self.generate_js_link(chart), **kwargs)
        )
        write_utf8_html_file(path, html)

    def render_chart_to_template(self, template_name: str, chart: Any, **kwargs) -> str:
        tpl = self.env.get_template(template_name)
        return utils.replace_placeholder(
            tpl.render(chart=self.generate_js_link(chart), **kwargs)
        )

    def render_chart_to_notebook(self, template_name: str, **kwargs) -> str:
        tpl = self.env.get_template(template_name)
        return utils.replace_placeholder(tpl.render(**kwargs))


def render(
    chart, path: str, template_name: str, env: Optional[Environment], **kwargs
) -> str:
    RenderEngine(env).render_chart_to_file(
        template_name=template_name, chart=chart, path=path, **kwargs
    )
    return os.path.abspath(path)


def render_embed(
    chart, template_name: str, env: Optional[Environment], **kwargs
) -> str:
    return RenderEngine(env).render_chart_to_template(
        template_name=template_name, chart=chart, **kwargs
    )


def render_notebook(self, notebook_template, lab_template):
    instance = self if isinstance(self, Iterable) else (self,)
    if CurrentConfig.NOTEBOOK_TYPE == NotebookType.JUPYTER_NOTEBOOK:
        require_config = utils.produce_require_dict(self.js_dependencies, self.js_host)
        return HTML(
            RenderEngine().render_chart_to_notebook(
                template_name=notebook_template,
                charts=instance,
                config_items=require_config["config_items"],
                libraries=require_config["libraries"],
            )
        )

    if CurrentConfig.NOTEBOOK_TYPE == NotebookType.JUPYTER_LAB:
        return HTML(
            RenderEngine().render_chart_to_notebook(
                template_name=lab_template, charts=instance
            )
        )

    if CurrentConfig.NOTEBOOK_TYPE == NotebookType.NTERACT:
        return HTML(self.render_embed())

    if CurrentConfig.NOTEBOOK_TYPE == NotebookType.ZEPPELIN:
        print("%html " + self.render_embed())


def load_javascript(chart):
    scripts = []
    for dep in chart.js_dependencies.items:
        f, ext = FILENAMES[dep]
        scripts.append("{}{}.{}".format(CurrentConfig.ONLINE_HOST, f, ext))
    return Javascript(lib=scripts)
pyechartsrender的时候会将图表渲染到HTML文件中,具体在屏幕中的位置由HTML文件的布局和样式决定。为了将图表渲染到屏幕中间,可以通过以下两种方法实现: 方法一:使用CSS样式 在HTML文件中,可以使用CSS样式将图表容器居中显示。首先,在HTML文件中找到pyecharts图表的容器元素的ID或者class,然后在CSS样式中为该元素设置居中的样式。示例代码如下: ``` <style> .chart-container { display: flex; justify-content: center; align-items: center; height: 100vh; } </style> <div id="chart-container" class="chart-container"></div> ``` 使用上述代码,将图表容器元素的class设置为"chart-container",并在CSS样式中设置该class的样式为居中。其中"100vh"是将容器元素的高度设置为视口高度的100%,这样可以确保图表在屏幕中垂直居中显示。 方法二:使用JavaScript 在pyechartsrender代码之前,可以通过JavaScript动态修改图表容器元素的样式,将其居中显示。示例代码如下: ``` <div id="chart-container"></div> <script> var chartContainer = document.getElementById('chart-container'); chartContainer.style.display = 'flex'; chartContainer.style.justifyContent = 'center'; chartContainer.style.alignItems = 'center'; </script> ``` 使用上述代码,在初始化图表容器元素的HTML代码之后,使用JavaScript动态修改该元素的样式,将其设置为居中显示。其中"display: flex"表示将该元素设置为flex布局,"justify-content: center"表示水平居中,"align-items: center"表示垂直居中。 通过上述两种方法,可以将pyecharts图表容器显示在屏幕的中间位置。根据具体需求选择适合的方法进行实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值