AreaSeries does not seem to work for highPrecision data points - lightningchart

Consider the following example. It does not display an area series plot.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Using chart in HTML page</title>
<meta charset="utf-8" />
<!-- Automatically support high DPI devices -->
<meta name="viewport" content="width=device-width,initial-scale=1" />
<script src="https://unpkg.com/#arction/lcjs#3.4.0/dist/lcjs.iife.js"></script>
<!-- Flexbox styling to have the chart and header fill the page.
Chart will take as much space as possible. -->
<style>
html,
body {
height: 100%;
margin: 0;
}
.box {
display: flex;
flex-flow: column;
height: 100%;
}
.box .row.header {
flex: 0 1 auto;
}
.box .row.content {
flex: 1 1 auto;
}
</style>
</head>
<body class="box">
<h1 class="row header">LightningChart<sup>®</sup> JS in HTML page</h1>
<!-- Create div to render the chart into-->
<div id="target" class="row content"></div>
<!--Actual chart related script tag-->
<script>
// Extract required parts from LightningChartJS.
const {
lightningChart
} = lcjs //Note: #arction/lcjs is not needed here, when using IIFE assembly
// Create a XY Chart.
const chart = lightningChart().ChartXY({
// Set the chart into a div with id, 'target'.
// Chart's size will automatically adjust to div's size.
container: 'target',
defaultAxisX: { type: 'linear-highPrecision' },
})
.setTitle('My first chart') // Set chart title
chart.getDefaultAxisX()
.setTickStrategy( lcjs.AxisTickStrategies.Numeric )
;
const data1 = [
{ x: 10, y: 200 },
{ x: 21, y: 900 },
{ x: 42, y: 300 },
{ x: 73, y: 500 },
{ x: 94, y: 100 }
];
const data2 = [
{ x: 55906939, y: 200 },
{ x: 59906939, y: 900 },
{ x: 75906939, y: 300 },
{ x: 76907939, y: 500 },
{ x: 86907939, y: 100 },
];
const data3 = [
{ x: 1665666055906939, y: 200 },
{ x: 1665666059906939, y: 900 },
{ x: 1665666075906939, y: 300 },
{ x: 1665666155906939, y: 500 },
{ x: 1665666255906939, y: 100 },
];
const data = data3;
// Add a line series.
// const series = chart.addLineSeries(
// { dataPattern: { pattern: 'ProgressiveX', regularProgressiveStep: false } }
// );
// Add a area series
const series = chart.addAreaSeries();
series
.setName('My data')
.add(data)
</script>
</body>
</html>
AreaSeries seem to work fine when axisX type does not have type = linear-highPrecision.
I have a time series data with timestamp in microseconds, so I would like to use high precision mode.
However, it seems to not work well.
First of all for small values (set data = data1 on line 85) , the shaded area does not align with the line plot
Shaded area not correct
If I use microsecond timestamp (set data = data3 on line 85), it just does not even show any shaded area.
Shows no shaded area at all
Small x-values work fine when I remove linear-highPrecision (on line 54).
Good case of low-precision area-series plot
What am I doing wrong for high precision plots? Is it supposed to work?

Related

Using chartjs, how to define relative width and height of canvas?

