如何将d3.js v5模块导入聚合物3元素?

时间:2018-10-02 12:58:19

标签: javascript d3.js polymer polymer-3.x

我之前使用d3 v3创建了聚合物1.x自定义元素。我想将它们更新为Polymer 3和d3 v5。

这里是基础聚合物3元素,我想将d3 v5包含在其中:

import {html, PolymerElement} from '@polymer/polymer/polymer-element.js';

/**
 * `foo-bar`
 * 
 *
 * @customElement
 * @polymer
 * @demo demo/index.html
 */
class FooBar extends PolymerElement {
  static get template() {
    return html`
      <style>
        :host {
          display: block;
        }
      </style>
      <h2>Hello [[prop1]]!</h2>
    `;
  }
  static get properties() {
    return {
      prop1: {
        type: String,
        value: 'foo-bar',
      },
    };
  }
  constructor() {
    super();
  }

  ready() {
    super.ready();
    console.log('foo-bar is ready!');
  }

}

window.customElements.define('foo-bar', FooBar);

我打电话给npm install d3

如何将d3导入此PolymerElement?我使用d3有两种不同类型的聚合物元素。我已经完成了力和层次聚合物元素。

我认为我需要在Polymer元素中的 constructor() ready()函数中做一些事情,以利用d3库。

我正在尝试以下导入:

import 'd3/dist/d3.js';

1 个答案:

答案 0 :(得分:3)

由于d3随附于ES模块。因此,您可以根据需要import

import { select, scaleOrdinal } from 'd3'
// or
import * as d3 from 'd3'

然后您可以照常使用d3

示例:

index.html

<foo-bar></foo-bar>
<script type='module' src='app.js'></script>

app.js

import { PolymerElement, html } from '@polymer/polymer/polymer-element.js'
import * as d3 from 'd3'

class FooBar extends PolymerElement {
  static get template () {
    return html`
      <style>
        .links line {
          stroke: #999;
          stroke-opacity: 0.6;
        }

        .nodes circle {
          stroke: #fff;
          stroke-width: 1.5px;
        }
      </style>

      <svg width='960' height='600'></svg>
    `
  }

  ready () {
    super.ready()
    this.initGraph()
  }

  initGraph () {
    let svg = d3.select(this.shadowRoot.querySelector('svg'))
    let width = +svg.attr('width')
    let height = +svg.attr('height')

    let color = d3.scaleOrdinal(d3.schemeCategory10)

    let simulation = d3.forceSimulation()
      .force('link', d3.forceLink().id(d => d.id))
      .force('charge', d3.forceManyBody())
      .force('center', d3.forceCenter(width / 2, height / 2))

    d3.json('miserables.json').then(graph => {
      let link = svg.append('g')
        .attr('class', 'links')
        .selectAll('line')
        .data(graph.links)
        .enter().append('line')
        .attr('stroke-width', d => Math.sqrt(d.value))

      let node = svg.append('g')
        .attr('class', 'nodes')
        .selectAll('circle')
        .data(graph.nodes)
        .enter().append('circle')
        .attr('r', 5)
        .attr('fill', d => color(d.group))
        .call(d3.drag()
          .on('start', dragstarted)
          .on('drag', dragged)
          .on('end', dragended))

      node.append('title').text(d => d.id)

      simulation.nodes(graph.nodes)
        .on('tick', () => {
          link
            .attr('x1', d => d.source.x)
            .attr('y1', d => d.source.y)
            .attr('x2', d => d.target.x)
            .attr('y2', d => d.target.y)
          node
            .attr('cx', d => d.x)
            .attr('cy', d => d.y)
        })

      simulation.force('link').links(graph.links)
    })

    function dragstarted (d) {
      if (!d3.event.active) simulation.alphaTarget(0.3).restart()
      d.fx = d.x
      d.fy = d.y
    }

    function dragged (d) {
      d.fx = d3.event.x
      d.fy = d3.event.y
    }

    function dragended (d) {
      if (!d3.event.active) simulation.alphaTarget(0)
      d.fx = null
      d.fy = null
    }
  }
}

customElements.define('foo-bar', FooBar)

注意:聚合物使用普通选择器(例如d3.select)无法通过的Shadow DOM。

在此示例中,我从Force-Directed Graph进行了修改。