SVG 标记未呈现
SVG markers not rendering
任何人都可以帮助我了解如何在以下示例中让标记呈现在路径上吗?
var size = {width: 500, height: 180},
svg = d3.select("body").append("svg").attr(size),
markers = Marker(svg, "red");
var circles = svg.append("ellipse").datum({})
.attr({
class: "circle",
'cx': size.width / 2,
'cy': size.height / 2,
'ry': 50,
'rx': 100,
"fill": "steelblue"
}),
shadePath = svg.append("path")
.attr({
class: "arrow",
d: d3.svg.line()([[100,50], [400,150]]),
stroke: "red"
}).style({
"marker-start": markers.start,
"marker-end": markers.end
});
function Marker(svg, color){
var id = "filter-marker", defs = svg.selectAll("defs").data([id]),
idS = id + "-start", idE = id + "-end";
defs.enter().append("defs");
var markers = defs.selectAll("#"+id).data([
{
attr: {id: idS, viewBox: "0 0 7 7",
markerWidth: "7", markerHeight: "7",
refX: "4", refY: "4",orient: "auto"},
symbol: {
type: "rect",
attr: {x: "1", y: "1", width: "5", height: "5", style: "stroke: none; fill: " + color + ";"}
}
},
{
attr: {id: idE, viewBox: "0 0 13 13",
markerWidth: "13", markerHeight: "13",
refX: "2", refY: "7", orient: "auto"},
symbol: {
type: "path",
attr:{d: "M2,2 L2,13 L8,7 L2,2", style: "stroke: none; fill: " + color + ";"}
}
}
]);
markers.enter().append("marker")
.each(function(d){
return d3.select(this).attr(d.attr)
});
var marker = markers.selectAll(".symbol").data(function(d){return [d.symbol]});
marker.enter().append(function(d) {
return document.createElement(d.type)
})
.each(function(d){
return d3.select(this).attr(d.attr)
});
return {
start: ["url(#", idS, ")"].join(""),
end: ["url(#", idE, ")"].join("")
}
};
body{margin:0; position: relative}
svg{outline:solid 1px #ccc;
overflow: visible;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinycolor/1.1.2/tinycolor.min.js"></script>
例如,如果我在 chrome devtools 中手动编辑标记元素,并删除 viewBox 属性,则标记会呈现。然后,如果我从代码中删除 viewBox 属性并重试,标记仍未呈现。然后,如果我手动添加 viewBox,则标记会呈现。
我尝试在计时器回调中添加标记,以防出现计时问题但没有任何变化。
渲染后的 HTML 看起来像这样...
<svg width="500" height="180">
<defs>
<marker id="filter-marker-start" viewBox="0 0 7 7" markerWidth="7"
markerHeight="7" refX="4" refY="4"
orient="auto">
<rect x="1" y="1" width="5" height="5"
style="stroke: none; fill: red;"></rect>
</marker>
<marker id="filter-marker-end" viewBox="0 0 13 13" markerWidth="13"
markerHeight="13" refX="2" refY="7"
orient="auto">
<path d="M2,2 L2,13 L8,7 L2,2" style="stroke: none; fill: red;"></path>
</marker>
</defs>
<ellipse class="circle" cx="250" cy="90" ry="50" rx="100" fill="steelblue"></ellipse>
<path class="arrow" d="M100,50L400,150" stroke="red"
style="marker-start: url(#filter-marker-start); marker-end: url(#filter-marker-end);">
</path>
</svg>
您不能使用 document.createElement 创建 SVG 元素,您必须使用 document.createElementNS 并提供 SVG 命名空间。
我敢肯定,如果您使用 Chrome 的开发工具检查矩形和路径元素,它会告诉您这些元素是 html 元素(在 html 命名空间中) 而不是 SVG 元素。
我已经在下面更正了您的示例:
var size = {width: 500, height: 180},
svg = d3.select("body").append("svg").attr(size),
markers = Marker(svg, "red");
var circles = svg.append("ellipse").datum({})
.attr({
class: "circle",
'cx': size.width / 2,
'cy': size.height / 2,
'ry': 50,
'rx': 100,
"fill": "steelblue"
}),
shadePath = svg.append("path")
.attr({
class: "arrow",
d: d3.svg.line()([[100,50], [400,150]]),
stroke: "red"
}).style({
"marker-start": markers.start,
"marker-end": markers.end
});
function Marker(svg, color){
var id = "filter-marker", defs = svg.selectAll("defs").data([id]),
idS = id + "-start", idE = id + "-end";
defs.enter().append("defs");
var markers = defs.selectAll("#"+id).data([
{
attr: {id: idS, viewBox: "0 0 7 7",
markerWidth: "7", markerHeight: "7",
refX: "4", refY: "4",orient: "auto"},
symbol: {
type: "rect",
attr: {x: "1", y: "1", width: "5", height: "5", style: "stroke: none; fill: " + color + ";"}
}
},
{
attr: {id: idE, viewBox: "0 0 13 13",
markerWidth: "13", markerHeight: "13",
refX: "2", refY: "7", orient: "auto"},
symbol: {
type: "path",
attr:{d: "M2,2 L2,13 L8,7 L2,2", style: "stroke: none; fill: " + color + ";"}
}
}
]);
markers.enter().append("marker")
.each(function(d){
return d3.select(this).attr(d.attr)
});
var marker = markers.selectAll(".symbol").data(function(d){return [d.symbol]});
marker.enter().append(function(d) {
return document.createElementNS("http://www.w3.org/2000/svg", d.type)
})
.each(function(d){
return d3.select(this).attr(d.attr)
});
return {
start: ["url(#", idS, ")"].join(""),
end: ["url(#", idE, ")"].join("")
}
};
body{margin:0; position: relative}
svg{outline:solid 1px #ccc;
overflow: visible;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinycolor/1.1.2/tinycolor.min.js"></script>
任何人都可以帮助我了解如何在以下示例中让标记呈现在路径上吗?
var size = {width: 500, height: 180},
svg = d3.select("body").append("svg").attr(size),
markers = Marker(svg, "red");
var circles = svg.append("ellipse").datum({})
.attr({
class: "circle",
'cx': size.width / 2,
'cy': size.height / 2,
'ry': 50,
'rx': 100,
"fill": "steelblue"
}),
shadePath = svg.append("path")
.attr({
class: "arrow",
d: d3.svg.line()([[100,50], [400,150]]),
stroke: "red"
}).style({
"marker-start": markers.start,
"marker-end": markers.end
});
function Marker(svg, color){
var id = "filter-marker", defs = svg.selectAll("defs").data([id]),
idS = id + "-start", idE = id + "-end";
defs.enter().append("defs");
var markers = defs.selectAll("#"+id).data([
{
attr: {id: idS, viewBox: "0 0 7 7",
markerWidth: "7", markerHeight: "7",
refX: "4", refY: "4",orient: "auto"},
symbol: {
type: "rect",
attr: {x: "1", y: "1", width: "5", height: "5", style: "stroke: none; fill: " + color + ";"}
}
},
{
attr: {id: idE, viewBox: "0 0 13 13",
markerWidth: "13", markerHeight: "13",
refX: "2", refY: "7", orient: "auto"},
symbol: {
type: "path",
attr:{d: "M2,2 L2,13 L8,7 L2,2", style: "stroke: none; fill: " + color + ";"}
}
}
]);
markers.enter().append("marker")
.each(function(d){
return d3.select(this).attr(d.attr)
});
var marker = markers.selectAll(".symbol").data(function(d){return [d.symbol]});
marker.enter().append(function(d) {
return document.createElement(d.type)
})
.each(function(d){
return d3.select(this).attr(d.attr)
});
return {
start: ["url(#", idS, ")"].join(""),
end: ["url(#", idE, ")"].join("")
}
};
body{margin:0; position: relative}
svg{outline:solid 1px #ccc;
overflow: visible;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinycolor/1.1.2/tinycolor.min.js"></script>
例如,如果我在 chrome devtools 中手动编辑标记元素,并删除 viewBox 属性,则标记会呈现。然后,如果我从代码中删除 viewBox 属性并重试,标记仍未呈现。然后,如果我手动添加 viewBox,则标记会呈现。
我尝试在计时器回调中添加标记,以防出现计时问题但没有任何变化。
渲染后的 HTML 看起来像这样...
<svg width="500" height="180">
<defs>
<marker id="filter-marker-start" viewBox="0 0 7 7" markerWidth="7"
markerHeight="7" refX="4" refY="4"
orient="auto">
<rect x="1" y="1" width="5" height="5"
style="stroke: none; fill: red;"></rect>
</marker>
<marker id="filter-marker-end" viewBox="0 0 13 13" markerWidth="13"
markerHeight="13" refX="2" refY="7"
orient="auto">
<path d="M2,2 L2,13 L8,7 L2,2" style="stroke: none; fill: red;"></path>
</marker>
</defs>
<ellipse class="circle" cx="250" cy="90" ry="50" rx="100" fill="steelblue"></ellipse>
<path class="arrow" d="M100,50L400,150" stroke="red"
style="marker-start: url(#filter-marker-start); marker-end: url(#filter-marker-end);">
</path>
</svg>
您不能使用 document.createElement 创建 SVG 元素,您必须使用 document.createElementNS 并提供 SVG 命名空间。
我敢肯定,如果您使用 Chrome 的开发工具检查矩形和路径元素,它会告诉您这些元素是 html 元素(在 html 命名空间中) 而不是 SVG 元素。
我已经在下面更正了您的示例:
var size = {width: 500, height: 180},
svg = d3.select("body").append("svg").attr(size),
markers = Marker(svg, "red");
var circles = svg.append("ellipse").datum({})
.attr({
class: "circle",
'cx': size.width / 2,
'cy': size.height / 2,
'ry': 50,
'rx': 100,
"fill": "steelblue"
}),
shadePath = svg.append("path")
.attr({
class: "arrow",
d: d3.svg.line()([[100,50], [400,150]]),
stroke: "red"
}).style({
"marker-start": markers.start,
"marker-end": markers.end
});
function Marker(svg, color){
var id = "filter-marker", defs = svg.selectAll("defs").data([id]),
idS = id + "-start", idE = id + "-end";
defs.enter().append("defs");
var markers = defs.selectAll("#"+id).data([
{
attr: {id: idS, viewBox: "0 0 7 7",
markerWidth: "7", markerHeight: "7",
refX: "4", refY: "4",orient: "auto"},
symbol: {
type: "rect",
attr: {x: "1", y: "1", width: "5", height: "5", style: "stroke: none; fill: " + color + ";"}
}
},
{
attr: {id: idE, viewBox: "0 0 13 13",
markerWidth: "13", markerHeight: "13",
refX: "2", refY: "7", orient: "auto"},
symbol: {
type: "path",
attr:{d: "M2,2 L2,13 L8,7 L2,2", style: "stroke: none; fill: " + color + ";"}
}
}
]);
markers.enter().append("marker")
.each(function(d){
return d3.select(this).attr(d.attr)
});
var marker = markers.selectAll(".symbol").data(function(d){return [d.symbol]});
marker.enter().append(function(d) {
return document.createElementNS("http://www.w3.org/2000/svg", d.type)
})
.each(function(d){
return d3.select(this).attr(d.attr)
});
return {
start: ["url(#", idS, ")"].join(""),
end: ["url(#", idE, ")"].join("")
}
};
body{margin:0; position: relative}
svg{outline:solid 1px #ccc;
overflow: visible;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinycolor/1.1.2/tinycolor.min.js"></script>