is there any way to change style of hover as well as the tooltip with chartjs or ng2-charts? I want to hide the hover points and only display them whenever I hover on them along with the indicator as the line. Here is the exact chart model I want to build:
https://interactive-bitcoin-price-chart-foxkmkynmg.now.sh/
Thank you in advance for your tips.
EDIT: I followed instructions of GRUNT to apply this chart option into my Angular app, the full chart is shown with tooltip whenever I hover, but the line-trace indicator is not. Here are my codes:
plugin-hoverline.ts:
export class PluginHoverline {
posX: null;
isMouseOut:boolean = false;
drawLine(chart, posX) {
const ctx = chart.ctx,
x_axis = chart.scales['x-axis-0'],
y_axis = chart.scales['y-axis-0'],
x = posX,
topY = y_axis.top,
bottomY = y_axis.bottom;
if (posX < x_axis.left || posX > x_axis.right) return;
// draw line
ctx.save();
ctx.beginPath();
ctx.moveTo(x, topY);
ctx.lineTo(x, bottomY);
ctx.lineWidth = chart.options.lineOnHover.lineWidth;
ctx.strokeStyle = chart.options.lineOnHover.lineColor;
ctx.stroke();
ctx.restore();
};
beforeInit(chart) {
chart.options.events.push('mouseover');
};
afterEvent(chart, event) {
if (!chart.options.lineOnHover || !chart.options.lineOnHover.enabled) return;
if (event.type !== 'mousemove' && event.type !== 'mouseover') {
if (event.type === 'mouseout') this.isMouseOut = true;
chart.clear();
chart.draw();
return;
}
this.posX = event.x;
this.isMouseOut = false;
chart.clear();
chart.draw();
this.drawLine(chart, this.posX);
var metaData = chart.getDatasetMeta(0).data,
radius = chart.data.datasets[0].pointHoverRadius,
posX = metaData.map(e => e._model.x);
posX.forEach(function(pos, posIndex) {
if (this.posX < pos + radius && this.posX > pos - radius) {
chart.updateHoverStyle([metaData[posIndex]], null, true);
chart.tooltip._active = [metaData[posIndex]];
} else chart.updateHoverStyle([metaData[posIndex]], null, false);
}.bind(this));
chart.tooltip.update();
};
afterDatasetsDraw(chart, ease) {
if (!this.posX) return;
if (!this.isMouseOut) this.drawLine(chart, this.posX);
};
}
banner.component.ts: (chart component)
import { Component, OnInit } from '@angular/core';
import { HistoricalBpiService } from '../../services/historical-bpi.service';
import { PluginHoverline } from './plugin-hoverline';
@Component({
selector: 'app-banner',
templateUrl: './banner.component.html',
styleUrls: ['./banner.component.scss']
})
export class BannerComponent implements OnInit {
private dataUrl: string = 'historical/close.json';
constructor(
private historicalBpiService:HistoricalBpiService
) {}
// lineChart
public lineChartData:any = [
{ data:[], label: 'Bitcoin price' }
];
public lineChartLabels:Array<any> = [];
public lineChartOptions:any = {
responsive: true,
maintainAspectRatio: false,
layout: {
padding: 0
},
lineOnHover: {
enabled: true,
lineColor: '#bbb',
lineWidth: 1
},
scales: {
yAxes: [{
display: true,
scaleLabel: {
display: false,
labelString: 'USD'
},
ticks: {
display: false
},
gridLines: {
display: true,
tickMarkLength: 0
}
}],
xAxes: [{
ticks: {
display: false
},
gridLines: {
display: false,
tickMarkLength: 0
}
}]
},
elements: {
point: {
radius: 3
},
line: {
tension: 0.4, // 0 disables bezier curves
}
},
hover: {
mode: 'nearest',
intersect: false
},
tooltips: {
mode: 'nearest',
intersect: false,
backgroundColor: 'rgb(95,22,21)',
callbacks: {
label: function (tooltipItems, data) {
return data.datasets[tooltipItems.datasetIndex].label + ' : ' + '$' + tooltipItems.yLabel.toLocaleString();
},
labelColor: function(tooltipItem, chart) {
var dataset = chart.config.data.datasets[tooltipItem.datasetIndex];
return {
backgroundColor : dataset.backgroundColor
}
}
}
}
};
public lineChartColors:Array<any> = [
{
backgroundColor: 'rgba(199,32,48,0.8',
borderColor: 'rgb(95,22,21);',
pointBackgroundColor: 'rgba(218,208,163,0.8)',
pointHoverBackgroundColor: 'rgba(218,208,163,0.8)',
pointHoverBorderColor: 'rgb(218,208,163)',
pointHoverRadius: 6,
steppedLine: false
}
];
public lineChartLegend:boolean = false;
public lineChartType:string = 'line';
// events
public chartClicked(e:any):void {
console.log(e);
}
public chartHovered(e:any):void {
console.log(e);
}
ngOnInit(){
this.historicalBpiService.getBpiData(this.dataUrl)
.subscribe(
res => {
//this.lineChartData = Object.keys(res.bpi).map(function (key) { return res.bpi[key];});
this.lineChartData[0].data = Object.values(res.bpi);
this.lineChartLabels = Object.keys(res.bpi);
//console.log(this.lineChartData,this.lineChartLabels);
}
)
}
}
template:
<div class="chart">
<canvas baseChart height="360px"
[datasets]="lineChartData"
[labels]="lineChartLabels"
[options]="lineChartOptions"
[colors]="lineChartColors"
[legend]="lineChartLegend"
[chartType]="lineChartType"
(chartHover)="chartHovered($event)"
(chartClick)="chartClicked($event)"></canvas>
</div>
Unfortunately there is no built-in functionality for this yet. However you can use this chart plugin (once created for my own purpose) to achieve your goal.
To utilize the plugin, set the following option in your chart's options config :
lineOnHover: {
enabled: true,
lineColor: '#bbb',
lineWidth: 1
}
also, make sure to set the following properties for your dataset :
pointRadius: 0,
pointHoverRadius: 5,
pointHoverBackgroundColor: 'white'
see - live demo