Using Chart.js version 4.2.0, I try to display a chart on a maximized window on Windows 11 where height of chart is 100% of screen's height and width of chart is 80% of screen's width.
I tried with following code
<body>
<div height="100%" width="80%">
<canvas id="canvas">
But this simple attributes don't do the job.
Finally, I have found this solution
<body>
<div>
<canvas id="canvas">
</canvas>
</div>
, options:
{ responsive: true
, maintainAspectRatio: true
, aspectRatio: 1.65
var ctx = document.getElementById("canvas").getContext("2d");
var myChart = new Chart(ctx, config);
myChart.canvas.parentNode.style.width = '80%';
This works correctly but is a little tricky because width (not height) is set dynamically in Javascript code and aspectRatio must be manually fixed in options.
Is there a simple solution to define width to 80% of screen and height to 100% of screen ?
My current screen size are 1920x1080.
What I obtain is
When I suppress aspectRatio in options, I obtains following chart
It seems that the standard way for a chart.js plot to fill a certain area with a size set in css, is to do these:
include the canvas in a div that doesn't contain anything else
set the size in the style of the div, not the canvas (that is already done in your code)
have at least one size in absolute units, (that is not both in %) - in your case
<div style="height:100vh; width:80vw">
<canvas id="myChart"></canvas>
</div>
See also this comment from the docs.
set chart options maintainAspectRatio: false and responsive: true - the latter for the chart to be redrawn when you resize the window.
Here's a code snippet doing these, including a plugin I wrote that displays the current sizes of the canvas, div and window
const plugin = {
id: 'canvasSizeMonitor',
currentWidth: 0,
currentHeight: 0,
resizing: false,
displaySizes(chart){
const canvas = chart.canvas,
div = canvas.parentElement;
document.querySelector('#sizes').innerText+=
`div: ${div.offsetWidth}x${div.offsetHeight}\n`+
`canvas: ${canvas.offsetWidth}x${canvas.offsetHeight}\n`+
`window:${window.innerWidth}x${window.innerHeight}\n`+
`0.8 * ${window.innerWidth} = ${Math.round(0.8*window.innerWidth)}\n`+
'---------\n'//`aspRatio: ${chart.options.aspectRatio.toFixed(3).replace(/[.]?0*$/, '')}\n\n`;
},
afterRender(chart){
if(!plugin.resizing &&
(chart.canvas.offsetWidth !== plugin.currentWidth ||
chart.canvas.offsetHeight !== plugin.currentHeight)){
plugin.resizing = true;
setTimeout(
function(){
plugin.resizing = false;
plugin.currentWidth = chart.canvas.offsetWidth;
plugin.currentHeight = chart.canvas.offsetHeight;
plugin.displaySizes(chart);
}, 500
)
}
}
};
chart = new Chart(document.getElementById("myChart"), {
type: 'line',
data: {
datasets: Array.from({length: 8}, (_, i)=>({
label: `k = ${i+1}`,
data: Array.from({length: 100}, (_, j)=>({
x: j/50, y: Math.exp(-j/10)*Math.cos((i+1)*j*Math.PI/100)
}))
}))
},
options: {
parsing: {
xAxisKey: 'x',
yAxisKey: 'y'
},
pointStyle: false,
borderWidth: 1,
responsive: true,
maintainAspectRatio: false,
//aspectRatio: 1,
scales: {
x: {
type: 'linear',
grid: {
drawOnChartArea: true,
lineWidth: 1
},
border:{
color: '#000',
},
ticks: {
display: true,
color: '#000',
padding: 10
},
title: {
display: true,
text: 'x',
align: 'end'
}
},
y: {
type: 'linear',
ticks: {
padding: 10,
color: '#000',
},
grid: {
drawOnChartArea: true,
lineWidth: 1
},
border:{
color: '#000',
},
title: {
display: true,
text: 'f[k](x)',
align: 'end'
}
}
},
plugins:{
legend:{
position: 'right'
}
},
animation: {duration: 0}
},
plugins: [plugin]
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.1.2/chart.umd.js"
integrity="sha512-t41WshQCxr9T3SWH3DBZoDnAT9gfVLtQS+NKO60fdAwScoB37rXtdxT/oKe986G0BFnP4mtGzXxuYpHrMoMJLA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<body style="margin: 0">
<pre id="sizes" style="position: absolute; top: 0; right: 10px; text-align: right;background-color:rgba(255, 200, 100,0.4)"></pre>
<div style="height:100vh; width:80vw; padding:0; margin: 0; background: red">
<canvas style="background: #ddd" id="myChart"></canvas>
</div>
</body>

Vis Network + Vuetify Tabs - Networks won't fill screen

I am having some problems getting some Vis JS Networks to fill the available space under the App Bar correctly in a '' element. The graph element will fill the space, but the 100% I height I have had to apply to both '.v-tabs-items' and '.v-window-item' seems to ignore the padding and creates a scroll-bar, I have also set 100% width and there is no horizontal scroll.
It also doesn't adjust properly when resizing the window, requiring a tab switch to readjust to the correct size.
If I remove the 100% Height and Width then the tab content is constrained to a small rectange.
I have simplified the relevant code and it is below, there are two parts, the App.Vue file which contains the main screen and also the GraphView.Vue file which contains the Component that is used to draw the graph.
App.Vue
<template>
<v-app>
<v-app-bar app>
<v-toolbar-title class="headline text-uppercase">
<span>Test</span>
</v-toolbar-title>
<template v-slot:extension>
<v-tabs v-model="graphTab">
<v-tab v-for="(graph, title) in getGraphData()" :key="title">
{{ title }}
<span style="display: none"> {{ graph }}</span>
</v-tab>
</v-tabs>
</template>
</v-app-bar>
<v-content>
<v-container fluid fill-height>
<v-tabs-items v-model="graphTab">
<v-tab-item v-for="(graph, title) in getGraphData()" :key="title">
<GraphView
:nodes="graph.nodes"
:edges="graph.edges"
:options="defaultVisOptions"
></GraphView>
</v-tab-item>
</v-tabs-items>
</v-container>
</v-content>
</v-app>
</template>
<script>
import GraphView from "./components/GraphView";
import { DataSet } from "vis-network";
const defaultVisOptions = {
autoResize: true,
height: "100%",
width: "100%",
edges: {
arrows: "to"
},
nodes: {
shape: "circle"
}
};
export default {
name: "App",
components: {
GraphView
},
data: () => ({
defaultVisOptions: defaultVisOptions,
graphTab: null
}),
methods: {
getGraphData: function() {
return {
"Graph 1": {
nodes: new DataSet([
{ id: 1, label: "Node 1" },
{ id: 2, label: "Node 2" },
{ id: 3, label: "Node 3" },
{ id: 4, label: "Node 4" },
{ id: 5, label: "Node 5" }
]),
edges: new DataSet([
{ from: 1, to: 3 },
{ from: 1, to: 2 },
{ from: 2, to: 4 },
{ from: 2, to: 5 }
])
},
"Graph 2": {
nodes: new DataSet([
{ id: 1, label: "Node 1" },
{ id: 2, label: "Node 2" },
{ id: 3, label: "Node 3" },
{ id: 4, label: "Node 4" },
{ id: 5, label: "Node 5" }
]),
edges: new DataSet([
{ from: 1, to: 2 },
{ from: 2, to: 3 },
{ from: 3, to: 4 },
{ from: 4, to: 5 }
])
}
};
}
}
};
</script>
<style scoped>
.v-tabs-items {
height: 100%;
width: 100%;
}
.v-window-item {
height: 100%;
width: 100%;
}
</style>
GraphView.Vue
<template>
<div class="graphContainer" ref="graphContainer"></div>
</template>
<script>
import { Network } from "vis-network";
export default {
name: "GraphView",
props: ["nodes", "edges", "options"],
mounted() {
this.network = new Network(
this.$refs.graphContainer,
{ nodes: this.$props.nodes, edges: this.$props.edges },
this.$props.options
);
}
};
</script>
<style scoped>
.graphContainer {
width: 100%;
height: 100%;
}
</style>
As explained above, the expected result is that the Graphs fill the available space without creating scroll bars but this doesn't happen.
I didn't test it with your code but the container should be styled like:
<div style="position: relative; width: 100%; height: 100%;">
<div
style="position: absolute; top: 0px; right: 0px; bottom: 0px; left: 0px;"
ref="graphContainer"
/>
</div>
This way it will fill all available space (you may need to set position: relative on the parent) without stretching it any further.

Issue Positioning Radar Chart Using Chart.js

I'm trying to position a radar chart using chart.js. My chart is outputting aligned to the right.
I've tried setting the container to width: 100%, text-align: center and margin: 0 auto but the output is still not correct.
Code:
<div class="chartholder">
<canvas id="myChart" width="400" height="400"></canvas>
</div>
<script>
var ctx = document.getElementById("myChart").getContext('2d');
var marksData = {
labels: ["Digital Product Definition", "Digital Thread", "Digital Twin", "Digital Innovation Platform", "Top Performers", "Others"],
datasets: [{
label: "Your Company",
backgroundColor: "rgba(200,0,0,0.2)",
data: [4.8,7.2,9.6,7.2, 4, 2]
}]
};
var radarChart = new Chart(ctx, {
type: 'radar',
data: marksData
});
var chartOptions = {
scale: {
ticks: {
beginAtZero: true,
min: 0,
max: 10,
stepSize: 1
},
pointLabels: {
fontSize: 18
}
},
legend: {
position: 'left'
},
responsive: true,
};
var radarChart = new Chart(ctx, {
type: 'radar',
data: marksData,
options: chartOptions
});
</script>
CSS
canvas {
margin: 0 auto!important;
width: 100%;
height: auto;
}
.chartholder {
text-align: center;
width: 100%;
margin: 0 auto;
background-color: blue;
}
Screenshot of the output. The yellow is just to show the alignment better.

Highcharts pie wrong legend colors

[![enter image description here][1]][1]
The Slice color and the Legend color of the Pie-Chart do not match when the color is set using className. Doing this for (some) other charts works.
As you can see in the following code snippet, the pie slice and the Legend color for Chrome do not match.
// Build the chart
Highcharts.chart('container-donut', {
chart: {
type: 'pie'
},
plotOptions: {
pie: {
cursor: 'pointer',
showInLegend: true,
}
},
series: [{
name: 'browsers',
data: [
{
name: 'Chrome',
y: 60 ,
className: 'MyCustomColor'
},
{ name: 'Internet Explorer', y: 5 },
{ name: 'Firefox', y: 5 },
{ name: 'Edge', y: 5 },
{ name: 'Safari', y: 5 },
{ name: 'Other', y: 5 }
]
}]
});
.MyCustomColor {
fill: green;
}
<script src="https://code.highcharts.com/modules/export-data.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container-donut" style="min-width: 310px; height: 400px; max-width: 600px; margin: 0 auto"></div>
<div id="container-column" style="min-width: 310px; height: 400px; max-width: 600px; margin: 0 auto"></div>
Your css is not accessing the legend element, which is a <rect> inside of the <g class="MyCustomColor">
Changing your css to this should solve your issue:
.MyCustomColor, .MyCustomColor rect {
fill: green;
}

Can resize Kendo bar chart to fill screen but not pie or gauge

I have the following style applied to my charts when they are clicked, which hides all other Div elements and makes the clicked one look "full screen":
<style>
.hidden {
display: none;
}
.overlay {
position: absolute !important;
top: 0 !important;
left: 0 !important;
bottom: 0 !important;
right: 0 !important;
width: 100% !important;
height: 100% !important;
}
</style>
Using the following:
var fullScreen = 0;
$('#VehicleStatus').click(function () {
if (fullScreen == 0) {
var position = $("#VehicleStatus").position();
var leftCoord = position.left;
var rightCoord = position.right;
var topCoord = position.top;
var bottomCoord = position.bottom;
$(".all").addClass("hidden");
$("#VehicleStatus").removeClass("hidden");
$("#VehicleStatus").addClass("overlay");
fullScreen = 1;
}
else {
$(".all").removeClass("hidden");
$("#VehicleStatus").removeClass("overlay");
$("#VehicleStatus").css("position", "relative");
$("#VehicleStatus").css("top", topCoord);
$("#VehicleStatus").css("bottom", bottomCoord);
$("#VehicleStatus").css("left", leftCoord);
$("#VehicleStatus").css("right", rightCoord);
$("#VehicleStatus").css("width", "500px");
$("#VehicleStatus").css("height", "280px");
fullScreen = 0;
}
})
But when I use the ID of one of my Pie charts or Gauges they dont work. The gauge just goes to the top left of the screen and remains its original size and the pie chart just removes everything from the page.
Does anyone know where I'm going wrong?
You need to call refresh, please see my example:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="KendoPieChart.aspx.cs" Inherits="Demo.KendoPieChart" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="Scripts/jquery.js"></script>
<script src="Scripts/kendo.all.min.js"></script>
<style>
.smallChart{ width: 200px;}
.bigChart{ width: 900px;}
</style>
</head>
<body>
<form id="form1" runat="server">
<div id="chartContainer" class="smallChart">
<div id="chart"></div>
</div>
<div id="resize">Resize</div>
</form>
<script>
$("#chart").kendoChart({
title: {
text: "Break-up of Spain Electricity Production for 2008"
},
legend: {
position: "bottom"
},
seriesDefaults: {
labels: {
visible: true,
format: "{0}%"
}
},
series: [{
type: "pie",
data: [{
category: "Hydro",
value: 22
}, {
category: "Solar",
value: 2
}, {
category: "Nuclear",
value: 49
}, {
category: "Wind",
value: 27
}]
}]
});
$('#resize').click(function() {
$('#chartContainer').toggleClass('smallChart');
$('#chartContainer').toggleClass('bigChart');
//$("#chart").redraw();
var chart = $("#chart").data("kendoChart");
chart.refresh();
});
</script>

Resources