1

I have created polymer 1.x custom elements using d3 v3 before. I want to update them to polymer 3 and d3 v5.

Here is a base polymer 3 element that I want to include d3 v5 into:

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

I call npm install d3

How shall I import d3 into this PolymerElement? I have two different types of polymer elements using d3. I have done both force and hierarchy polymer elements.

I am figuring that I need to do something in the constructor() or ready() functions within the polymer element to utilize the d3 library.

I was trying the following import:

import 'd3/dist/d3.js';
4

1 回答 1

3

因为d3已经附带了 ES 模块。因此,您可以根据需要导入

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

然后就可以d3照常使用了。

例子:

索引.html

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

应用程序.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)

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

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

于 2018-10-03T07:18:44.147 回答