为什么我的 SVG 在 Polymer 组件内由 D3 呈现,没有样式?

Why is my SVG rendered by D3 inside a Polymer component unstyled?

Here is a Plunker sketch of my problem.

相关代码,包含 Polymer 模板及其调用:

<link rel="import"
      href="http://www.polymer-project.org/1.0/components/polymer/polymer.html">

<dom-module id="polymer-d3-component">
    <template>
        <style>
            #monthChart .line {
                stroke: rgb(247, 150, 29);
                stroke-width: 2;
                fill: none;
            }

            #monthChart .axis {
                shape-rendering: crispEdges;
            }

            #monthChart .x.axis line {
                stroke: rgba(88, 89, 93, .12);
            }

            #monthChart .x.axis .minor {
                stroke-opacity: .5;
            }

            #monthChart .x.axis path {
                display: none;
            }

            #monthChart .y.axis line, .y.axis path {
                fill: none;
                stroke: rgba(88, 89, 93, .5);
            }

            #monthChart .axis path,
            #monthChart .axis line {
                fill: none;
                stroke: rgba(88, 89, 93, .3);
                shape-rendering: crispEdges;
            }

            #monthChart .axis text {
                font: 10px sans-serif;
                fill: rgba(88, 89, 93, .5);
            }
        </style>

        <div id="monthChart"></div>
    </template>

    <script>
        Polymer({
            is: "polymer-d3-component",
            ready: function() {
                var m = [20, 20, 20, 20];
                var w = 850 - m[1] - m[3];
                var h = 400 - m[0] - m[2];

                var data=[24509, 19466, 18004, 18381, 17312, 19926, 24761, 24815, 24333, 29117, 24527, 17478];

                function formatCurrency (d) {
                    return "$" + d;
                }

                var xLabels = d3.time.scale().domain([new Date(2013, 0, 1), new Date(2013, 11, 31)]).range([0, w]);
                var x = d3.scale.linear().domain([0, data.length]).range([0, w]);
                var y = d3.scale.linear().domain([0, d3.max(data)]).range([h, 0]);

                var line = d3.svg.line()
                    .x(function(d, i) {
                        return x(i);
                    })
                    .y(function(d) {
                        return y(d);
                    })

                var graph = d3.select(this.$.monthChart).append("svg")
                            .attr("width", w + m[1] + m[3])
                            .attr("height", h + m[0] + m[2])
                        .append("g")
                            .attr("transform", "translate(" + 120 + "," + m[0] + ")");

                var xAxis = d3.svg.axis().scale(xLabels).ticks(d3.time.months).tickFormat(d3.time.format("%B")).tickSize(-h).tickSubdivide(true);
                graph.append("g")
                            .attr("class", "x axis")
                            .attr("transform", "translate(0," + h + ")")
                            .call(xAxis);

                var yAxisLeft = d3.svg.axis().scale(y).ticks(7).tickFormat(formatCurrency).orient("left");
                graph.append("g")
                            .attr("class", "y axis")
                            .attr("transform", "translate(-25,0)")
                            .call(yAxisLeft);

                    graph.append("path")
                        .attr("d", line(data))
                        .attr('class', 'line');
            }
        })
    </script>
</dom-module>

SVG 是错误的,但也没有应用样式,可以从全黑的形状和许多未正确绘制的形状中看出。如果我将 SVG 代码直接手动放入 Polymer 组件中,它可以正常工作。

可能发生了什么?

当模板呈现为 DOM 时,Polymer 会应用样式,因此 DOM 之后由库附加的节点(例如 ready)不会设置样式。这是描述 in the manual here.

解决方法是调用—

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

——在ready的开头。这告诉 Polymer 观察给定子树的变化,并在节点被其他库附加到它时应用给定样式,例如 D3。

Here's a fork of your Plunk with that.