How to put shadow inside of bar chart in highcharts?

会有一股神秘感。 提交于 2019-12-24 06:48:19

问题


How to put shadow inside of bar chart like box-shadow inset(css) in hightcharts as image below.
Thank you. Have a good day~

enter image description here


回答1:


You can use two overlap series, one with default shadow property and translate both of them by a few pixels in load event:

Highcharts.chart('container', {
    chart: {
        ...,
        events: {
            load: function() {
                this.series[0].points[0].graphic.attr({
                    translateX: -2
                });

                this.series[1].points[0].graphic.attr({
                    translateX: -2
                });
            }
        }
    },
    ...,
    series: [{
        ...,
        data: [100],
        shadow: {
            color: 'gray',
            opacity: 0.8,
            width: 2
        }
    }, {
        data: [50]
    }]
});

Live demo: http://jsfiddle.net/BlackLabel/b7hp0r6s/

API Reference: https://api.highcharts.com/highcharts/series.bar.shadow




回答2:


Unfortunately, Highcharts doesn't have an inset shadow implemented in the core. However, it can be done by adding custom logic to Highcharts.SVGElement.prototype.shadow method. Check the code and demo posted below and let me know if something is unclear for you.

Additionally, to add a partial fill to columns with the inner shadow you have to make a custom column elements and insert them to the DOM between shadows and particular points.

Code:

function insertAfter(newNode, referenceNode) {
  referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}

(function(H) {
  H.SVGElement.prototype.shadow = function(shadowOptions, group, cutOff) {
    var shadows = [],
      i, shadow, element = this.element,
      strokeWidth, shadowWidth, shadowElementOpacity,
      // compensate for inverted plot area
      transform,
      elemBBox = element.getBBox(),
      translateX,
      translateY;

    if (!shadowOptions) {
      this.destroyShadows();
    } else if (!this.shadows) {
      shadowWidth = H.pick(shadowOptions.width, 3);
      shadowElementOpacity = (shadowOptions.opacity || 0.15) /
        shadowWidth;
      transform = this.parentInverted ?
        '(' + H.pick(shadowOptions.offsetY, 1) * -1 + ', ' +
        H.pick(shadowOptions.offsetX, 1) * -1 + ')' :
        '(' + H.pick(shadowOptions.offsetX, 1) + ', ' +
        H.pick(shadowOptions.offsetY, 1) + ')';

      if (!shadowOptions.inside) {
        for (i = 1; i <= shadowWidth; i++) {
          shadow = element.cloneNode(0);
          strokeWidth = (shadowWidth * 2) + 1 - (2 * i);
          H.attr(shadow, {
            stroke: (shadowOptions.color ||
              '#000000'),
            'stroke-opacity': shadowElementOpacity * i,
            'stroke-width': strokeWidth,
            transform: 'translate' + transform,
            fill: 'none'
          });
          shadow.setAttribute('class', (shadow.getAttribute('class') || '') + ' highcharts-shadow');
          if (cutOff) {
            H.attr(shadow, 'height', Math.max(H.attr(shadow, 'height') - strokeWidth, 0));
            shadow.cutHeight = strokeWidth;
          }
          if (group) {
            group.element.appendChild(shadow);
          } else if (element.parentNode) {
            element.parentNode.insertBefore(shadow, element);
          }
          shadows.push(shadow);
        }
      } else {

        for (i = shadowWidth; i >= 1; i--) {
          shadow = element.cloneNode(0);
          translateX = i / 2 - shadowOptions.offsetY;
          translateY = i / 2 - shadowOptions.offsetX;

          H.attr(shadow, {
            stroke: (shadowOptions.color ||
              '#000000'),
            'stroke-opacity': shadowElementOpacity * (shadowWidth - i + 1),
            'stroke-width': i,
            transform: 'translate(' + translateX + ',' + translateY + ')',
            fill: 'none'
          });

          H.css(shadow, {
            width: elemBBox.width - i,
            height: elemBBox.height - i,
          });

          shadow.setAttribute('class', (shadow.getAttribute('class') || '') + ' highcharts-shadow');
          if (cutOff) {
            H.attr(shadow, 'height', Math.max(H.attr(shadow, 'height') - strokeWidth, 0));
            shadow.cutHeight = strokeWidth;
          }

          if (group) {
            group.element.appendChild(shadow);
          } else if (element.parentNode) {
            insertAfter(shadow, element);
          }
          shadows.push(shadow);
        }
      }

      this.shadows = shadows;
    }
    return this;
  };
})(Highcharts)

Highcharts.chart('container', {
  chart: {
    type: 'column',
    inverted: true,
    events: {
      render: function() {
        var chart = this,
          yAxis = chart.yAxis[0],
          partialFillWidth,
          elem,
          bBox;

        if (chart.customElements && chart.customElements.length) {
          chart.customElements.forEach(custElem => {
            custElem.parentNode.removeChild(custElem);
          })

          chart.customElements.length = 0;
        } else {
          chart.customElements = [];
        }

        chart.series[0].points.forEach(point => {
          bBox = point.graphic.getBBox();
          elem = point.graphic.element.cloneNode(0);
          partialFillWidth = yAxis.toPixels(point.partialFill);

          Highcharts.attr(elem, {
            fill: point.partialFillColor,
            transform: 'translate(0, ' + (bBox.height - (point.partialFill / point.y) * bBox.height) + ')'
          });

          Highcharts.css(elem, {
            height: (point.partialFill / point.y) * bBox.height
          });

          insertAfter(elem, point.graphic.element);
          chart.customElements.push(elem);
        });
      }
    }
  },
  title: {
    text: 'Efficiency Optimization by Branch'
  },
  xAxis: {
    categories: [
      'Seattle HQ',
      'San Francisco',
      'Tokyo'
    ]
  },
  yAxis: [{
    min: 0,
    title: {
      text: 'Employees'
    }
  }, {
    title: {
      text: 'Profit (millions)'
    },
    opposite: true
  }],
  legend: {
    shadow: false
  },
  tooltip: {
    shared: true
  },
  plotOptions: {
    column: {
      grouping: false,
      shadow: false,
      borderWidth: 0,
      pointPadding: 0,
      groupPadding: 0
    }
  },
  series: [{
    color: '#efefef',
    id: 'main',
    data: [{
      y: 120,
      partialFill: 100,
      partialFillColor: '#bbb'
    }, {
      y: 50,
      partialFill: 10,
      partialFillColor: '#bbb'
    }, {
      y: 70,
      partialFill: 20,
      partialFillColor: '#bbb'
    }],
    pointPadding: 0.4,
    shadow: {
      color: 'rgba(0, 0, 0, 0.5)',
      opacity: 0.3,
      width: 5,
      offsetX: 0,
      offsetY: 0,
      inside: true
    }
  }]
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container"></div>

Demo:

  • https://jsfiddle.net/BlackLabel/kvrjd48w/

API reference:

  • https://api.highcharts.com/highcharts/chart.events.render

  • https://api.highcharts.com/class-reference/Highcharts.SVGElement

  • https://api.highcharts.com/class-reference/Highcharts#.attr



来源:https://stackoverflow.com/questions/56716094/how-to-put-shadow-inside-of-bar-chart-in-highcharts

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!