Добавление элементов D3.js в теневой DOM полимерного элемента

Я работаю над проектом Polymer (v1), и один из моих пользовательских полимерных элементов должен содержать диаграмму 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?


person Joel    schedule 31.03.2017    source источник


Ответы (1)


Я нашел решение. Мне просто нужно было добавить следующую строку в начало готовой функции в «Попытке решения 1».

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

Для получения дополнительной информации: Почему мой SVG визуализируется D3 внутри компонента Polymer без стилей?

person Joel    schedule 31.03.2017