Can't show all data on Lightweight Chart when chart is small, is it expected? - lightweight-charts

Not sure if it's a limitation or not but I can't make chart display all data (I have 1500 records). fitContent() or setVisibleRange() doesn't help.
Demo
var chart = LightweightCharts.createChart(document.body, {
width: 600,
height: 300,
rightPriceScale: {
scaleMargins: {
top: 0.1,
bottom: 0.1,
},
},
});
var areaSeries = chart.addAreaSeries({
topColor: 'rgba(76, 175, 80, 0.56)',
bottomColor: 'rgba(76, 175, 80, 0.04)',
lineColor: 'rgba(76, 175, 80, 1)',
lineWidth: 2,
title: 'AAPL',
});
areaSeries.setData([{
"time": 1629353327,
"value": 19.97
}, {
"time": 1629439727,
"value": 19.67
},
....
}]);
chart.timeScale().fitContent();
Is this expected? It'll work if chart width is set to 800px.

By default the min bar spacing value (the min space between bars) is 0.5, which allows you to show 2 values per 1 pixel. But if you want to show more data in a small viewport, you need to change this value to a smaller value, e.g. 0.001.
You can do that by modifying minBarSpacing option of timeScale - just add timeScale: { minBarSpacing: 0.001 } to your chart's options and it will work. Demo

Related

Chart.js how to highlight a part of a label

