【问题标题】:Highcharts Multi-Depth 3d pie chartHighcharts 多深度 3d 饼图
【发布时间】:2019-06-30 16:39:48
【问题描述】:

所以我希望创建一个 3d 饼图(在 Highcharts 中),其中每个切片的深度由点的值确定。问题here 应该让您对我的目标有一个很好的了解。

目前 Highcharts 仅支持系列级别的深度参数,所以我的第一个想法是制作多个系列,如下所示:#1

1:

Highcharts.chart('container', {
  chart: {
    type: 'pie',
    options3d: {
      enabled: true,
      alpha: 60
    }
  },
  title: {
    text: 'Contents of Highsoft\'s weekly fruit delivery'
  },
  subtitle: {
    text: '3D donut in Highcharts'
  },
  plotOptions: {
    pie: {
      innerSize: 125,
      depth: 60
    }
  },
  series: [{
    name: 'Delivered amount',
    data: [
      { name: 'a', y: 1, val: 0.59, color: '#25683d' },
      { name: 'b', y: 1, val: 1.25, color: '#222f58' },
      { name: 'c', y: 2, val: 0.73, color: '#bebe89' },
      
    ],
    depth: 45,
    startAngle: 0,
    endAngle: 180
  }, {
    data: [
      { name: 'd', y: 2, val: -0.69, color: '#900' },
      { name: 'e', y: 2, val: 0.57, color: '#a0a0a0' }
    ],
		depth: 60,
    startAngle: 180,
    endAngle: 360
  }]
});
<script src="https://code.highcharts.com/highcharts.js">
</script>
<script src="https://code.highcharts.com/highcharts-3d.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/export-data.js"></script>

<div id="container" style="height: 400px"></div>
  • 问题在于深度似乎保持相同的顶部参考点,而不是每个“切片”从相同 y 点开始的预期结果。

