d3.js - 将 D3.js 元素附加到 Polymer 元素的 Shadow DOM

标签 d3.js polymer shadow-dom

我正在开发一个 polymer (v1) 项目,我的一个自定义 polymer 元素需要包含 D3 (v4) 图表。 D3 似乎在附加到 DOM 方面的工作量很大。不幸的是,Polymer 对于 DOM 操作的执行方式似乎相当严格。

我创建了一个非常简单的 D3 图表版本,我想要实现:

index.html

<!DOCTYPE html>
<html>
<head>
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <style>
        .bar {
            fill: #0198E1;
        }
    </style>
</head>
<body>

<svg></svg>

<script>
var data = [100, 120, 130, 110, 150, 90];

const CHART_WIDTH = 126;
const CHART_HEIGHT = 160;

svg = d3.select('svg')
    .attr("width", CHART_WIDTH)
    .attr("height", CHART_HEIGHT);

svg.selectAll('rect')
    .data(data).enter().append('rect')
        .attr("x", function(d, i) {return i * 21})
        .attr("y", function(d) {return CHART_HEIGHT - d})
        .attr("height", function(d) {return d})
        .attr("width", 20)
        .attr("class", "bar");
</script>
</body>
</html>

我尝试了使用以下文件的两种解决方案。

index.html

<!DOCTYPE html>
<html>
<head>
    <link rel="import" href="../bower_components/polymer/polymer.html">
    <link rel="import" href="./d3-chart.html">
</head>
<body>
    <d3-chart></d3-chart>
</body>
</html>

d3-lib.html

<script src="https://d3js.org/d3.v4.min.js"></script>

尝试的解决方案 1

使用 D3 和 Polymer 的组合来选择目标 svg 元素,然后执行 d3 附加。

d3-chart.html

<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="./d3-lib.html">

<dom-module id="d3-chart">
    <template>
        <style>
           .bar {
               fill: #0198E1;
           }
        </style>

        <svg id="svg"></svg>
    </template>

    <script>
        Polymer({
            is: 'd3-chart',
            properties: {
                data: {
                    Type: Array,
                    value: [100, 120, 130, 110, 150, 90]
                }
            },
            ready: function() {
                const CHART_WIDTH = 126;
                const CHART_HEIGHT = 160;

                var svg = d3.select(this.$.svg)
                    .attr("width", CHART_WIDTH)
                    .attr("height", CHART_HEIGHT);

                svg.selectAll('rect')
                    .data(this.data).enter().append('rect')
                        .attr("x", function(d, i) {return i * 21})
                        .attr("y", function(d) {return CHART_HEIGHT - d})
                        .attr("height", function(d) {return d})
                        .attr("width", 20)
                        .attr("class", "bar");
            }
        });
    </script>
</dom-module>

这成功显示了图表,但 css 样式不适用。我认为这是因为 Polymer 不“了解”已附加的新元素。

尝试的解决方案 2

使用 D3 选择一个新的 svg 元素(不在 DOM 中),对该元素执行 D3 附加,然后使用 Polymer 将其附加到 DOM。

d3-chart.html

<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="./d3-lib.html">

<dom-module id="d3-chart">
    <template>
        <style>
           .bar {
               fill: #0198E1;
           }
        </style>

    </template>

    <script>
        Polymer({
            is: 'd3-chart',
            properties: {
                data: {
                    Type: Array,
                    value: [100, 120, 130, 110, 150, 90]
                }
            },
            ready: function() {
                const CHART_WIDTH = 126;
                const CHART_HEIGHT = 160;

                var newSvgElement = document.createElement("svg");

                var svg = d3.select(newSvgElement)
                    .attr("width", CHART_WIDTH)
                    .attr("height", CHART_HEIGHT);

                svg.selectAll('rect')
                    .data(this.data).enter().append('rect')
                        .attr("x", function(d, i) {return i * 21})
                        .attr("y", function(d) {return CHART_HEIGHT - d})
                        .attr("height", function(d) {return d})
                        .attr("width", 20)
                        .attr("class", "bar");

                Polymer.dom(this.root).appendChild(newSvgElement);
            }
        });
    </script>
</dom-module>

此代码成功将所有元素附加到 DOM,但没有显示任何内容。

将 Polymer 与 D3 集成的正确方法是什么?

最佳答案

我找到了解决方案。我只需将以下行添加到“尝试的解决方案 1”中的就绪函数的开头即可。

this.scopeSubtree(this.$.svg, true);

欲了解更多信息: Why is my SVG rendered by D3 inside a Polymer component unstyled?

关于d3.js - 将 D3.js 元素附加到 Polymer 元素的 Shadow DOM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43149989/

相关文章:

javascript - 工具提示中的 c3.js 时间格式

html - iOS 中 textarea 上的 Shadow DOM 强制填充

typescript - Rust WebAssembly 自定义元素内存释放错误

performance - 使用 FAST 有没有办法将样式应用于 ShadowDOM 子元素?

javascript - C3js时间序列无法显示连续线

d3.js - 如何可视化两个图之间的差异

polymer - 应使用哪个 Polymer 生命周期事件在渲染之前修改包含的元素?

polymer :在数据绑定(bind)表达式中使用函数

javascript - polymer JS : Does prepending an item to an Array property re-render the whole UI?

javascript - dc-js 折线图在过滤其他图表后消失