代码之家  ›  专栏  ›  技术社区  ›  Hoàng Nguyễn

更改chartjs或ng2图表中悬停和工具提示的样式

  •  3
  • Hoàng Nguyễn  · 技术社区  · 7 年前

    有什么方法可以用chartjs或ng2图表改变悬停的样式和工具提示吗?我想隐藏悬停点,只在我将其与指示器一起悬停为直线时显示它们。下面是我想要构建的精确图表模型:

    https://interactive-bitcoin-price-chart-foxkmkynmg.now.sh/

    提前感谢您的提示。

    编辑:我按照GRUNT的指示将此图表选项应用到我的Angular应用程序中,每当我悬停时,完整的图表都会显示工具提示,但线条跟踪指示器不会。以下是我的代码:

    插件悬停线。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);
       };
    }
    

    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);
            }
          )
      }
    }
    

    模板:

    <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>
    
    2 回复  |  直到 7 年前
        1
  •  2
  •   ɢʀᴜɴᴛ    7 年前

    不幸的是,目前还没有内置的功能。但是你可以使用 this 图表插件

    要使用插件,请在图表中设置以下选项

    lineOnHover: {
       enabled: true,
       lineColor: '#bbb',
       lineWidth: 1
    }
    

    此外,请确保为数据集设置以下属性:

    pointRadius: 0,
    pointHoverRadius: 5,
    pointHoverBackgroundColor: 'white'
    

    live demo

        2
  •  0
  •   Kiong    5 年前

    这个答案是建立在 GRUNT's answer above 要能够显示多行图:


    here

    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));
    

    posX.forEach(function(pos, posIndex) {
      var metaDatum = []
      if (this.posX < pos + radius && this.posX > pos - radius) {
        chart.data.datasets.forEach((dataset, ind) => {
          metaDatum.push(chart.getDatasetMeta(ind).data[posIndex]);
        })
    
        chart.updateHoverStyle(metaDatum, null, true);
        chart.tooltip._active = metaDatum;
      } else {
        metaDatum.push(metaData[posIndex]);
        chart.updateHoverStyle(metaDatum, null, false);
      }
    }.bind(this));