【问题标题】:Typings for d3-cloudd3-cloud 的类型
【发布时间】:2017-01-20 11:52:44
【问题描述】:

我想使用d3-cloud 在我的 Angular2 应用程序中生成词云。但是,我找不到要安装的正确类型。我尝试了this,但是当我尝试在我的组件中导入它时,它不起作用。我不断收到错误消息,“在类型中找不到属性布局”。有人可以帮我解决这个问题吗?

【问题讨论】:

标签: angular typescript d3.js d3-cloud


【解决方案1】:

我想出了如何做到这一点。不是正确的 Typescript 方式,而是使用后备 JS 方式。以下是你的做法:

  1. import d3 库像往常一样,但给它一个别名:import * as D3 from 'd3';(注意:D3 的大写 D)
  2. declare d3 再次用于 WordCloud:declare let d3: any;
  3. D3 用于所有与父 d3 库相关的内容,d3 用于单独的词云生成。

d3-cloud 的类型似乎不起作用。所以declareing 似乎是目前唯一的方法。

完整代码

word-cloud.component.ts

import { Component, Input, ElementRef, DoCheck, KeyValueDiffers } from '@angular/core';
import { WordCloudConfig } from '../../../models/charts/word-cloud-config';
import * as D3 from 'd3';

declare let d3: any;

@Component({
  selector   : 'word-cloud',
  templateUrl: './word-cloud.component.html',
  styleUrls  : ['./word-cloud.component.scss']
})
export class WordCloudComponent implements DoCheck {

  @Input() config: WordCloudConfig;

  private _host;              // D3 object referencing host DOM object
  private _svg;               // SVG in which we will print our chart
  private _margin: {          // Space between the svg borders and the actual chart graphic
    top: number,
    right: number,
    bottom: number,
    left: number
  };
  private _width: number;      // Component width
  private _height: number;     // Component height
  private _htmlElement: HTMLElement; // Host HTMLElement
  private _minCount: number;   // Minimum word count
  private _maxCount: number;   // Maximum word count
  private _fontScale;          // D3 scale for font size
  private _fillScale;          // D3 scale for text color
  private _objDiffer;

  constructor(private _element: ElementRef, private _keyValueDiffers: KeyValueDiffers) {
    this._htmlElement = this._element.nativeElement;
    this._host = D3.select(this._element.nativeElement);
    this._objDiffer = this._keyValueDiffers.find([]).create(null);
  }

  ngDoCheck() {
    let changes = this._objDiffer.diff(this.config);
    if (changes) {
      if (!this.config) {
        return;
      }
      this._setup();
      this._buildSVG();
      this._populate();
    }
  }

  private _setup() {
    this._margin = {
      top   : 10,
      right : 10,
      bottom: 10,
      left  : 10
    };
    this._width = ((this._htmlElement.parentElement.clientWidth == 0)
        ? 300
        : this._htmlElement.parentElement.clientWidth) - this._margin.left - this._margin.right;
    if (this._width < 100) {
      this._width = 100;
    }
    this._height = this._width * 0.75 - this._margin.top - this._margin.bottom;

    this._minCount = D3.min(this.config.dataset, d => d.count);
    this._maxCount = D3.max(this.config.dataset, d => d.count);

    let minFontSize: number = (this.config.settings.minFontSize == null) ? 18 : this.config.settings.minFontSize;
    let maxFontSize: number = (this.config.settings.maxFontSize == null) ? 96 : this.config.settings.maxFontSize;
    this._fontScale = D3.scaleLinear()
                        .domain([this._minCount, this._maxCount])
                        .range([minFontSize, maxFontSize]);
    this._fillScale = D3.scaleOrdinal(D3.schemeCategory20);
  }

  private _buildSVG() {
    this._host.html('');
    this._svg = this._host
                    .append('svg')
                    .attr('width', this._width + this._margin.left + this._margin.right)
                    .attr('height', this._height + this._margin.top + this._margin.bottom)
                    .append('g')
                    .attr('transform', 'translate(' + ~~(this._width / 2) + ',' + ~~(this._height / 2) + ')');
  }

  private _populate() {
    let fontFace: string = (this.config.settings.fontFace == null) ? 'Roboto' : this.config.settings.fontFace;
    let fontWeight: string = (this.config.settings.fontWeight == null) ? 'normal' : this.config.settings.fontWeight;
    let spiralType: string = (this.config.settings.spiral == null) ? 'rectangular' : this.config.settings.spiral;

    d3.layout.cloud()
      .size([this._width, this._height])
      .words(this.config.dataset)
      .rotate(() => 0)
      .font(fontFace)
      .fontWeight(fontWeight)
      .fontSize(d => this._fontScale(d.count))
      .spiral(spiralType)
      .on('end', () => {
        this._drawWordCloud(this.config.dataset);
      })
      .start();
  }

  private _drawWordCloud(words) {
    this._svg
        .selectAll('text')
        .data(words)
        .enter()
        .append('text')
        .style('font-size', d => d.size + 'px')
        .style('fill', (d, i) => {
          return this._fillScale(i);
        })
        .attr('text-anchor', 'middle')
        .attr('transform', d => 'translate(' + [d.x, d.y] + ')rotate(' + d.rotate + ')')
        .attr('class', 'word-cloud')
        .text(d => {
          return d.word;
        });
  }

}

word-cloud.component.html

<ng-content></ng-content>

word-cloud.component.scss

.word-cloud {
  cursor                : default;
  -webkit-touch-callout : none;
  -webkit-user-select   : none;
  -khtml-user-select    : none;
  -moz-user-select      : none;
  -ms-user-select       : none;
  user-select           : none;
}

【讨论】:

  • 谢谢伙计,这对我有用。只需要玩转图书馆就可以得到我想要的外观。
  • 您是如何在您的应用程序中包含 d3-cloud 的?我正在使用带有 webpack 的 angular-cli,因为 d3-cloud NPM 模块使用了“require”。
  • @ansorensen 您不必“包含”d3-cloud。我只是将&lt;script src="https://cdn.rawgit.com/jasondavies/d3-cloud/v1.2.1/build/d3.layout.cloud.js"&gt;&lt;/script&gt;添加到index.html中并使用答案中提到的方法访问它。
  • 谢谢!该链接已损坏,但当前包确实有一个构建文件夹。我一直在使用 index.js(需要 node 或 browserify)并且没有意识到构建版本是独立的。刚刚将构建版本添加到我的编译脚本列表中,瞧! (好吧,加上大量从包中按摩示例代码)。
  • 酷!我没有意识到链接一直被破坏。谢谢你,我修好了。 :D
【解决方案2】:

我按照以下步骤解决了 -

  1. 导入 d3-cloud npm 包 --> npm i d3-cloud
  2. d3-cloud 的导入类型 --> npm i @types/d3-cloud --save-dev
  3. 下面是示例 component.ts 导入和代码 -

import * as d3 from "d3";
import * as d3Cloud from "d3-cloud";

wordCloud(): void {
    let svg: any = d3.select("svg")
        .attr("width", 850)
        .attr("height", 350);
    d3Cloud().size([800, 300])
        .words(wordList)
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-06
    • 2016-07-21
    • 2016-10-19
    • 2017-07-13
    • 1970-01-01
    • 2017-06-28
    • 2022-01-23
    • 1970-01-01
    相关资源
    最近更新 更多