HighCharts源码解析之Class体系
HighCharts
是一个默认使用SVG
渲染器的图表引擎,其对内部的DOM
元素都设置了Class
属性以描述其类别和样式。起到了类似ECharts theme的效果。
图表中的Dom结构及Class示例
以下是封面图的部分DOM
结构以及Class
名称。HighCharts
基本对图表内的所有图元都定义了Class
属性。其中的命名规律为以highcharts-
作为前缀、辅以语义化的说明。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
| <figure class="highcharts-figure"> <div id="container" ...> <div class="highcharts-announcer-container"> <div class="highcharts-container" ...> <div class="highcharts-a11y-proxy-container-before" ...></div> <svg version="1.1" class="highcharts-root" ...> <rect class="highcharts-background" ...></rect> <rect class="highcharts-plot-background" ...></rect> <g class="highcharts-grid highcharts-xaxis-grid" ...> <path class="highcharts-grid-line" ...></path> <path class="highcharts-grid-line" ...></path> <path class="highcharts-grid-line" ...></path> ... </g> <g class="highcharts-grid highcharts-yaxis-grid"> <path class="highcharts-grid-line" ...></path> <path class="highcharts-grid-line" ...></path> <path class="highcharts-grid-line" ...></path> ... </g> <rect class="highcharts-plot-border" ...></rect> <g class="highcharts-axis highcharts-xaxis" ...> <path class="highcharts-tick"></path> <path class="highcharts-tick"></path> <path class="highcharts-tick"></path> 。。。 </g> <g class="highcharts-axis highcharts-yaxis" ...> <text class="highcharts-axis-title" ...>Exchange rate</text> <path class="highcharts-axis-line" ...></path> </g> <g class="highcharts-series-group" ...> <g class="highcharts-series highcharts-series-0 highcharts-area-series" ... > <path class="highcharts-area" ...></path> <path class="highcharts-graph" ...></path> <path class="highcharts-tracker-line" ...></path> </g> <g class="highcharts-markers highcharts-series-0 highcharts-area-series highcharts-tracker" ... > <path class="highcharts-halo highcharts-color-undefined" ... ></path> <path class="highcharts-point" ...></path> </g> </g> <g class="highcharts-exporting-group" ...> <g class="highcharts-no-tooltip highcharts-button highcharts-contextbutton" ... > <rect class="highcharts-button-box" ...></rect> <path class="highcharts-button-symbol" ...></path> </g> </g> <text class="highcharts-title">...</text> <text class="highcharts-subtitle" ...>...</text> <text class="highcharts-caption" ...></text> <g class="highcharts-no-tooltip highcharts-button highcharts-reset-zoom" ... > <rect class="highcharts-button-box" ...></rect> </g> <g class="highcharts-axis-labels highcharts-xaxis-labels" ...> <text>...</text> </g> <g class="highcharts-axis-labels highcharts-yaxis-labels" ...> <text>...</text> </g> <text class="highcharts-credits"></text> <g class="highcharts-label highcharts-tooltip highcharts-color-undefined" ... > <path class="highcharts-label-box highcharts-tooltip-box" ... ></path> <text></text> </g> </svg> <div class="highcharts-a11y-proxy-container-after" ...> <div class="highcharts-a11y-proxy-group highcharts-a11y-proxy-group-zoom" > <button class="highcharts-a11y-proxy-element highcharts-no-tooltip" ... ></button> </div> <div class="highcharts-a11y-proxy-group highcharts-a11y-proxy-group-chartMenu" > <button class="highcharts-a11y-proxy-element highcharts-no-tooltip" ... ></button> </div> </div> </div> <div id="highcharts-screen-reader-region-after-0" ...> <div></div> </div> </div> <p class="highcharts-description highcharts-linked-description"></p> </figure>
|
HighCharts
的Class
定义
Class
都定义在了highcharts.css
相关文件里, https://github1s.com/highcharts/highcharts/blob/master/css/highcharts.css。
使用css
变量定义了一些主题颜色。并在各个class
中使用了这些css
变量。
CLass
的添加
在创建具体图元的时候由负责创建该图元的方法通过链式调用的方式为其添加class
名称。以下是两个简单示例:
1 2 3 4 5 6 7
| if (!chartBackground) { chart.chartBackground = chartBackground = renderer.rect() .addClass('highcharts-background') .add(); verb = 'attr'; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| series.tracker = tracker = renderer.path(trackerPath) .attr({ visibility: series.visible ? 'inherit' : 'hidden', zIndex: 2 }) .addClass( trackByArea ? 'highcharts-tracker-area' : 'highcharts-tracker-line' ) .add(series.group);
if (!chart.styledMode) { tracker.attr({ 'stroke-linecap': 'round', 'stroke-linejoin': 'round', stroke: TRACKER_FILL, fill: trackByArea ? TRACKER_FILL : 'none', 'stroke-width': series.graph.strokeWidth() + (trackByArea ? 0 : 2 * snap) }); }
|
总结
给每个图元都创建Class
,并通过语意化的Class
名称可以达到两个目的。
- 可以更容易的感知和分辨图元所表述具体内容,比如区分是轴线,还是图形。
- 开辟了一条新的方式来来控制图元样式。
这两个特性都在一定程度上提升了图表的灵活性,无论是通过querySelector
来获取图元还是直接对其Class
做覆盖都能在HighCharts
的逻辑之外对图表的样式做出修改。
通过多种不同的体系【Class
体系,Style
体系、 SVG
属性体系】同时去控制图表的样式,在提高灵活性的同时无疑会增加其维护难度。需要更清晰和明确的规范去做出约束和限制。这里笔者并没有找到明确规范仅从具体表现上来推断各体系负责的部分如下:
Class
体系: 负责最基础和通用的样式内容,比如会对字体颜色、线条颜色等根据主题颜色做出描述。在其他体系未对相同属性做出描述时,Class
体系将提供基础的默认样式。
Style
体系:一些具体的样式例如color
、font-size
、fill
、cursor
、pointer-events
等。
SVG
属性体系:元素的布局信息例如z-index
、x
、y
、以及一些filter
等。
笔者在不同的图元上均有发现不符合上述规范的地方。 一方面可能是不同图元上有不同的规范导致的,另一方面也可能是其本身的规范不够清晰导致的。
以上各体系所负责的内容表述不是十分准确,仅能作为大致参考。