This question is two-fold (two ways to solve)
I want to make a chart that plots 24 hours worth of data, not starting at midnight, and with ticks (and associated grid) at the four cardinal points of the day.
I don't care if the x axis is 'time' or anything else, as long as it looks fine. I've seen a category chart with the labels arbitrarily shifted, but I can only reproduce this with one data point per label, and this needs multiple data points between the labels. If I label all the data points I don't know how to skip labels such that only "0:00', '6:00', '12:00', and '18:00' are visible.
It's supposed to look like this:
This is how far I've come:
function generateData() {
function randomNumber(min, max) {
return Math.random() * (max - min) + min;
}
function randomPoint(date) {
return {
t: date.valueOf(),
y: randomNumber(0, 100)
};
}
var date = moment("2000-01-01T"+"08:30");
var now = moment();
var data = [];
while (data.length <=48) {
data.push(randomPoint(date));
date = date.clone().add(30, 'minute')
}
return data;
}
var cfg = {
data: {
datasets: [{
label: 'CHRT - Chart.js Corporation',
backgroundColor: 'red',
borderColor: 'red',
data: generateData(),
type: 'line',
pointRadius: 0,
fill: false,
lineTension: 0,
borderWidth: 2
}]
},
options: {
scales: {
xAxes: [{
type: 'time',
time: {
round: 'minute',
unit: 'minute',
stepSize: 360,
displayFormats: {
minute: 'kk:mm'
}
}
}],
yAxes: [{
gridLines: {
drawBorder: false
}
}]
},
tooltips: {
intersect: false,
mode: 'index'
}
}
};
var chart = new Chart('chart1', cfg);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="chart1" height="60"></canvas>
The problem here is that the first tick is at 08:30 not at 12:00.
I've tried to set the min value of the axis, but this either shifts part of the data out of view (min: moment("2000-01-01T12:00")), or creates a gap before the data starts (min: moment("2000-01-01T06:00")), both of which are unacceptable.
function generateData() {
function randomNumber(min, max) {
return Math.random() * (max - min) + min;
}
function randomPoint(date) {
return {
t: date.valueOf(),
y: randomNumber(0, 100)
};
}
var date = moment("2000-01-01T"+"08:30");
var now = moment();
var data = [];
while (data.length <=48) {
data.push(randomPoint(date));
date = date.clone().add(30, 'minute')
}
return data;
}
var cfg = {
data: {
datasets: [{
label: 'CHRT - Chart.js Corporation',
backgroundColor: 'red',
borderColor: 'red',
data: generateData(),
type: 'line',
pointRadius: 0,
fill: false,
lineTension: 0,
borderWidth: 2
}]
},
options: {
scales: {
xAxes: [{
type: 'time',
time: {
round: 'minute',
unit: 'minute',
stepSize: 360,
displayFormats: {
minute: 'kk:mm'
}
},
ticks: {
min: moment("2000-01-01T06:00"),
}
}],
yAxes: [{
gridLines: {
drawBorder: false
}
}]
},
tooltips: {
intersect: false,
mode: 'index'
}
}
};
var chart = new Chart('chart1', cfg);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="chart1" height="60"></canvas>
Took me some time, but I think I got the answer.
You can define the ticks with and display them with options.scales.xAxes[0].ticks.source = 'labels', but the hardest part was to get the next timestamp of 0:00, 6:00, 12:00 or 18:00.
That's why the code for the first label is quite complex. If you want to know anything, just let me know and I can explain it.
Should work with any time you want.
Complete code (same as JSBin with preview here):
let data = {
datasets: [{
label: 'CHRT - Chart.js Corporation',
backgroundColor: 'red',
borderColor: 'red',
type: 'line',
pointRadius: 0,
pointHoverRadius: 0,
fill: false,
lineTension: 0,
borderWidth: 2,
data: []
}]
}
function randomNumber(min, max) {
return Math.round(Math.random() * (max - min) + min)
}
// temp variable for data.datasets[0].data
let datasetData = []
// Fill first dataset
datasetData[0] = {
x: moment("2000-01-01T08:30"),
y: randomNumber(0, 100)
}
// Fill remaining datasets
for (let i = 1; i < 48; i++) {
datasetData[i] = {
x: moment(datasetData[i-1].x).add(30, 'minutes'),
y: randomNumber(0, 100)
}
}
data.datasets[0].data = datasetData
// Fill first label
data.labels = [
moment(datasetData[0].x).hour(moment(datasetData[0].x).hour() + (6 - moment(datasetData[0].x).hour() % 6) % 6).minutes(0)
]
// Fill remaining labels
for (let i = 1; i < 4; i++) {
data.labels.push(moment(data.labels[i-1]).add(6, 'hours'))
}
let options = {
responsive: true,
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'hour',
displayFormats: {
hour: 'kk:mm'
}
},
ticks: {
source: 'labels'
}
}],
yAxes: [{
gridLines: {
drawBorder: false
}
}]
},
tooltips: {
intersect: false,
mode: 'index',
callbacks: {
title: function(tooltipItem, data) {
return moment(tooltipItem[0].label).format('YYYY-MM-DD, HH:mm')
}
}
}
}
let chart = new Chart('chart1', {
type: 'line',
data: data,
options: options
});
Related
I am trying to make a chart to show data for the last 7 days.
My x axis - is a time cartesian axis and time unit is set to 'day' but the chart shows me only 6 ticks and I want to show 7 ticks, one tick for every day.
Also the ticks are offset to the chart points, I want the points be exactly align with the ticks
let [priceData, scoreData] = generateFakeData(7);
// max price to show on the chart is max price + 1000
const maxPrice = Math.max(...priceData.map(data => data.y)) + 1000;
//console.log(data);
console.log(priceData[0].x);
console.log(priceData[scoreData.length - 1].x);
function generateRandomNumber(min, max) {
return Math.floor(Math.random() * max) + min;
}
const ctx = document.getElementById('chart').getContext('2d');
const myChart = new Chart(ctx, {
type: 'line',
pointRadius: 0,
options: {
elements: {
point: {
pointRadius: 0,
pointHoverRadius: 3
}
},
interaction: {
mode: 'nearest',
intersect: false,
axis: 'x'
},
plugins: {
legend: {
labels: {
// This more specific font property overrides the global property
color: '#fff',
font: {
size: 14,
}
}
}
},
scales: {
x: {
type: 'time',
beginAtZero: true,
ticks: {
color: "white",
autoSkip: false,
maxTicksLimit: 7,
count: 7,
},
time: {
displayFormats: {
month: 'dd MMM yy'
},
unit: 'day'
},
gridLines: {
offsetGridLines: true,
},
offset: false,
},
y: {
type: 'linear',
min: 0,
max: maxPrice,
ticks: {
color: "white"
}
},
y1: {
type: 'linear',
min: 0.5,
max: 10.5,
display: true,
position: 'right',
ticks: {
color: "white",
autoSkip: false,
maxTicksLimit: 12,
callback: function (val, index) {
// Hide first and last tick label
return val === 0.5 || val === 10.5 ? '' : this.getLabelForValue(val);
},
},
// grid line settings
grid: {
drawOnChartArea: false, // only want the grid lines for one axis to show up
},
},
}
},
data: {
datasets: [
{
label: 'price',
data: priceData,
borderColor: [
'#ffb800'
],
borderWidth: 1
},
{
label: 'score',
data: scoreData,
borderColor: [
'#00ff00'
],
borderWidth: 1,
yAxisID: 'y1',
}
]
}
});
function generateFakeData(numOfDays) {
const priceData = [];
const scoreData = [];
let today = new Date();
priceData.unshift({ x: new Date(today), y: generateRandomNumber(1000, 2500) });
scoreData.unshift({ x: new Date(today), y: generateRandomNumber(1, 10) });
for (let i = 0; i < numOfDays - 1; i++) {
const newDate = today.setDate(today.getDate() - 1);
priceData.unshift({ x: new Date(newDate), y: generateRandomNumber(1000, 2500) });
scoreData.unshift({ x: new Date(newDate), y: generateRandomNumber(1, 10) });
}
return [priceData, scoreData];
}
html {
background-color: black
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.7.1/dist/chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns/dist/chartjs-adapter-date-fns.bundle.min.js"></script>
</head>
<body>
<canvas id="chart"></canvas>
</body>
</html>
Link to jsBin: https://jsbin.com/viduman/5/edit?html,js,output
I only needed to set the hour of each day to (0,0,0,0)
let today = new Date();
today.setHours(0, 0, 0, 0);
Good Day,
I have a bar chart with multiple datasets for the chart. I would like to hide all the bars except for one (a Totals if you will), and on the Tooltip, I want to show all of the data in all the datasets. Unfortunately, the tooltip only shows the visible datasets. Does anyone know how to show all the data sets?
If you run this with
<canvas id="myChart" width="400" height="400"></canvas>
Hover over the chart and the first dataset (labeled 'First Label') is not shown. How do I show that in the tooltip? Does anyone know?
var ds1 = [], ds2 = [], ds3 = [], ds4 = [], ds5 = [], ds6 = [], labels = [];
for(var i = 0; i < 2; i++){
labels.push('Label: ' + i);
ds1.push(i);
ds2.push(i+1);
ds3.push(i+2);
ds4.push(i+3);
ds5.push(i+4);
ds6.push(i+5);
}
const dataSets = {
labels: labels,
datasets: [
{
label: 'First Label',
hidden: true,
data: ds1
},{
label: 'Second Label',
data: ds2
},{
label: 'Third Label',
data: ds3
},{
label: 'Fourth Label',
data: ds4
},{
label: 'Fifth Label',
data: ds5
},{
label: 'Totals',
data: ds6
}
]
}
var myChart = new Chart(ctx, {
type: 'horizontalBar',
data: dataSets,
elements: {
rectangle: {
borderWidth: 2
}
},
responsive: true,
legend: {
display: false
},
title: {
display: false
},
scales: {
yAxes: [
{
barThickness: 15
}
],
xAxes: [
{
ticks: {
suggestedMin: 0,
suggestedMax: 50
},
minBarLength: 5
}]
}
});
Thanks,
Tim
If you hide all bars except one, you can define a tooltips.callback function for label. This function collects the labels and appropriate values from all datasets using Array.map() and returns a string array.
tooltips: {
callbacks: {
label: (tooltipItem, chart) => dataSets.datasets.map(ds => ds.label + ': ' + ds.data[tooltipItem.index])
}
},
Please have a look at your amended code below:
var ds1 = [], ds2 = [], ds3 = [], ds4 = [], ds5 = [], ds6 = [], labels = [];
for (var i = 0; i < 2; i++) {
labels.push('Label: ' + i);
ds1.push(i);
ds2.push(i + 1);
ds3.push(i + 2);
ds4.push(i + 3);
ds5.push(i + 4);
ds6.push(5 * i + 10);
};
const dataSets = {
labels: labels,
datasets: [{
label: 'First Label',
hidden: true,
data: ds1
}, {
label: 'Second Label',
hidden: true,
data: ds2
}, {
label: 'Third Label',
hidden: true,
data: ds3
}, {
label: 'Fourth Label',
hidden: true,
data: ds4
}, {
label: 'Fifth Label',
hidden: true,
data: ds5
}, {
label: 'Totals',
data: ds6
}]
};
var myChart = new Chart('myChart', {
type: 'horizontalBar',
responsive: true,
data: dataSets,
elements: {
rectangle: {
borderWidth: 2
}
},
options: {
legend: {
display: false
},
title: {
display: false
},
tooltips: {
callbacks: {
label: (tooltipItem, chart) => dataSets.datasets.map(ds => ds.label + ': ' + ds.data[tooltipItem.index])
}
},
scales: {
xAxes: [{
ticks: {
min: 0,
stepSize: 1
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="myChart" height="100"></canvas>
If you wanted to display the legend and allow users to show additional bars through a mouse click on individual legend labels, the callback function would be invoked once for each visible bar. Therefore you would have to make sure to return the labels array only once and return null in all other cases. The following code would return the labels array only for the 'Totals' bar.
tooltips: {
callbacks: {
label: (tooltipItem, chart) => {
if (tooltipItem.datasetIndex == dataSets.datasets.length - 1) {
return dataSets.datasets.map(ds => ds.label + ': ' + ds.data[tooltipItem.index]);
}
return null;
}
}
},
This would not work however, if the user decides to hide the 'Totals' bar. The code could however be improved to also overcome this limitation.
I'm trying to refactor an old Flex app using Chart.js and I would like to replicate this linear/log axis. Notice the clean minimal spacing on the yAxis.
Here is my Chart.js code.
var mtbsoData = [];
var mtbsoLables = [];
for (let i = 0; i <= 10; i++) {
mtbsoData.push(i * i * i * i);
mtbsoLables.push(i.toString());
}
var ctxMtbso = document.getElementById("chartMtbso").getContext('2d');
var chartMtbso = new Chart(ctxMtbso, {
type: 'bar',
data: {
labels: mtbsoLables,
datasets: [{
label: 'label',
data: mtbsoData,
backgroundColor: 'rgba(0, 0, 255, .6)',
borderColor: 'rgba(0, 0, 255, 1)',
borderWidth: 1
}]
},
options: {
title: {
text: 'Title',
display: true,
fontSize: 24
},
scales: {
xAxes: [{
display: true,
ticks: {
beginAtZero: true
},
scaleLabel: {
display: true,
labelString: 'X Axis'
}
}],
yAxes: [{
type: 'logarithmic',
ticks: {
min: 0,
max: 1000,
callback: function (value, index, values) {
return value + ' years';
}
},
scaleLabel: {
display: true,
labelString: 'Y Axis'
}
}]
},
tooltips: {
callbacks: {
label: function (tooltipItem, data) {
var label = data.datasets[tooltipItem.datasetIndex].label || '';
if (label) {
label += ': ';
}
label += tooltipItem.yLabel.toFixed(2);
return label;
}
}
},
legend: {
display: false
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script>
<canvas id="chartMtbso"></canvas>
Here's a screenshot. Notice the crowded ticks on the yAxis.
It seems from the documentation that the only ticks properties that you can apply are the "min" and "max" properties.
Can anybody suggest a solution?
I fixed it.
Modify the yAxes callback as shown:
yAxes: [{
type: 'logarithmic',
ticks: {
autoSkip: true,
min: 0,
callback: function (value, index, values) {
if( value==10 || value==100 || value==1000 || value==10000 || value==100000 || value==1000000){
return value + ' years';
}
}
},
scaleLabel: {
display: true,
labelString: 'Mean Time Between Stock-Out'
}
}]
Then you only return a tick if the value is a power of ten.
I need to draw a chart with 2 lines using Chart.js.
Each of this line has a different label set.
i.e.
Chart 1:
1 -> 2
2 -> 4
3 -> 8
4 -> 16
Chart 2:
1 -> 3
3 -> 4
4 -> 6
6 -> 9
This following sample obviously does not work as it uses the labels from chart1. But is it possible to realize this with Chart.js?
var config = {
type: 'line',
data: {
labels: [1,2,3,4,5],
datasets: [{
label: 'Chart 1',
data: [2,4,8,16],
}, {
label: 'Chart 2',
data: [3,4,6,9],
}]
},
Other charting libs offers a (label/data) set as parameter so I could simply give a tupel as parameter
(ie. [(1->2),(2->4),(3->8)...]
for each chart and the lib will match everything.
Thanks
Edit: Detailed sample as requested:
var config = {
type: 'line',
data: {
labels: [1, 2, 3, 4, 5],
datasets: [{
label: 'Chart 1',
data: [2, 4, 8, 16],
}, {
label: 'Chart 2',
data: [3, 4, 6, 9],
}]
},
options: {
spanGaps: true,
responsive: true,
title: {
display: true,
text: 'Chart.js Line Chart'
},
tooltips: {
mode: 'index',
intersect: false,
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
xAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Labels'
}
}],
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Values'
},
ticks: {
min: 1,
max: 10,
}
}]
}
}
};
window.onload = function() {
var ctx = document.getElementById('canvas').getContext('2d');
window.myLine = new Chart(ctx, config);
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script>
<div style="width:90%;" class="container">
<canvas id="canvas"></canvas><br>
</div>
Use scatter type chart and showLine: true instead of line type with labels:
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'scatter',
data: {
datasets: [
{
label: 'Chart 1',
data: [{x: 1, y: 2}, {x: 2, y: 4}, {x: 3, y: 8},{x: 4, y: 16}],
showLine: true,
fill: false,
borderColor: 'rgba(0, 200, 0, 1)'
},
{
label: 'Chart 2',
data: [{x: 1, y: 3}, {x: 3, y: 4}, {x: 4, y: 6}, {x: 6, y: 9}],
showLine: true,
fill: false,
borderColor: 'rgba(200, 0, 0, 1)'
}
]
},
options: {
tooltips: {
mode: 'index',
intersect: false,
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
},
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<canvas id="myChart"></canvas>
What this code does is, it displays multi line graph using chart.js
Create a class for your labeling x and y values
//DataContract for Serializing Data - required to serve in JSON format
[DataContract]
public class LabelPoint
{
//Explicitly setting the name to be used while serializing to JSON.
[DataMember(Name = "label")]
public string Label { get; set; }
public DataPoint DataPoint { get; set; }
}
[DataContract]
public class DataPoint
{
[DataMember(Name = "x")]
public List<string> X { get; set; }
//Explicitly setting the name to be used while serializing to JSON.
[DataMember(Name = "y")]
public List<string> Y { get; set; }
}
Controller code to retrieve data
List<LabelPoint> dataPoints = GetProducts.ToList()
.GroupBy(p => p.ProductName,
(k, c) => new LabelPoint()
{
DataPoint = new DataPoint { X = c.Select(y => y.Date.ToString("dd/MM/yyyy HH:mm")).ToList(), Y = c.Select(cs => cs.Quantity).ToList() },
Label = k
}
).ToList();
ViewBag.DataPoints = dataPoints;
cshtml code to display chart and retrieve data
<canvas id="myChart"></canvas>
<script>
$(document).ready(function () {
// Get the data from the controller using viewbag
// so the data looks something like this [ { Label : "ABC" , DataPoint :[ { X: '222' , Y :60 } ] } ]
var data = #Html.Raw(Json.Encode(ViewBag.DataPoints));
// declare empty array
var dataSet = []; var qty= []; var dates= [];
// loop through the data and get the Label as well as get the created dates and qty for the array of object
for (var i = 0; i < data.length; i++) {
qty.push(data[i].DataPoint.Y);
for (var d = 0; d < data[i].DataPoint.X.length; d++) {
// we're setting this on the X- axis as the label so we need to make sure that we get all the dates between searched dates
dates.push(data[i].DataPoint.X[d]);
}
// we create an array of object, set the Lable which will display LocationName, The data here is the Quantity
dataSet.push(
{
label: data[i].Label,
data: data[i].DataPoint.Y,
fill: false,
borderColor: poolColors(qtyInLocations.length),
pointBorderColor: "black",
pointBackgroundColor: "white",
lineTension: 0.1
}
);
}
// this is the options to set the Actual label like Date And Quantity
var options = {
scales: {
xAxes: [{
scaleLabel: {
display: true,
labelString: "Date",
fontSize: 20
},
}],
yAxes: [{
ticks: {
beginAtZero:true
},
scaleLabel: {
display: true,
labelString: 'Quantity',
fontSize: 20
}
}]
}
};
// we need to remove all duplicate values from the CreatedDate array
var uniq = [ ...new Set(dates) ];
// get the canvas
var ctx = document.getElementById("myChart").getContext('2d');
// build the chart
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: uniq,
datasets:dataSet
},
options: options
});
});
/// will get get random colors each time
function dynamicColors() {
var r = Math.floor(Math.random() * 255);
var g = Math.floor(Math.random() * 255);
var b = Math.floor(Math.random() * 255);
return "rgba(" + r + "," + g + "," + b + ", 0.5)";
}
/// will display random colors each time
function poolColors(a) {
var pool = [];
for(i = 0; i < a; i++) {
pool.push(dynamicColors());
}
return pool;
}
</script>
I have a graph with multiple data points / lines. Currently, if you hover near a data point, it will display the label/value for that point.
What I'd like is the following: when you hover anywhere on the chart, it will display the labels + values for all data points at that x-value simultaneously in a single label.
For example, let's take the given datasets:
Date (x-labels): ['Jan 01','Jan 02','Jan 03']
Apples Sold: [3,5,1]
Oranges Sold: [0,10,2]
Gallons of Milk Sold: [5,7,4]
When you hover over the middle of the graph, above the 'Jan 02' vertical space, the label should display:
Jan 02
-----------------------
Apples Sold: 5
Oranges Sold: 10
Gallons of Milk Sold: 7
Is there a simple way to accomplish this?
Thanks.
Is there a simple way to accomplish this?
YES !! There is a quite straightforward way to accomplish this. If you would have read the documentation, you could have found that pretty easily.
Anyway, basically you need to set the tooltips mode to index in your chart options, in order to accomplish the behavior you want.
...
options: {
tooltips: {
mode: 'index'
}
}
...
Additionally, you probably want to set the following:
...
options: {
tooltips: {
mode: 'index',
intersect: false
},
hover: {
mode: 'index',
intersect: false
}
}
...
This will make it so all of the expected hover/label interactions will occur when hovering anywhere on the graph at the nearest x-value.
From the Documentation :
# index
Finds item at the same index. If the intersect setting is true, the
first intersecting item is used to determine the index in the data. If
intersect false the nearest item, in the x direction, is used to
determine the index.
Here is a working example :
var ctx = document.getElementById('canvas').getContext('2d');
var chart = new Chart(ctx, {
type: 'line',
data: {
labels: ['Jan 01', 'Jan 02', 'Jan 03'],
datasets: [{
label: 'Apples Sold',
data: [3, 5, 1],
borderColor: 'rgba(255, 99, 132, 0.8)',
fill: false
}, {
label: 'Oranges Sold',
data: [0, 10, 2],
borderColor: 'rgba(255, 206, 86, 0.8)',
fill: false
}, {
label: 'Gallons of Milk Sold',
data: [5, 7, 4],
borderColor: 'rgba(54, 162, 235, 0.8)',
fill: false
}]
},
options: {
tooltips: {
mode: 'index',
intersect: false
},
hover: {
mode: 'index',
intersect: false
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<canvas id="canvas"></canvas>
For Chart.js 3.3.2, you can use #baburao's approach with a few changes. You can check the documentation. Put tooltip in plugins. Example:
...
options: {
plugins: {
tooltip: {
mode: 'nearest',
intersect: false
}
}
}
...
I know this is an old post, but in a time I needed to divide a bar on multiple datasets, but the labels to be keeped as original values:
eg:
dataset 1: Totals: 10 15 10
dataset 2: Red: 4 5 9
dataset 3: Blue: 4 2 1
In my chart I want to show the "Totals" bar and to collor a part of it in red/blue or "the rest" (which is Totals color). I'll don't write the code to modify the datasets, but I'll complete #busterroni answer for chartjs v3+
plugins: {
tooltip: {
mode: 'index',
intersect: false,
callbacks: {
label: (item) => item.dataset.label + ': ' +
this.originalValues[item.datasetIndex].data[item.dataIndex]
}
}
}
You can achieve this after plotting the data like this:
Html
<div class="container">
<h2>Chart.js — Line Chart Demo</h2>
<div>
<canvas id="myChart"></canvas>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.4/Chart.min.js">
</script>
CSS
.container {
width: 80%;
margin: 15px auto;
}
Javascript
var ctx = document.getElementById('myChart').getContext('2d');
function convert(str) {
var date = new Date(str),
mnth = ("0" + (date.getMonth() + 1)).slice(-2),
day = ("0" + date.getDate()).slice(-2);
return [date.getFullYear(), mnth, day].join("-");
}
var date = ["Tue Jun 25 2019 00:00:00 GMT+0530 (India Standard Time)"];
var y1 = [12];
var y2 = [32];
var y3 = [7];
var dataPoints1 = [], dataPoints2 = [], dataPoints3 = [], datep=[];
console.log(date.length)
if(date.length=="1"){
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["",convert(date[0]),""],
datasets: [{
label:"Tweets",
backgroundColor: "rgba(153,255,51,0.4)",
fill:false,
borderColor:"rgba(153,255,51,0.4)",
data: [null,y1[0],null]
}, {
label:"Retweets",
backgroundColor: "rgba(255,153,0,0.4)",
fill:false,
borderColor:"rgba(255,153,0,0.4)",
data: [null,y2[0],null]
},{
label:"Favourites",
backgroundColor: "rgba(197, 239, 247, 1)",
fill:false,
borderColor:"rgba(197, 239, 247, 1)",
data:[null,y3[0],null]
}
]
},
options: {
scales: {
xAxes: [{
gridLines: {
display: false
}
}],
yAxes: [{
ticks: {
display: true
},
gridLines: {
display: false,
// drawBorder: false //maybe set this as well
}
}]
},
}
});}
else{
for (var i = 0; i < date.length; i++) {
datep.push(convert(date[i]))
dataPoints1.push(y1[i]);
dataPoints2.push(y2[i]);
dataPoints3.push(y3[i]);
}
console.log(datep)
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: datep,
datasets: [{
label:"Tweets",
backgroundColor: "rgba(153,255,51,0.4)",
fill:false,
borderColor:"rgba(153,255,51,0.4)",
data: dataPoints1
}, {
label:"Retweets",
backgroundColor: "rgba(255,153,0,0.4)",
fill:false,
borderColor:"rgba(255,153,0,0.4)",
data: dataPoints2
},{
label:"Favourites",
backgroundColor: "rgba(197, 239, 247, 1)",
fill:false,
borderColor:"rgba(197, 239, 247, 1)",
data:dataPoints3
}
]
},
options: {
scales: {
xAxes: [{
gridLines: {
display: false
}
}],
yAxes: [{
ticks: {
display: true
},
gridLines: {
display: false,
// drawBorder: false //maybe set this as well
}
}]
},
}
});
}
or chk this fiddle https://jsfiddle.net/gqozfb4L/
You could try using JavaScript to track the users mouse and based on the position, return the data at that vertice.
document.querySelector('.button').onmousemove = (e) => {
const x = e.pageX - e.target.offsetLeft
const y = e.pageY - e.target.offsetTop
e.target.style.setProperty('--x', `${ x }px`)
e.target.style.setProperty('--y', `${ y }px`)
}