Anychart.js 动态显示数据

Anychart.js Display data dynamically

我正在尝试使用 Anychart v8 和 Angular CLI v10.0.4 使用从数据库中获取的数据绘制时间线图表 我看到这个 topic,这与我这里的问题非常相似。我按照步骤操作,但看不到数据。我收到此错误:错误:属性 d:预期数字,“M NaN 56.5 L NaN 5 ...”。 我试着硬编码数据,然后它工作得很好,所以我不知道出了什么问题。

以下是我如何使用 Sequelize 获取数据:

exports.getAllStoryArcs = (req, res, next) => {
    StoryArc.findAll({
        include: [StoryArc.startChapter, StoryArc.endChapter],
        order: [['startChapter', 'number', 'ASC']]
    })
            .then((storyArcs) => {
                res.status(200).json(storyArcs);
            })
            .catch((err) => {
                console.log(err);
                res.status(400).json({
                    error: err
                })
            });
};

编辑:这是使用 Sequelize 从 MySQL 数据库获取的数据示例:

[
  Story Arc {
    dataValues: {
      id: 6,
      name: "Introduction",
      synopsis: "synopsis text",
      delailedSummary: "detailedSummary text",
      createdAt: 2020-08-22T16:41:21.000Z,
      updatedAt: 2020-08-22T16:41:21.000Z,
      startChapterId: 1,
      endChapterId: 8,
      startChapter: {
        id: 1,
        number: 1,
        title: "title text",
        synopsis: "synopsis text"
      },
      endChapter: {
        id: 8,
        number: 8,
        title: "title text",
        synopsis: "synopsys text"
      }
    }
  }
]

这是我的数据转换函数 (data.service.ts) :

<div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre><code>import { Injectable } from '@angular/core';
import { StoryArcService } from './story-arc.service';
import { StoryArcDTO } from '../models/story-arc-dto.model';
const BASE_YEAR: number = 2000;
const START_MONTH: number = 0;
const END_MONTH: number = 11;
const START_DAY: number = 1;
const END_DAY: number = 31;

@Injectable({
  providedIn: 'root'
})
/**
* Service class to manage the timeline chart's data.
*/
export class DataService {
  
  // Array of arcs
  private _arcs: Array<StoryArcDTO>;
  // The arcs mapped to be use in the timeline chart
  private _arcsMap: Array<Object> = [];
  // The set to use in the chart
  private _arcsSet: anychart.data.Set;
  
  constructor(private arcService: StoryArcService) {
    this.setArcData();
  }
  
  private setArcData() {
    // Fill the array of story arcs
    this.arcService.getAllArcs().subscribe(
      gottenArcs => {
        if (gottenArcs) {
          this._arcs = gottenArcs;
          // Fill the anychart data set
          this._arcs.forEach((arc) => {
            // Map the arc data set
            this._arcsMap.push({
              name: arc.name,
              start: Date.UTC(BASE_YEAR + arc.startChapter.number, START_MONTH, START_DAY),
              end: Date.UTC(BASE_YEAR + arc.endChapter.number, END_MONTH, END_DAY),
              startNb: arc.startChapter.number,
              endNb: arc.endChapter.number
            });
          });
        }
      }
    );
  }
  
  public get arcsMap() : Object[] {
    return this._arcsMap;
  }
}

编辑 2:我确实完成了映射,但它不起作用。映射后,它看起来像这样:

[
   {name: "Introduction", start: Date.UTC(2001, 0, 1), end: Date.UTC(2008, 11, 31), startNb: 1, endNb: 8},
   {name: "Révolution chez les princesses", start: Date.UTC(2009, 0, 1), end: Date.UTC(2014, 11, 31), startNb: 9, endNb: 14},
   {name: "La formule magique de l'ange", start: Date.UTC(2015, 0, 1), end: Date.UTC(2019, 11, 31), startNb: 15, endNb: 19}
]

然后是我的组件 (timelines.component.js):


<div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre><code>import { Component, OnInit, AfterViewInit } from '@angular/core';
import 'anychart';
import { DataService } from 'src/app/services/data.service';

@Component({
  selector: 'app-timelines',
  templateUrl: './timelines.component.html',
  styleUrls: ['./timelines.component.css']
})
export class TimelinesComponent implements OnInit {
  
  public initTimeline: anychart.charts.Timeline;
  public globalTimeline: anychart.charts.Timeline;
  public globalRange: anychart.core.timeline.series.Range;
  
  constructor(private dataService: DataService) { }
  