i am trying to highlight part of a label from the axis labels based on what the user has searched for.
However the label is being rendered as text so the html tags are shown like plain text. any ideas on how to achieve this?
You can use the Plugin Core API. It offers different hooks that may be used for executing custom code. In below code snippet, I use the afterDraw hook to draw text of different styles underneath each bar.
When drawing your own tick labels, probably want to define the text rotation. Further you need to instruct Chart.js not to display the default labels. This can be done through the following definition inside the chart options.
scales: {
xAxes: [{
ticks: {
display: false,
rotation: 40
}
}],
You also need to define some padding for the bottom of the chart, otherwise you won't see your custom tick labels.
layout: {
padding: {
bottom: 60
}
},
Please take a look at below code sample and see how it works. Tick labels that need to be drawn with two different styles are separated with a semicolon inside data.labels.
new Chart(document.getElementById('myChart'), {
type: 'bar',
plugins: [{
afterDraw: chart => {
let ctx = chart.chart.ctx;
let xAxis = chart.scales['x-axis-0'];
let yAxis = chart.scales['y-axis-0'];
chart.data.labels.forEach((l, i) => {
let labelTokens = l.split(';');
let rotation = xAxis.options.ticks.rotation * -Math.PI / 180;
let x = xAxis.getPixelForValue(l);
if (labelTokens.length == 2) {
ctx.save();
let width = ctx.measureText(labelTokens.join(' ')).width;
ctx.translate(x, yAxis.bottom + 10);
ctx.rotate(rotation);
ctx.font = 'italic 12px Arial';
ctx.fillStyle = 'blue';
ctx.fillText(labelTokens[0], -width, 0);
ctx.restore();
}
ctx.save();
let labelEnd = labelTokens[labelTokens.length - 1];
let width = ctx.measureText(labelEnd).width;
ctx.translate(x, yAxis.bottom + 10);
ctx.rotate(rotation);
ctx.font = '12px Arial';
ctx.fillText(labelEnd, -width, 0);
ctx.restore();
});
}
}],
data: {
labels: ['NASTY!!;Errors', 'Warnings'],
datasets: [{
label: 'Result',
data: [30, 59],
fill: false,
backgroundColor: ['rgba(255, 99, 132, 0.2)', 'rgba(255, 159, 64, 0.2)'],
borderColor: ['rgb(255, 99, 132)', 'rgb(255, 159, 64)'],
borderWidth: 1
}]
},
options: {
layout: {
padding: {
bottom: 60
}
},
legend: {
display: false
},
tooltips: {
callbacks: {
title: tooltipItem => tooltipItem[0].xLabel.split(';').join(' ')
}
},
scales: {
xAxes: [{
ticks: {
display: false,
rotation: 40
}
}],
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
canvas {
max-width: 250px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
<canvas id="myChart" width="10" height="8"></canvas>

Individual shape and position of annotations in highcharts

I have figured out how to set the size for an annotation individually:
labels: [
{
point: {
x: chart.xAxis[0].max - 0.1,
y: 50,
xAxis: 0,
yAxis: 0
},
height: 100,
shape: "rect",
text: "test",
verticalAlign: "bottom"
}
]
I would like it to position between 50 and 150. How can I achieve that?
And additionally, I would like the text to be aligned in the center of the box?!
You can calculate the height by using toPixels method. You have to also take a padding into account. To center the text you can use asynchronous function, because annotations do not exist in load event yet.
chart: {
events: {
load: function() {
const chart = this;
const height =
chart.yAxis[0].toPixels(50) - chart.yAxis[0].toPixels(150);
chart.addAnnotation({
labels: [
{
point: {
x: chart.xAxis[0].max - 0.1,
y: 150,
xAxis: 0,
yAxis: 0
},
y: 0,
padding: 0,
height: height,
shape: "rect",
text: "test",
verticalAlign: "top"
}
]
});
}
}
}
Live demo: https://codesandbox.io/s/qqqkx2zr49
API: https://api.highcharts.com/class-reference/Highcharts.Axis#toPixels

How to display AmCharts' funnel chart bars in sorted order?

I'm using AmCharts and angularjs to build a defect priority funnel chart. Everything is working fine, but it's displaying values in out of order like High, Low, No Status, Medium along with my count data.
HTML:
<div id="funnelChart" class="admin-chart" ng-controller="DefectCtrl" ng-init="defectPrioirtyFunnelChart()"></div>
Controller:
$scope.defectPrioirtyFunnelChart= function(data){
$scope.data =data;
$scope.graphData=[];
for( var i=0;i<$scope.data.length;i++){
if($scope.data[i].priority == ""){
$scope.data[i].priority = "No Priority";
}
$scope.graphData.push({priority:$scope.data[i].priority,
count:$scope.data[i].priorityCnt })
}
var layoutColors = baConfig.colors;
var id = $element[0].getAttribute('id');
var chart = AmCharts.makeChart("funnelChart", {
type: 'funnel',
theme: 'blur',
colors: ["#209e91", "#FF6600", "#FFFF4D", "#e85656", "#FF9E01", "#0D8ECF"],
labelTickColor: layoutColors.borderDark,
dataProvider:$scope.graphData ,
titleField: 'priority',
marginRight: 160,
marginLeft: 15,
labelPosition: 'right',
funnelAlpha: 0.9,
valueField: 'count',
startX: 0,
alpha: 0.8,
neckWidth: '0%',
startAlpha: 0,
outlineThickness: 1,
neckHeight: '0%',
balloonText: '[[priority]]:<b>[[count]]</b>',
export: {
enabled: true
},
creditsPosition: 'bottom-left',
pathToImages: layoutPaths
});
chart.dataProvider = $scope.graphData;
chart.validateData();
}
I want to display the bars in my defect priority chart in this order (High, Medium, Low, No Status). How can I do this?
AmCharts displays the data in the order that it is received, with the first data element being at the base of the funnel and the last element being at the tip. You'll need to sort your data manually in the order you want, i.e. first element = High, second = Med, etc.
If you also want the "No Status" slice to show, you need to set showZeroSlices to true.
Here's a simplified version of your code to illustrate this:
var chart = AmCharts.makeChart("funnelChart", {
type: 'funnel',
theme: 'blur',
colors: ["#209e91", "#FF6600", "#FFFF4D", "#e85656", "#FF9E01", "#0D8ECF"],
dataProvider:[{
"count": 60,
"priority": "High"
},{
"count": 50,
"priority": "Med"
},{
"count": 30,
"priority": "Low"
}, {
"count": "",
"priority": "No status"
}],
showZeroSlices: true,
titleField: 'priority',
marginRight: 160,
marginLeft: 15,
labelPosition: 'right',
funnelAlpha: 0.9,
valueField: 'count',
startX: 0,
alpha: 0.8,
neckWidth: '0%',
startAlpha: 0,
outlineThickness: 1,
neckHeight: '0%',
balloonText: '[[priority]]:<b>[[count]]</b>',
export: {
enabled: true
},
creditsPosition: 'bottom-left'
});
<script type="text/javascript" src="//www.amcharts.com/lib/3/amcharts.js"></script>
<script type="text/javascript" src="//www.amcharts.com/lib/3/funnel.js"></script>
<div id="funnelChart" style="width: 100%; height: 300px;"></div>

How can I set max value(range) for y-axis and bar width of a bar chart using nvd3.js

I have generated a bar chart for the data to show ratings of five topics on scale of 5 (Ratings).On x-axis I showed Topic names.
$scope.options = {
chart: {
type: 'discreteBarChart',
height: 450,
margin: {
top: 20,
right: 20,
bottom: 50,
left: 55
},
x: function(d) {
return d.label;
},
y: function(d) {
return d.value;
},
showValues: true,
duration: 500,
xAxis: {
axisLabel: 'X Axis'
},
yAxis: {
axisLabel: 'Y Axis',
axisLabelDistance: -10
}
}
};
$scope.data = [{
values: $scope.Details.ratings
}];
HTML:
<nvd3 options="options" data="data"></nvd3>
On y-axis the max value should be 5, but here it is taking the maximum value among the data and the bars in the bar chart are having large width. How can I change the bar width and max range on y-axis?
i used the following code to set bar width and adjust the bar curvature
enter code here
dispatch: {
renderEnd: function (e) {
d3.selectAll("rect.nv-bar").attr('rx', 4).attr('ry', 4).attr('width', 15)
}
}
putting
groupSpacing : 0.57,
in chart dict will also help to adjust width dynamically

How can I display legend in two columns in pie chart

I want to display legend in two columns in the pie chart. My JSfiddle: http://jsfiddle.net/Cp73s/2185/
itemStyle: {
width:200,
font: 'Helvetica Neue'
},
Try this
legend: {
borderRadius: 0,
borderColor: 'silver',
enabled: true,
margin: 30,
itemMarginTop: 2,
itemMarginBottom: 2,
width:200,
itemWidth:100,
itemStyle: {
width:100
}
}
fiddle link :)
function renderElements() {
if (this.legend) {
this.legend.destroy();
}
//distance between 2 elements
let itemDistance = this.legend.options.itemDistance;
//the biggest element
let maxItemWidth = this.legend.maxItemWidth;
//make the width of the legend in the size of 2 largest elements +
//distance
let nextLegendWidth = (maxItemWidth * 2) + itemDistance;
//container width
let boxWidth = this.plotBox.width;
//if the length of the 2 largest elements + the distance between them
//is less than the width of container, we make 1 row, else
//set legend width 2 max elements + distance between
if (boxWidth < nextLegendWidth) {
this.legend.options.width = maxItemWidth;
} else {
this.legend.options.width = nextLegendWidth;
}
this.render()
}
chart: {
events: {
load: renderElements,
redraw: renderElements
}
}
https://jsfiddle.net/jecrovb7/38/
You need to set a bunch of things in order to make it look as you expecting.
First you need to change the layout parameter to 'horizontal', enable the floating, setting fixed width of legend for example to 300 and finally - position it by x, y parameters. Here is the code and example:
legend: {
align: 'right',
verticalAlign: 'top',
layout: 'horizontal',
floating: true,
useHTML: true,
symbolWidth: 0,
width: 300,
y: 80,
itemMarginTop: 5,
itemMarginBottom: 5,
itemStyle: {
width: 200,
font: 'Helvetica Neue'
},
}
Live example: https://jsfiddle.net/9pnru4s7/

Resources