洞察掌握android电视app开发中的安全与合规策略,提升企业运营效率
1085
2022-10-10
pyecharts 源码分析-直角坐标系图表(源码+解析)
目录
1、在从pyecharts.charts导入Bar:
2、其实,直角坐标系下所有的图表都继承了 RectChart 类。
3、RectChart 类 继承了 Chart 类,我们再来看 Chart 类,惊喜在最后~
我们以Bar为例:
from pyecharts.charts import Bar
1、在从pyecharts.charts导入Bar:
"""学习中遇到问题没人解答?小编创建了一个Python学习交流QQ群:732481539寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!"""class Bar(RectChart): """ <<< Bar Chart >>> Bar chart presents categorical data with rectangular bars with heights or lengths proportional to the values that they represent. """ def add_yaxis( # 系列名称,用于 tooltip 的显示,legend 的图例筛选。 series_name: str, # 系列数据 y_axis: Sequence[Numeric, opts.BarItem, dict], # 是否选中图例 is_selected: bool = True, # 使用的 x 轴的 index,在单个图表实例中存在多个 x 轴的时候有用。 xaxis_index: Optional[Numeric] = None, # 使用的 y 轴的 index,在单个图表实例中存在多个 y 轴的时候有用。 yaxis_index: Optional[Numeric] = None, # 是否启用图例 hover 时的联动高亮 is_legend_hover_link: bool = True, # 系列 label 颜色 color: Optional[str] = None, # 是否显示柱条的背景色。通过 backgroundStyle 配置背景样式。 is_show_background: bool = False, # 每一个柱条的背景样式。需要将 showBackground 设置为 true 时才有效。 background_style: types.Union[types.BarBackground, dict, None] = None, # 数据堆叠,同个类目轴上系列配置相同的 stack 值可以堆叠放置。 stack: Optional[str] = None, # 柱条的宽度,不设时自适应。 # 可以是绝对值例如 40 或者百分数例如 '60%'。百分数基于自动计算出的每一类目的宽度。 # 在同一坐标系上,此属性会被多个 'bar' 系列共享。此属性应设置于此坐标系中最后一个 'bar' 系列上才会生效,并且是对此坐标系中所有 'bar' 系列生效。 bar_width: types.Union[types.Numeric, str] = None, # 柱条的最大宽度。比 barWidth 优先级高。 bar_max_width: types.Union[types.Numeric, str] = None, # 柱条的最小宽度。在直角坐标系中,默认值是 1。否则默认值是 null。比 barWidth 优先级高。 bar_min_width: types.Union[types.Numeric, str] = None, # 柱条最小高度,可用于防止某数据项的值过小而影响交互。 bar_min_height: types.Numeric = 0, # 同一系列的柱间距离,默认为类目间距的 20%,可设固定值 category_gap: Union[Numeric, str] = "20%", # 不同系列的柱间距离,为百分比(如 '30%',表示柱子宽度的 30%)。 # 如果想要两个系列的柱子重叠,可以设置 gap 为 '-100%'。这在用柱子做背景的时候有用。 gap: Optional[str] = "30%", # 是否开启大数据量优化,在数据图形特别多而出现卡顿时候可以开启。 # 开启后配合 largeThreshold 在数据量大于指定阈值的时候对绘制进行优化。 # 缺点:优化后不能自定义设置单个数据项的样式。 is_large: bool = False, # 开启绘制优化的阈值。 large_threshold: types.Numeric = 400, # 使用 dimensions 定义 series.data 或者 dataset.source 的每个维度的信息。 # 注意:如果使用了 dataset,那么可以在 dataset.source 的第一行/列中给出 dimension 名称。 # 于是就不用在这里指定 dimension。 # 但是,如果在这里指定了 dimensions,那么 ECharts 不再会自动从 dataset.source 的第一行/列中获取维度信息。 dimensions: types.Union[types.Sequence, None] = None, # 当使用 dataset 时,seriesLayoutBy 指定了 dataset 中用行还是列对应到系列上,也就是说,系列“排布”到 dataset 的行还是列上。可取值: # 'column':默认,dataset 的列对应于系列,从而 dataset 中每一列是一个维度(dimension)。 # 'row':dataset 的行对应于系列,从而 dataset 中每一行是一个维度(dimension)。 series_layout_by: str = "column", # 如果 series.data 没有指定,并且 dataset 存在,那么就会使用 dataset。 # datasetIndex 指定本系列使用那个 dataset。 dataset_index: types.Numeric = 0, # 是否裁剪超出坐标系部分的图形。柱状图:裁掉所有超出坐标系的部分,但是依然保留柱子的宽度 is_clip: bool = True, # 柱状图所有图形的 zlevel 值。 z_level: types.Numeric = 0, # 柱状图组件的所有图形的z值。控制图形的前后顺序。 # z值小的图形会被z值大的图形覆盖。 # z相比zlevel优先级更低,而且不会创建新的 Canvas。 z: types.Numeric = 2, # 标签配置项,参考 `series_options.LabelOpts` label_opts: Union[opts.LabelOpts, dict] = opts.LabelOpts(), # 标记点配置项,参考 `series_options.MarkPointOpts` markpoint_opts: Union[opts.MarkPointOpts, dict, None] = None, # 标记线配置项,参考 `series_options.MarkLineOpts` markline_opts: Union[opts.MarkLineOpts, dict, None] = None, # 提示框组件配置项,参考 `series_options.TooltipOpts` tooltip_opts: Union[opts.TooltipOpts, dict, None] = None, # 图元样式配置项,参考 `series_options.ItemStyleOpts` itemstyle_opts: Union[opts.ItemStyleOpts, dict, None] = None, # 可以定义 data 的哪个维度被编码成什么。 encode: types.Union[types.JSFunc, dict, None] = None,)
我们发现Bar继承了
RectChart 类
2、其实,直角坐标系下所有的图表都继承了 RectChart 类。
我们再来看 RectChart 类
class RectChart(Chart): def __init__(self, init_opts: types.Init = opts.InitOpts()): super().__init__(init_opts=init_opts) self.options.update(xAxis=[opts.AxisOpts().opts], yAxis=[opts.AxisOpts().opts]) # 扩展x/y轴 def extend_axis( self, # 扩展 X 坐标轴数据项 xaxis_data: Sequence = None, # 扩展 X 坐标轴配置项,参考 `global_options.AxisOpts` xaxis: Union[opts.AxisOpts, dict, None] = None, # 新增 Y 坐标轴配置项,参考 `global_options.AxisOpts` yaxis: Union[opts.AxisOpts, dict, None] = None, ): if xaxis is not None: if isinstance(xaxis, opts.AxisOpts): xaxis = xaxis.opts xaxis.update(data=xaxis_data) self.options["xAxis"].append(xaxis) if yaxis is not None: if isinstance(yaxis, opts.AxisOpts): yaxis = yaxis.opts self.options["yAxis"].append(yaxis) return self # 新增x轴数据 def add_xaxis(self, xaxis_data: Sequence): self.options["xAxis"][0].update(data=xaxis_data) # X 轴数据项 self._xaxis_data = xaxis_data return self # 翻转xy轴数据 def reversal_axis(self): self.options["yAxis"][0]["data"] = self._xaxis_data self.options["xAxis"][0]["data"] = None return self # 层叠多图 chart为直角坐标系类型图表 def overlap(self, chart: Base): self.options.get("legend")[0].get("data").extend( chart.options.get("legend")[0].get("data") ) self.options.get("legend")[0].get("selected").update( chart.options.get("legend")[0].get("selected") ) self.options.get("series").extend(chart.options.get("series")) return self
3、RectChart 类 继承了 Chart 类,我们再来看 Chart 类,惊喜在最后~
class Chart(Base): def __init__(self, init_opts: types.Init = opts.InitOpts()): if isinstance(init_opts, dict): temp_opts = opts.InitOpts() temp_opts.update(**init_opts) init_opts = temp_opts super().__init__(init_opts=init_opts) self.colors = ( "#c23531 #2f4554 #61a0a8 #d48265 #749f83 #ca8622 #bda29a #6e7074 " "#546570 #c4ccd3 #f05b72 #ef5b9c #f47920 #905a3d #fab27b #2a5caa " "#444693 #726930 #b2d235 #6d8346 #ac6767 #1d953f #6950a1 #918597" ).split() if init_opts.opts.get("theme") == ThemeType.WHITE: self.options.update(color=self.colors) self.options.update( series=[], legend=[{"data": [], "selected": dict()}], tooltip=opts.TooltipOpts().opts, ) self._chart_type: Optional[str] = None def set_colors(self, colors: Sequence[str]): self.options.update(color=colors) return self def set_series_opts( self, label_opts: types.Label = None, linestyle_opts: types.LineStyle = None, splitline_opts: types.SplitLine = None, areastyle_opts: types.AreaStyle = None, axisline_opts: types.AxisLine = None, markpoint_opts: types.MarkPoint = None, markline_opts: types.MarkLine = None, markarea_opts: types.MarkArea = None, effect_opts: types.Effect = opts.EffectOpts(), tooltip_opts: types.Tooltip = None, itemstyle_opts: types.ItemStyle = None, **kwargs, ): for s in self.options.get("series"): if label_opts: s.update(label=label_opts) if linestyle_opts: s.update(lineStyle=linestyle_opts) if splitline_opts: s.update(splitLine=splitline_opts) if areastyle_opts: s.update(areaStyle=areastyle_opts) if axisline_opts: s.update(axisLine=axisline_opts) if markpoint_opts: s.update(markPoint=markpoint_opts) if markline_opts: s.update(markLine=markline_opts) if markarea_opts: s.update(markArea=markarea_opts) if effect_opts: s.update(rippleEffect=effect_opts) if tooltip_opts: s.update(tooltip=tooltip_opts) if itemstyle_opts: s.update(itemStyle=itemstyle_opts) if len(kwargs) > 0: s.update(kwargs) return self def _append_legend(self, name, is_selected): self.options.get("legend")[0].get("data").append(name) self.options.get("legend")[0].get("selected").update({name: is_selected}) def _append_color(self, color: Optional[str]): if color: self.colors = [color] + self.colors if self.theme == ThemeType.WHITE: self.options.update(color=self.colors) def set_global_opts( self, title_opts: types.Title = opts.TitleOpts(), legend_opts: types.Legend = opts.LegendOpts(), tooltip_opts: types.Tooltip = None, toolbox_opts: types.Toolbox = None, brush_opts: types.Brush = None, xaxis_opts: types.Axis = None, yaxis_opts: types.Axis = None, visualmap_opts: types.VisualMap = None, datazoom_opts: types.DataZoom = None, graphic_opts: types.Graphic = None, axispointer_opts: types.AxisPointer = None, ): if tooltip_opts is None: tooltip_opts = opts.TooltipOpts( formatter=ToolTipFormatterType.get(self._chart_type, None) ) self.options.update( title=title_opts, toolbox=toolbox_opts, tooltip=tooltip_opts, visualMap=visualmap_opts, dataZoom=datazoom_opts, graphic=graphic_opts, axisPointer=axispointer_opts, ) if brush_opts is not None: self.options.update(brush=brush_opts) if isinstance(legend_opts, opts.LegendOpts): legend_opts = legend_opts.opts for _s in self.options["legend"]: _s.update(legend_opts) if xaxis_opts and self.options.get("xAxis", None): if isinstance(xaxis_opts, opts.AxisOpts): xaxis_opts = xaxis_opts.opts self.options["xAxis"][0].update(xaxis_opts) if yaxis_opts and self.options.get("yAxis", None): if isinstance(yaxis_opts, opts.AxisOpts): yaxis_opts = yaxis_opts.opts self.options["yAxis"][0].update(yaxis_opts) return self def add_dataset( self, # 原始数据。一般来说,原始数据表达的是二维表。 source: types.Union[types.Sequence, types.JSFunc] = None, # 使用 dimensions 定义 series.data 或者 dataset.source 的每个维度的信息。 dimensions: types.Optional[types.Sequence] = None, # dataset.source 第一行/列是否是 维度名 信息。可选值: # null/undefine(对应 Python 的 None 值):默认,自动探测。 # true:第一行/列是维度名信息。 # false:第一行/列直接开始是数据。 source_header: types.Optional[bool] = None, ): self.options.update( dataset={ "source": source, "dimensions": dimensions, "sourceHeader": source_header, } ) return self
我们又发现 每个class都返回为self,这也就是为什么python支持链式调用的原因了。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~