请考虑以下代码:
var svg = d3.select('#somediv').append("svg").attr("width", w).attr("height", h);
Run Code Online (Sandbox Code Playgroud)
我想重构这段代码,以便它更像这样:
var svg = makesvg(w, h);
d3.select("#somediv").append(svg);
Run Code Online (Sandbox Code Playgroud)
请注意,与第一个版本中显示的情况相反,在第二个版本append 中不会创建 "svg"对象; 它只会附加到它d3.select("#somediv").
问题是如何实现该功能makesvg.这反过来又减少了问题:如何在不使用的情况下实例化"svg"对象append,因为可以执行以下操作:
function makesvg(width, height) {
return _makesvg().attr("width", w).attr("height", h);
}
Run Code Online (Sandbox Code Playgroud)
所以我的问题归结为_makesvg()上面提到的假设工厂的通用等价物是什么?
Dre*_*kes 29
您可以使用以下内容:
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
Run Code Online (Sandbox Code Playgroud)
注意使用createElementNS.这是必需的,因为svg元素与大多数HTML元素不在同一个XHTML名称空间中.
svg无论是否使用D3,此代码都会创建一个新元素,然后在该单个元素上创建一个选择.
这可以略微简洁但更清晰,更不容易出错:
var svg = document.createElementNS(d3.ns.prefix.svg, 'svg');
Run Code Online (Sandbox Code Playgroud)
Pau*_*aul 24
要节省一点时间,可以使用d3.ns.prefix.svg
var svg = document.createElementNS(d3.ns.prefix.svg, 'svg');
Run Code Online (Sandbox Code Playgroud)
最后,与D3的发布V5(3月22日第二,2018),但是现在可以在D3自身完成.这不会影响其他答案,无论如何,这些答案仍然有效,最后,D3将会document.createElementNS()像之前的帖子中描述的那样使用.
从v5开始,您现在可以使用:
给定指定的元素名称,返回包含当前文档中给定名称的分离元素的单元素选择.
这个新功能可以使用如下:
// Create detached <svg> element.
const detachedSVG = d3.create("svg");
// Manipulate detached element.
detachedSVG
.attr("width", 400)
.attr("height", 200);
// Bind data. Append sub-elements (also not attached to DOM).
detachedSVG.selectAll(null)
.data([50, 100])
.enter()
//...
// Attach element to DOM.
d3.select("body")
.append(() => detachedSVG.node());
Run Code Online (Sandbox Code Playgroud)
请查看以下代码片段,了解创建分离子树的工作演示,该子树附加在click事件上:
// Create detached <svg> element.
const detachedSVG = d3.create("svg");
// Manipulate detached element.
detachedSVG
.attr("width", 400)
.attr("height", 200);
// Bind data. Attach sub-elements.
detachedSVG.selectAll(null)
.data([50, 100])
.enter().append("circle")
.attr("r", 20)
.attr("cx", d => d)
.attr("cy", 50);
// Still detached. Attach on click.
d3.select(document)
.on("click", () => {
// Attach element to DOM.
d3.select("body")
.append(() => detachedSVG.node());
});Run Code Online (Sandbox Code Playgroud)
<script src="https://d3js.org/d3.v5.js"></script>Run Code Online (Sandbox Code Playgroud)
这种方法的主要优点是易于使用和清晰.元素的创建由D3在幕后完成,并且可以作为一个完整的选择,包含所有方法.除了操作新创建的分离元素之外,返回的选择可以很容易地用于数据绑定.
还值得注意的是,该函数不限制从SVG名称空间创建元素,但可用于从使用D3注册的任何名称空间创建元素.
小智 6
这是一个创建未附加组元素的示例函数:
function createSomething(){
return function(){
var group = d3.select(document.createElementNS(d3.ns.prefix.svg, 'g'));
// Add stuff...
return group.node();
}
}
Run Code Online (Sandbox Code Playgroud)
你可以像这样调用它:
node.append(createSomething());
Run Code Online (Sandbox Code Playgroud)
假设您正在渲染一个可折叠的树,并且您希望使用带有圆边框的加/减图标作为切换.你的绘图功能已经非常庞大,所以你想要代码在它自己的函数中绘制加号.绘制/更新方法将负责正确定位.
一种选择是将现有容器传递给函数:
createPlus(node).attr({
x: 10,
y: 10
});
function createPlus(node){
var group = node.append('g');
// Add stuff...
return group;
}
Run Code Online (Sandbox Code Playgroud)
我们可以通过应用@Drew和@Paul中的技术来创建未附加的元素,从而使这更好.
node.append(createPlus())
.attr({
x: 10,
y: 10
});
function createPlus(){
var group = d3.select(document.createElementNS(d3.ns.prefix.svg, 'g'));
// Add stuff...
return group;
}
Run Code Online (Sandbox Code Playgroud)
除了因为append()需要字符串或函数而抛出错误.
该名称可以指定为常量字符串,也可以指定为返回要追加的DOM元素的函数.
所以我们只需将其更改为:
node.append(function(){
return createPlus();
});
Run Code Online (Sandbox Code Playgroud)
但那仍然行不通.它会导致以下错误:
TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
Run Code Online (Sandbox Code Playgroud)
幸运的是我发现selection.node()哪个确实有效!虽然,诚然,我不知道为什么.
function createPlus(){
var group = d3.select(document.createElementNS(d3.ns.prefix.svg, 'g'));
// Add stuff...
return group.node();
}
Run Code Online (Sandbox Code Playgroud)
我们可以通过将匿名函数移动到createPlus以下内容来节省更多时间:
node.append(createPlus())
function createPlus(){
return function(){
var group = d3.select(document.createElementNS(d3.ns.prefix.svg, 'g'));
// Add stuff...
return group.node();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10055 次 |
| 最近记录: |