【问题标题】:Simple way to use existing object as a clipping path?使用现有对象作为剪切路径的简单方法?
【发布时间】:2014-05-16 02:15:03
【问题描述】:

我有以下简单的例子,当线条延伸到矩形之外时,我想剪掉它。我已经将矩形用作轮廓,将同一矩形用作剪切路径的简单方法是什么?我目前使用id 的方法被忽略了。这个相关的question 有一个答案,但它需要单独创建剪辑区域。我想重复使用我的信息,而不是重复几乎相同的信息。

<!DOCTYPE html>
<meta charset="utf-8">

<body>
<script src = "http://d3js.org/d3.v3.min.js"> </script>
<script>

var margin = {top: 100, right: 20, bottom: 20, left: 20},
    width = 600 - margin.left - margin.right,
    height = 270 - margin.top - margin.bottom;

var xdata = d3.range(0, 20);
var ydata = [1, 4, 5, 9, 10, 14, 15, 15, 11, 10, 5, 5, 4, 8, 7, 5, 5, 5, 8, 10];


var xy = []; // start empty, add each element one at a time
for(var i = 0; i < xdata.length; i++ ) {
   xy.push({x: xdata[i], y: ydata[i]});
}

var xscl = d3.scale.linear()
    .domain(d3.extent(xy, function(d) {return d.x;})) //use just the x part
    .range([margin.left, width + margin.left])

var yscl = d3.scale.linear()
    .domain([1, 8]) // use just the y part
    .range([height + margin.top, margin.top])

var slice = d3.svg.line()
  .x(function(d) { return xscl(d.x);}) // apply the x scale to the x data
  .y(function(d) { return yscl(d.y);}) // apply the y scale to the y data

var svg = d3.select("body")
    .append("svg")

svg.append('rect') // outline for reference
    .attr({x: margin.left, y: margin.top,
           width: width,
           height: height,
           id: "xSliceBox",
           stroke: 'black',
           'stroke-width': 0.5,
           fill:'white'});

svg.append("path")
    .attr("class", "line")
    .attr("d", slice(xy))
    .attr("clip-path", "#xSliceBox")
    .style("fill", "none")
    .style("stroke", "red")
    .style("stroke-width", 2);

</script>
</body>

【问题讨论】:

    标签: javascript svg d3.js


    【解决方案1】:

    你不能直接在clip-path属性中引用矩形,你需要创建一个&lt;clipPath&gt;元素。然后,在&lt;clipPath&gt; 元素内,您可以使用&lt;use&gt; 元素来引用矩形。

    (是的,您认为它应该是迂回且复杂的,但这就是 SVG 规范的定义。)

    使用您的代码:

    var svg = d3.select("body")
        .append("svg")
    
    var clip = svg.append("defs").append("clipPath")
       .attr("id", "clipBox");
    
    svg.append('rect') // outline for reference
        .attr({x: margin.left, y: margin.top,
               width: width,
               height: height,
               id: "xSliceBox",
               stroke: 'black',
               'stroke-width': 0.5,
               fill:'white'});
    
    clip.append("use").attr("xlink:href", "#xSliceBox");
    
    svg.append("path")
        .attr("class", "line")
        .attr("d", slice(xy))
        .attr("clip-path", "url(#clipBox)") //CORRECTION
        .style("fill", "none")
        .style("stroke", "red")
        .style("stroke-width", 2);
    

    您也可以反过来做,在clipPath 元素中定义矩形,然后使用&lt;use&gt; 元素将其实际绘制到屏幕上。无论哪种方式,您都希望只定义一次矩形,这样如果您决定更改它,您只需在一个地方进行,另一个将更新以匹配。

    【讨论】:

    • 感谢您的简洁明了的解释。但是,当我尝试时,没有剪辑。没有抛出错误,当我查看页面元素时,一切似乎都已正确定义。也许还需要一些东西?
    • 我一定遗漏了一些基本的东西,因为我硬连线了clipPath,但它仍然不起作用。我需要指出xlink 的一些定义吗?我在其他答案中看到了这一点。
    • 抱歉,几天前我没有收到您的评论。如果您的 svg 是独立的,则需要声明 xlink 命名空间,但如果它嵌入在 html5 文档中,则可以跳过它(html5 解析器无论如何都会忽略命名空间)。问题在于clip-path 属性的定义方式——尽管我们将clip-path 添加为表示属性,但它同样可以添加为样式属性,并且与所有其他样式属性一样,它使用CSS @ 987654333@ 语法。
    • SVG中的一般规则:如果属性有xlink前缀,你可以只使用裸片段,比如.attr("xlink:href", "#xSliceBox");。当您为其他属性引用文件片段时,您需要将其包装在 url 函数中,例如 .attr("clip-path", "url(#clipBox)")。使用函数符号的其他属性是过滤器、填充或描边(当引用渐变或图案时)或线标记。所有这些属性也可以在 CSS 中声明,因此它们使用 CSS 格式。再次抱歉,我之前没有发现错误。上面的代码已经更正了。
    • 问题是剪辑路径被应用之前翻译。 (或者从技术上讲,它的应用就像矩形是在路径的新坐标系中绘制的一样;如果您删除 transform 属性,您会看到没有被剪裁的一小段线是矩形内唯一的部分.) 我不确定您在代码中进行了哪些更改以要求额外的翻译,但一个简单的解决方案是将路径放在一个组中并将 clip-path 属性放在&lt;g&gt;;这样,路径将在移动到位后被剪裁。 jsfiddle.net/Ewb8X/1
    猜你喜欢
    • 2012-03-14
    • 1970-01-01
    • 1970-01-01
    • 2015-05-31
    • 1970-01-01
    • 1970-01-01
    • 2013-07-23
    • 1970-01-01
    相关资源
    最近更新 更多