Victory.js get x,y data from hovered line point - victory-charts

How can I get the x,y data of a point on hover in a victory line component?
I tried this:
<VictoryLine
data={data}
style={{ data: { stroke: Colors.green } }}
events={[
{
target: 'parent',
eventHandlers: {
onMouseOver: () => {
return [
{
target: 'data',
mutation: (props) => {
// props.data returns the values of all data points
},
},
]
}
},
},
]}
/>
Is there a possible way to do this in victory.js?

Separating the different components of a victory chart
No
Component
Purpose
1
VictoryChart
It is a wrapper components, it is good to use to share events
2
VictoryVoronoiContainer
It is useful for hover interactions like tooltip
3
VictoryTooltip
It is used for tooltip
4
VictoryAxis
It is used for the axis, tickLabels
5
VictoryLine
It is used for single line path
Dummy Data
const data = [
{
each: "2022-12-19",
total: 1
},
{
each: "2022-12-20",
total: 15
},
{
each: "2022-12-21",
total: 8
},
{
each: "2022-12-22",
total: 21
},
{
each: "2022-12-23",
total: 3
}
];
Code
<VictoryChart
domainPadding={20}
height={300}
containerComponent={
<VictoryVoronoiContainer
voronoiDimension="x"
labels={({ datum }) =>
`x: ${datum.each}, y: ${datum.total}`
}
labelComponent={
<VictoryTooltip
cornerRadius={0}
flyoutStyle={{
fill: "white",
stroke: "blue"
}}
/>
}
/>
}
>
<VictoryLine
width={10}
data={data}
style={{
labels: {
fill: "blue"
},
data: {
stroke: "blue",
strokeWidth: 4
}
}}
labels={({ datum }) => datum.y}
x={"each"}
y={"total"}
height={250}
/>
<VictoryAxis
tickFormat={(x) => x}
style={{
tickLabels: { fill: "transparent" },
axis: { stroke: "transparent" },
ticks: { stroke: "transparent" }
}}
/>
<VictoryAxis
dependentAxis
style={{
tickLabels: { fill: "transparent" },
axis: { stroke: "transparent" },
ticks: { stroke: "transparent" }
}}
/>
</VictoryChart>
Explanation
To get the x,y data on a point, you need a tooltip
Use the VictoryChart and add VictoryVoronoiContainer
VictoryVoronoiContainer
No
Props
What it does
1
label
To show the label data from your data point
2
labelComponent
Use VictoryTooltip to gain more control
VictoryTooltip
No
Props
What it does
1
flyoutStyle
Use stroke to change border color, fill -> background color
VictoryAxis
This is just used to change the color of the axis and the ticks.
Hopefully this was clear.
This method works very well for tooltip situations
events can be used to show tooltip. However this only works victory bars and some others but not victory line.

Related

How to set alignment of individual x-axis labels in Highcharts

I have a chart where basically I want to set the alignment of the first/last labels on the x-axis to be left/right and any labels in between would be the default center. From what I can tell there is only a way to set the Labels.alignment property to apply to all labels and no clear way to individually align them
here is a before and after pic of what I am trying to achieve:
xAxis: {
title: {
enabled: false,
text: ''
},
crosshair: {
width: 2,
color: '#C4C4C4',
dashStyle: 'shortdot'
},
lineColor: 'transparent',
tickLength: 1,
labels: {
//overflow: 'justify',
step: 1,
formatter: function() {
console.log(this.value)
//if(this.value == 0 || this.value == 9)
return Highcharts.dateFormat("%b<br/>%Y", new Date(chartData.Dates[this.value]));
},
//align: 'center',
style: {
fontSize: '14px'
}
},
//tickPositions: [0,3,5,7,9]
},
any help would be appreciated, here is my working fiddle:
fiddle
You can use the render callback to find those labels and use the translate feature to move them.
chart: {
height: 300,
events: {
render() {
const xAxis = this.xAxis[0];
const ticksPositions = xAxis.tickPositions;
const ticks = xAxis.ticks;
const firstTickLabel = ticks[0].label;
const lastTickLabel = ticks[ticksPositions.length - 1].label;
firstTickLabel.translate(firstTickLabel.getBBox().width / 2, 0)
lastTickLabel.translate(-lastTickLabel.getBBox().width / 2, 0)
}
}
},
Demo: https://jsfiddle.net/BlackLabel/krL5ey1o/
API: https://api.highcharts.com/highcharts/chart.events.render
API: https://api.highcharts.com/class-reference/Highcharts.SVGElement#translate

