G2 图表示例
源码
g2-react
x
 
1
<!DOCTYPE html>
2
<html>
3
  <head>
4
    <meta charset="utf-8">
5
    <title>层叠柱状图(温度计隐喻)</title>
6
    <script src="https://a.alipayobjects.com/jquery/jquery/1.11.1/jquery.js"></script>
7
    <script src="https://gw.alipayobjects.com/as/g/datavis/g2/2.3.13/index.js"></script>
8
  </head>
9
  <body>
10
    <div id="c1"></div>
11
    <script>
12
      var gapWidth = 3;
13
      var Shape = G2.Shape;
14
      var Util = G2.Util;
15
      function getFillAttrs(cfg) {
16
        var attrs = {
17
          fill: cfg.color,
18
          fillOpacity: cfg.opacity,
19
        };
20
        return attrs;
21
      }
22
      function getRectPath(points) {
23
        var path = [];
24
        for (var i = 0; i < points.length; i++) {
25
          var point = points[i];
26
          if (point) {
27
            var action = i === 0 ? 'M' : 'L';
28
            path.push([action, point.x, point.y]);
29
          }
30
        }
31
        var first = points[0];
32
        path.push(['L', first.x, first.y]);
33
        path.push(['z']);
34
        return path;
35
      }
36
      Shape.registShape('interval', 'top', {
37
        drawShape(cfg, container) {
38
          var points = cfg.points;
39
          var attrs = getFillAttrs(cfg);
40
          var path = getRectPath(cfg.points);
41
          path = this.parsePath(path); // 将 0 - 1 的值转换为画布坐标
42
          var realInterval = container.addShape('path', {
43
            attrs: Util.mix(attrs, {
44
              path,
45
            }),
46
          });
47
          var radius = (path[2][1] - path[1][1]) / 2;
48
          var temp = [];
49
          temp.push(['M', path[1][1], path[1][2]]);
50
          temp.push(['A', radius, radius, 90, 0, 1, (path[2][1] + path[1][1]) / 2, path[2][2] - radius]);
51
          temp.push(['A', radius, radius, 90, 0, 1, path[2][1], path[2][2]]);
52
          temp.push(['L', path[2][1], path[2][2]]);
53
          var topShape = container.addShape('path', {
54
            attrs: {
55
              path: temp,
56
              fill: '#fff',
57
              stroke: '#000',
58
            },
59
          });
60
          return realInterval;
61
        },
62
      });
63
      // 中间带边的矩形
64
      Shape.registShape('interval', 'other', {
65
        drawShape(cfg, container) {
66
          var points = cfg.points;
67
          var attrs = getFillAttrs(cfg);
68
          var path = getRectPath(cfg.points);
69
          path = this.parsePath(path); // 将 0 - 1 的值转换为画布坐标
70
          var intervalPath = [];
71
          intervalPath.push(['M', path[0][1] + gapWidth, path[0][2]]);
72
          intervalPath.push(['L', path[1][1] + gapWidth, path[1][2]]);
73
          intervalPath.push(['L', path[2][1] - gapWidth, path[2][2]]);
74
          intervalPath.push(['L', path[3][1] - gapWidth, path[3][2]]);
75
          intervalPath.push(['Z']);
76
          var intervalShape = container.addShape('path', {
77
            attrs: Util.mix(attrs, {
78
              path: intervalPath,
79
            }),
80
          });
81
          container.addShape('line', {
82
            attrs: {
83
              x1: path[0][1],
84
              y1: path[0][2],
85
              x2: path[1][1],
86
              y2: path[2][2],
87
              stroke: '#000',
88
              lineWidth: 1,
89
            },
90
          });
91
          container.addShape('line', {
92
            attrs: {
93
              x1: path[2][1],
94
              y1: path[2][2],
95
              x2: path[3][1],
96
              y2: path[3][2],
97
              stroke: '#000',
98
              lineWidth: 1,
99
            },
100
          });
101
          return intervalShape;
102
        },
103
      });
104
      // 底边带圆角
105
      Shape.registShape('interval', 'bottom', {
106
        drawShape(cfg, container) {
107
          var points = cfg.points;
108
          var attrs = getFillAttrs(cfg);
109
          var path = getRectPath(cfg.points);
110
          path = this.parsePath(path);
111
          var circleStartY = path[1][2] + (path[0][2] - path[1][2]) / 3;
112
          var h = path[0][2] - circleStartY;
113
          var w = (path[2][1] - path[1][1]) / 2;
114
          var radius = (Math.pow(w, 2) + Math.pow(h, 2)) / (2 * h);
115
          var temp1 = [];
116
          temp1.push(['M', path[1][1], path[1][2]]);
117
          temp1.push(['L', path[1][1], circleStartY]);
118
          temp1.push(['A', radius, radius, 0, 1, 0, path[2][1], circleStartY]);
119
          temp1.push(['L', path[2][1], path[2][2]]);
120
          var temp2 = [];
121
          temp2.push(['M', path[1][1] + gapWidth, path[1][2]]);
122
          temp2.push(['L', path[1][1] + gapWidth, circleStartY + gapWidth]);
123
          temp2.push(['A', radius - gapWidth, radius - gapWidth, 0, 1, 0, path[2][1] - gapWidth, circleStartY + gapWidth]);
124
          temp2.push(['L', path[2][1] - gapWidth, path[2][2]]);
125
          container.addShape('path', {
126
            attrs: Util.mix({
127
              path: temp1,
128
              stroke: '#000',
129
              lineWidth: 1,
130
            }),
131
          });
132
          return container.addShape('path', {
133
            attrs: Util.mix(attrs, {
134
              path: temp2,
135
            }),
136
          });
137
        },
138
      });
139
      var colors = ["#CECA9B","#B1C753","#3CA6DF","#459E96","#2E6936","#52AD3B","#90C320","#F7B632","#F39831","#EA452F"];
140
      var data = [
141
        { name: '个人奢侈品', value: 2490 },
142
        { name: '豪华车', value: 4380 },
143
        { name: '豪华酒店', value: 1830 },
144
        { name: '优质葡萄酒和烈酒', value: 660 },
145
        { name: '优质食品', value: 460 },
146
        { name: '艺术精品', value: 390 },
147
        { name: '设计师家具', value: 330 },
148
        { name: '私人飞机', value: 180 },
149
        { name: '游艇', value: 70 },
150
        { name: '豪华游轮', value: 20 },
151
      ];
152
      var Frame = G2.Frame;
153
      var frame = new Frame(data);
154
      frame.addCol('type', obj => '1');
155
      frame = Frame.sortBy(frame, (obj1, obj2) => obj1.value > obj2.value);
156
      var max = Frame.max(frame, 'value');
157
      var min = Frame.min(frame, 'value');
158
      var chart = new G2.Chart({
159
        id: 'c1',
160
        width: 500,
161
        height: 450,
162
        plotCfg: {
163
          margin: [20, 150, 80, 80]
164
        }
165
      });
166
      chart.source(frame);
167
      chart.axis(false);
168
      chart.legend({
169
        title: null,
170
        mode: false // 不可点击
171
      });
172
      chart.tooltip({
173
        title: null,
174
      });
175
      chart.intervalStack().position('type*value').color('name', colors).size(40)
176
        .shape('name*value', (name, val) => {
177
        var value = val[1] - val[0];
178
        if (value === min) {
179
          return 'top';
180
        } else if (value === max) {
181
          return 'bottom';
182
        }
183
        return 'other';
184
      });
185
      chart.render();
186
    </script>
187
  </body>
188
</html>
189

层叠柱状图(温度计隐喻)