当这不起作用时,我又将所有数据存储在一个系列中,并尝试在渲染后更新 SVG 元素深度(可以在此处看到:#2

2:

Highcharts.chart('container', {
  chart: {
    type: 'pie',
    options3d: {
      enabled: true,
      alpha: 60
    },
    events: {
      load: function() {
        this.series[0].data.forEach((val, i) => {
          var depth = val.graphic.attribs.depth;
          val.graphic.attribs.depth = depth + (i * 10);
        });
        this.redraw();
      }
    }
  },
  title: {
    text: 'Contents of Highsoft\'s weekly fruit delivery'
  },
  subtitle: {
    text: '3D donut in Highcharts'
  },
  plotOptions: {
    pie: {
      innerSize: 125,
      depth: 60
    }
  },
  series: [{
    name: 'Delivered amount',
    data: [{
        name: 'a',
        y: 1,
        val: 0.59,
        color: '#25683d'
      },
      {
        name: 'b',
        y: 1,
        val: 1.25,
        color: '#222f58'
      },
      {
        name: 'c',
        y: 2,
        val: 0.73,
        color: '#bebe89'
      },
      {
        name: 'd',
        y: 2,
        val: -0.69,
        color: '#900'
      },
      {
        name: 'e',
        y: 2,
        val: 0.57,
        color: '#a0a0a0'
      }

    ],

  }]
});

3:

Highcharts.chart('container', {
  chart: {
    type: 'pie',
    options3d: {
      enabled: true,
      alpha: 60
    },
    events: {
      load: function() {
        this.series[0].data.forEach((val, i) => {
          var depth = val.graphic.attribs.depth;
          val.graphic.attribs.depth = depth + (i * 10);
        });
        this.redraw();
      },
      redraw: function() {
        var y_trans = [0, -8, -16, -25, -34];
        this.series[0].data.forEach((val, i) => {
          val.graphic.translate(0, y_trans[i]);
        });
      }
    }
  },
  title: {
    text: 'Contents of Highsoft\'s weekly fruit delivery'
  },
  subtitle: {
    text: '3D donut in Highcharts'
  },
  plotOptions: {
    pie: {
      innerSize: 125,
      depth: 60
    }
  },
  series: [{
    name: 'Delivered amount',
    data: [{
        name: 'a',
        y: 1,
        val: 0.59,
        color: '#25683d'
      },
      {
        name: 'b',
        y: 1,
        val: 1.25,
        color: '#222f58'
      },
      {
        name: 'c',
        y: 2,
        val: 0.73,
        color: '#bebe89'
      },
      {
        name: 'd',
        y: 2,
        val: -0.69,
        color: '#900'
      },
      {
        name: 'e',
        y: 2,
        val: 0.57,
        color: '#a0a0a0'
      }

    ],

  }]
});

任何参考或想法将不胜感激,因为我开始碰壁了。

【问题讨论】:

    标签: javascript svg highcharts


    【解决方案1】:

    您可以使用 Highcharts wrap 和扩展 translate 方法:

    var each = Highcharts.each,
        round = Math.round,
        cos = Math.cos,
        sin = Math.sin,
        deg2rad = Math.deg2rad;
    
    Highcharts.wrap(Highcharts.seriesTypes.pie.prototype, 'translate', function(proceed) {
        proceed.apply(this, [].slice.call(arguments, 1));
    
        // Do not do this if the chart is not 3D
        if (!this.chart.is3d()) {
            return;
        }
    
        var series = this,
            chart = series.chart,
            options = chart.options,
            seriesOptions = series.options,
            depth = seriesOptions.depth || 0,
            options3d = options.chart.options3d,
            alpha = options3d.alpha,
            beta = options3d.beta,
            z = seriesOptions.stacking ? (seriesOptions.stack || 0) * depth : series._i * depth;
    
        z += depth / 2;
    
        if (seriesOptions.grouping !== false) {
            z = 0;
        }
    
        each(series.data, function(point) {
    
            var shapeArgs = point.shapeArgs,
                angle;
    
            point.shapeType = 'arc3d';
    
            var ran = point.options.h;
    
            shapeArgs.z = z;
            shapeArgs.depth = depth * 0.75 + ran;
            shapeArgs.alpha = alpha;
            shapeArgs.beta = beta;
            shapeArgs.center = series.center;
            shapeArgs.ran = ran;
    
            angle = (shapeArgs.end + shapeArgs.start) / 2;
    
            point.slicedTranslation = {
                translateX: round(cos(angle) * seriesOptions.slicedOffset * cos(alpha * deg2rad)),
                translateY: round(sin(angle) * seriesOptions.slicedOffset * cos(alpha * deg2rad))
            };
        });
    });
    
    (function(H) {
        H.wrap(Highcharts.SVGRenderer.prototype, 'arc3dPath', function(proceed) {
            // Run original proceed method
            var ret = proceed.apply(this, [].slice.call(arguments, 1));
            ret.zTop = (ret.zOut + 0.5) / 100;
            return ret;
        });
    }(Highcharts));
    

    另外,在load 事件中,您需要反转图表:

            events: {
                load: function() {
                    var each = Highcharts.each,
                        points = this.series[0].points;
    
                    each(points, function(p, i) {
                        p.graphic.attr({
                            translateY: -p.shapeArgs.ran
                        });
    
                        p.graphic.side1.attr({
                            translateY: -p.shapeArgs.ran
                        });
    
                        p.graphic.side2.attr({
                            translateY: -p.shapeArgs.ran
                        });
                    });
                }
            }
    

    现场演示:http://jsfiddle.net/BlackLabel/c4wk5z9L/

    文档:https://www.highcharts.com/docs/extending-highcharts

    【讨论】:

    • 我注意到的一件小事... deg2rad 应该是 Highcharts.deg2rad 而不是 Math.deg2rad。除此之外,完美!再次感谢
    • 如果你能帮忙的话还有一件事......我正在尝试为负值添加一个功能。我将映射函数(从真值到深度)保持为正,如果真值为负,我只需反转 translateY 参数以将切片“向下”移动。然而,这导致需要将这些负片的中心“移回”到屏幕中,以便边缘对齐。有什么想法吗?
    • 嗨 laventnc,看来设置固定translateY 值就足够了:jsfiddle.net/BlackLabel/073o1wum
    • 如果其他人因此得到帮助,为了动态设置固定 translateY 值,我发现将其设置为最小负切片和最小正切片的高度之间的差异会产生良好的效果
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多