我正在开发一个 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/