如何创建一个返回自定义SVG图形而不附加任何内容的函数?我可以创建一个空选择并将其返回吗? 我目前有什么:
function makeGraphic(svgParent) {
return svgParent.append('circle').attrs({...});
}
这就是我想要的:
function makeGraphic() {
return d3.makeCircle?.attrs({...});
}
svgParent.append(makeGraphic());
答案 0 :(得分:2)
您可以在函数内部使用svg命名空间创建一个临时的svg节点-无需渲染svg。然后,您可以在处理svg并返回某种形状时将其视为典型节点。
要注意的一件事是.append()
接受标记名称或函数,因此我在下面不提供该函数的结果:
var svg = d3.select("body")
.append("svg")
.attr("width", 400)
.attr("height",200)
.attr("transform", "translate(200,100)");
var makeCircle = function() {
// create a temporary svg
let svg = document.createElementNS(d3.namespaces.svg, "svg")
// create a circle
let circle = d3.select(svg).append("circle")
.attr("r", 20)
.attr("fill", "steelblue");
// return a circle
return circle.node();
}
svg.append(makeCircle);
<script src="https://d3js.org/d3.v5.min.js"></script>
这样,您可以制作更复杂的形状生成器以返回形状以供d3.append()
之类的东西使用:
let svg = d3.select("body").append("svg")
.attr("width", 500)
.attr("height", 200);
var shapes = [{shape: "circle",y: 40, fill: "darkblue"},{shape:"square", y: 35},{y:40}]
svg.selectAll()
.data(shapes)
.enter()
.append(shapemaker);
function shapemaker(options = {}) {
let svg = document.createElementNS(d3.namespaces.svg, "svg")
var shape;
if (options.shape == "circle") {
shape = d3.select(svg).append("circle")
.attr("cx", options.x ? options.x : 50)
.attr("cy", options.y ? options.y : 50)
.attr("r", options.r ? options.r : 10)
.attr("fill", options.fill ? options.fill : "steelblue" )
}
else if (options.shape == "square") {
shape = d3.select(svg).append("rect")
.attr("x", options.x ? options.x : 100)
.attr("y", options.y ? options.y : 50)
.attr("width", options.width ? options.size : 10)
.attr("height", options.width ? options.size : 10)
.attr("fill", options.fill ? options.fill : "orange" )
}
else {
let x = options.x ? options.x : 150, y = options.y ? options.y : 50;
shape = d3.select(svg).append("path")
.attr("d", d3.symbol().type(d3.symbolStar).size(options.size ? options.size : 100))
.attr("transform","translate("+[x,y]+")")
.attr("fill", options.fill ? options.fill : "crimson")
}
return shape.node();
}
<script src="https://d3js.org/d3.v5.min.js"></script>
答案 1 :(得分:2)
在我看来,这是使用detached element的理想情况。您也可以使用DocumentFragment,但是在D3代码中,分离元素更常见。
要创建分离的whatever
SVG元素,您需要做的是:
var detached = d3.create('svg:whatever');
根据文档
给出指定的元素名称,返回一个单元素选择,其中包含当前文档中给定名称的分离元素。
这与Andrew's answer非常相似,因为内部d3.create
使用document.createElement
。但是请注意,它使用document.createElement
,而不是document.createElementNS
,因此此处需要名称空间:
var detached = d3.create('svg:whatever');
//this is the namespace----ˆ
然后,在那之后,您可以创建所需的结构。例如:
detached.selectAll(null)
.data(d3.range(5))
.enter()
.append("circle")
//etc...
最后,使用append
,获取分离元素的节点并将其附加到所需的位置:
svg.append(function(){ return detached.node();});
这是一个演示,函数makeGraphic
创建一个分离的元素,并返回其节点。然后,我们只需将返回值附加到SVG:
var svg = d3.select("body")
.append("svg")
.attr("width", 500)
.attr("height", 300);
function makeGraphic() {
var detached = d3.create('svg:g');
detached.selectAll(null)
.data(d3.range(10))
.enter()
.append("circle")
.attr("cx", function() {
return Math.random() * 500
})
.attr("cy", function() {
return Math.random() * 300
})
.attr("r", function() {
return Math.random() * 50
})
.attr("fill", function(_, i) {
return d3.schemeCategory10[i]
});
return detached.node();
};
svg.append(makeGraphic)
<script src="https://d3js.org/d3.v5.min.js"></script>