问题
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