Styling echarts - Cannot modify title color

Looking to work with the below chart, but cannot get to change the title color to white and the axis and axis numbers to grey (or white). This should go above a dark background. Does anybody knows how to change the title color with echarts ?
<script type="text/javascript">
// based on prepared DOM, initialize echarts instance
var myChart = echarts.init(document.getElementById('main'));
// specify chart configuration item and data
var option = {
title: {
text: 'Total memebers of the club',
fontColor: 'white',
display: true,
position: 'bottom'
},
tooltip: {},
legend: {
data: ['Total member']
},
xAxis: {
data: ["11/2018", "12/2018", "01/2019", "02/2019", "03/2019", "04/2019"]
},
yAxis: {},
series: [{
itemStyle: {normal: {color: 'white'}},
name: 'Total',
type: 'bar',
data: [5, 384, 612, 2344, 4670, 9372]
}]
};
// use configuration item and data specified to show chart
myChart.setOption(option);
</script>
Give this a try. Add it under 'text:' like:
text: 'Total memebers of the club',
textStyle: {
color: '#ed2d2e'
}

How to curve every data labels along the individual segments in Sunburst chart?

My requirement in short Phrase:
I am looking for a feature in sunburst chart to curve data labels along the individual segments. (Something similar to this Google result).
Is there a feature already in sunburst chart?
If yes, can you please provide me with an example?
My requirement in long Phrase:
Please have a look at the attachment. It is the highcharts sunburst chart. As you can see in the attachment, though there is a lot of space in every segment, still data label is chopped off and added "..." ellipsis to the end of data label.
Is there a way to use the left out space in the segment to show the data label as much as possible?
Is there a feature already in sunburst chart to curve the text along the segment? (Something similar to this Google result) Or yet to be developed?
If there is a feature already, can you please provide me with an example?
Thanks in advance!
Already referred suggestions:
Highcharts: Is it possible to show Sunburst chart series data labels outside the leaf level nodes with connectors?
Unfortunately, we still not implemented such a feature, because it doesn't get enough votes on our UserVoice platform, but all is not lost.
Here is the example which could be helpful for you to do it by yourself: http://jsfiddle.net/Lcnon9ss/ . That example is based on pie series type, but it should be quick to fit it to your requirements.
Additionally, you can vote on this feature on the UserVoice platform mentioned above, here is the link: https://highcharts.uservoice.com/forums/55896-highcharts-javascript-api/suggestions/34591699-ability-to-write-the-labels-of-the-sunburst-chart
Kind regards!
I had the same issue and I resolved it by adding a textPath for the datalabels as following:
...series:[ ...
dataLabels: {
textPath: {
enabled: true,
attiributes: {
startOffset: '10%',
textAnchor: 'start',
}
}
}
and you cann adjust the params 'startOffset' and 'textAnchor' as required.
https://codesandbox.io/s/antd-sunburst-customization-7q4wq
you can customize by hitting this link
import { Sunburst } from "#ant-design/charts";
const CustomSunburst = (props) => {
const [data, setData] = useState([]);
function getCustomArray(value) {
if (value > 0) {
let arra = [];
arra.push({ value: value, name: "USER" });
return arra;
} else {
return [];
}
}
useEffect(() => {
var dataa = {
children: [
{
type: "ABC",
name: `ABC`,
value: 4,
children: getCustomArray(2)
},
{
type: "XYZ",
name: `XYZ`,
value: 2,
children: getCustomArray(3)
},
{
type: "MNO",
name: `MNO`,
value: 4,
children: getCustomArray(5)
}
]
};
setData(dataa);
}, []);
var config = {
data: data,
color: ["#00A5A0", "#057DAF", "#05AF79"],
innerRadius: 0.35,
interactions: [{ type: "element-active" }],
sunburstStyle: (datum) => {
if (datum.path === "ABC / USER") {
return {
fill: "#74ECE9",
fillOpacity: 0.9
};
}
if (datum.path === "XYZ / USER") {
return {
fill: "#74C9EC",
fillOpacity: 0.9
};
}
if (datum.path === "MNO / USER") {
return {
fill: "#70F7CC",
fillOpacity: 0.9
};
}
},
tooltip: {
customContent: (title, data) => {
if (data[0]?.name === "ABC / USER") {
return (
<div style={{ padding: 10, fontWeight: "600" }}>
AMC Users Count : {data[0]?.value}
</div>
);
}
if (data[0]?.name === "XYZ / USER") {
return (
<div style={{ padding: 10, fontWeight: "600" }}>
XYZ Users Count : {data[0]?.value}
</div>
);
}
if (data[0]?.name === "MNO / USER") {
return (
<div style={{ padding: 10, fontWeight: "600" }}>
MNO Users Count : {data[0]?.value}
</div>
);
}
if (data[0]?.name === "ABC") {
return (
<div style={{ padding: 10, fontWeight: "600" }}>
AMC Site Count : {data[0]?.data?.data?.value}
</div>
);
}
if (data[0]?.name === "XYZ") {
return (
<div style={{ padding: 10, fontWeight: "600" }}>
XYZ Site Count : {data[0]?.data?.data?.value}
</div>
);
}
if (data[0]?.name === "MNO") {
return (
<div style={{ padding: 10, fontWeight: "600" }}>
MNO Site Count : {data[0]?.data?.data?.value}
</div>
);
} else {
return "NO DATA";
}
}
}
};
return (
<>
<Sunburst {...config} height={300}></Sunburst>
<div
style={{
position: "absolute",
top: "44%",
left: "47%",
fontWeight: "600"
}}
>
Lorem /
</div>
<div
style={{
position: "absolute",
top: "49%",
left: "47%",
fontWeight: "600"
}}
>
Ipsum
</div>
</>
);
};
export default CustomSunburst;

Negative bar chart of highcharts in chartjs

I been playing with Chartjs to generate something like highcharts but couldn't bring it close. The application is finished and it seems a waste to buy highcharts, migrate from chartjs for this single chart.
Is there a way Chartjs can output something like that? I did try creating two horizontal bar charts side-by-side in separate canvas; while i saw the output; the behavior is not what I want.
You could use a horizontal stacked barchart with two datasets. Add negative values to the dataset on the left (male) but display the absolute value in the callbacks of the xAxis and the tooltip.
var ctx = document.getElementById('myChart').getContext('2d');
var data = {
labels: ["20-30", "10-20", "0-10"],
datasets: [{
label: "Male",
backgroundColor: "rgba(54, 162, 235, 0.2)",
borderColor: "rgb(54, 162, 235)",
borderWidth: 2,
data: [-65, -59, -20],
}, {
label: "Female",
backgroundColor: "rgba(255,99,132,0.2)",
borderColor: "rgba(255,99,132,1)",
borderWidth: 2,
data: [72, 45, 18],
},
]
};
var myBarChart = new Chart(ctx, {
type: 'horizontalBar',
data: data,
options: {
scales: {
yAxes: [{
stacked: true
}],
xAxes: [{
ticks: {
callback: function(value, index, values) {
return Math.abs(value);
}
}
}]
},
tooltips: {
callbacks: {
label: function(tooltipItems, data) {
return data.datasets[tooltipItems.datasetIndex].label + ": " + Math.abs(tooltipItems.xLabel);
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.min.js"></script>
<canvas id="myChart"></canvas>

Auto chart height

The default highstock chart has height = 400px.
How can height chart be set for auto size based on chart axis and its sizes ?
See the example bellow, the navigation bar is over the volume panel.
http://jsfiddle.net/BYNsJ/
I know that I can set the height for the div but I have a solution that insert/remove axis/series dynamically in the chart and would be nice an auto height chart.
The example is the same Candlestick/Volume demo from Highchart site, but without height property in the div container.
// split the data set into ohlc and volume
var ohlc = [],
volume = [],
dataLength = data.length;
for (i = 0; i < dataLength; i++) {
ohlc.push([
data[i][0], // the date
data[i][1], // open
data[i][2], // high
data[i][3], // low
data[i][4] // close
]);
volume.push([
data[i][0], // the date
data[i][5] // the volume
])
}
// set the allowed units for data grouping
var groupingUnits = [[
'week', // unit name
[1] // allowed multiples
], [
'month',
[1, 2, 3, 4, 6]
]];
// create the chart
$('#container').highcharts('StockChart', {
rangeSelector: {
selected: 1
},
title: {
text: 'AAPL Historical'
},
yAxis: [{
title: {
text: 'OHLC'
},
height: 200,
lineWidth: 2
}, {
title: {
text: 'Volume'
},
top: 300,
height: 100,
offset: 0,
lineWidth: 2
}],
series: [{
type: 'candlestick',
name: 'AAPL',
data: ohlc,
dataGrouping: {
units: groupingUnits
}
}, {
type: 'column',
name: 'Volume',
data: volume,
yAxis: 1,
dataGrouping: {
units: groupingUnits
}
}]
});
});
});
Regards.
here is one example which is resize chart according screen.
http://jsfiddle.net/davide_vallicella/LuxFd/2/
Just don't set the height property in HighCharts and it will handle it dynamically for you so long as you set a height on the chart's containing element. It can be a fixed number or a even a percent if position is absolute.
http://api.highcharts.com/highcharts/chart.height
By default the height is calculated from the offset height of the containing element
find example here:- http://jsfiddle.net/wkkAd/149/
#container {
width:100%;
height:100%;
position:absolute;
}
hey I was using angular 2+ and highchart/highstock v.5, I think it will work in JS or jQuery also, here is a easy solution
HTML
<div id="container">
<chart type="StockChart" [options]="stockValueOptions"></chart>
</div>
CSS
#container{
height: 90%;
}
TS
this.stockValueOptions = {
chart: {
renderTo: 'container'
},
yAxis: [{
height: '60%'
},{
top: '65%',
height: '35%'
}]
}
Its working, and a easy one. Remove chart height add height in '%' for the yAxis.
Highcharts does not support dynamic height, you can achieve it by $(window).resize event:
$(window).resize(function()
{
chart.setSize(
$(document).width(),
$(document).height()/2,
false
);
});
See demo fiddle here.
You can set chart.height dynamically with chart.update method.
http://api.highcharts.com/highcharts/Chart.update
function resizeChartFromValues (chart) {
const pixelsForValue = 10
const axis = chart.yAxis[0]
chart.update({ chart: { height: (axis.max - axis.min) * pixelsForValue } })
}
const options = {
chart: {
events: {
load () {resizeChartFromValues(this)}
}
},
series: [{
data: [30, 70, 100],
}]
}
const chart = Highcharts.chart('container', options)
setTimeout(() => {
chart.series[0].setData([10, 20, 30])
resizeChartFromValues(chart)
}, 1000)
Live example: https://jsfiddle.net/a97fgsmc/
I had the same problem and I fixed it with:
<div id="container" style="width: 100%; height: 100%; position:absolute"></div>
No special options to the chart. The chart fits perfect to the browser even if I resize it.

Resources