  ngOnInit(): void {
    this.initChart();
  }
  
  initChart() {
    console.log(this.dataService.arcsMap);
    let arcsSet = anychart.data.set(this.dataService.arcsMap);
    
    this.globalTimeline = anychart.timeline();
    this.globalTimeline.axis().height(20);
    this.globalTimeline.axis().fill("#7030A0");
    this.globalTimeline.axis().stroke("#381850");
    this.globalTimeline.axis().ticks().stroke("#AB74D5");
    this.globalTimeline.axis().labels().fontFamily("Ubuntu");
    this.globalTimeline.axis().labels().fontWeight("bold");
    this.globalTimeline.axis().labels().fontColor("#E3D1F1");
    this.globalTimeline.axis().labels().format(function() {
      let realNumber = this.value;
      if (realNumber >= BASE_YEAR) {
        realNumber = this.value - BASE_YEAR;
      }
      return realNumber;
    })
    
    this.globalRange = this.globalTimeline.range(arcsSet);
    
    this.globalRangeSettings();
    
    this.globalTimeline.container("global-timeline");
    this.globalTimeline.draw();      
  }
  
  globalRangeSettings() {
    this.globalRange.height(30);
    this.globalRange.labels().format("{%name}");
    this.globalRange.labels().fontFamily("Ubuntu");
    this.globalRange.tooltip().titleFormat("{%name}");
    this.globalRange.tooltip().fontFamily("Ubuntu");
    this.globalRange.tooltip().format(function() {
      return `Début : Chapitre ${this.getData("startNb")}
              Fin : Chapitre ${this.getData("endNb")}`;
    })
    this.globalRange.color("#8E44BD");
  }
}

我验证了,我在 initChart 函数中得到了我想要的数据,但是 draw 函数似乎不理解它们。

有人可以帮我吗?

您的数据内容不符合图表要求的数据格式。您可以对其进行预处理或应用指定的映射,让图表正确解析您的数据。您可以在 the article. The sample 描述如何将映射应用到时间轴图表中找到所需的数据格式。

好的,所以我按照@AnyChart Support 所说的关于获取数据的时间。

我摆脱了我的数据服务 class,我转换了时间线组件中的数据,并将 async 关键字添加到我的 iniChart 方法中,所以它起作用了!

我真的不明白为什么 XD

结果如下所示:

ngOnInit(): void {
    this.initChart();
}
    
async initChart() {
    let arcsSet = anychart.data.set(await this.setArcData());
        
    this.globalTimeline = anychart.timeline();
    this.globalTimeline.axis().height(20);
    this.globalTimeline.axis().fill("#7030A0");
    this.globalTimeline.axis().stroke("#381850");
    this.globalTimeline.axis().ticks().stroke("#AB74D5");
    this.globalTimeline.axis().labels().fontFamily("Ubuntu");
    this.globalTimeline.axis().labels().fontWeight("bold");
    this.globalTimeline.axis().labels().fontColor("#E3D1F1");
    this.globalTimeline.axis().labels().format(function() {
        let realNumber = this.value;
        if (realNumber >= BASE_YEAR) {
            realNumber = this.value - BASE_YEAR;
        }
        return realNumber;
    });
        
    this.globalRange = this.globalTimeline.range(arcsSet);
        
    this.globalRangeSettings();
        
    this.globalTimeline.container("global-timeline");
    this.globalTimeline.draw();      
}
      
globalRangeSettings() {
    this.globalRange.height(30);
    this.globalRange.labels().format("{%name}");
    this.globalRange.labels().fontFamily("Ubuntu");
    this.globalRange.tooltip().titleFormat("{%name}");
    this.globalRange.tooltip().fontFamily("Ubuntu");
    this.globalRange.tooltip().format(function() {
        return `Début : Chapitre ${this.getData("startNb")}
                Fin : Chapitre ${this.getData("endNb")}`;
        })
    this.globalRange.color("#8E44BD");
}
      
async setArcData(): Promise<Object[]> {
    this.arcs = await this.arcService.getAllArcs().toPromise();
    let result: Object[] = [];
    this.arcs.forEach(arc => {
        result.push({
            name: arc.name,
            start: Date.UTC(BASE_YEAR + arc.startChapter.number, START_MONTH, START_DAY),
            end: Date.UTC(BASE_YEAR + arc.endChapter.number, END_MONTH, END_DAY),
            startNb: arc.startChapter.number,
            endNb: arc.endChapter.number
        });
    });
    return result;
}