【问题标题】:SVG markers not renderingSVG 标记不渲染
【发布时间】:2015-10-01 10:01:34
【问题描述】:

谁能帮我理解如何让标记在以下示例中呈现在路径上?

    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>

【问题讨论】:

    标签: svg marker


    【解决方案1】:

    您不能使用 document.createElement 创建 SVG 元素,您必须使用 document.createElementNS 并提供 SVG 命名空间。

    我敢肯定,如果您使用 Chrome 的开发工具检查 rect 和 path 元素,它会告诉您这些元素是 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>

    【讨论】:

    • 太棒了!如果我可以勾选一百万次,我会的。嗯……那是我再也见不到的 6 个小时。
    猜你喜欢
    • 2021-06-24
    • 1970-01-01
    • 2021-12-22
    • 2021-06-04
    • 1970-01-01
    • 1970-01-01
    • 2017-04-05
    • 2019-01-05
    • 1970-01-01
    相关资源
    最近更新 更多