首页 > 解决方案 > 使用 d3.drag 时,剪辑路径与元素组一起移动

问题描述

我正在尝试在剪切路径上拖动一组形状。第一次,它工作得很好,但是一旦我开始拖动,剪辑就根本不起作用。

这是我的工作代码;

var svg = d3.select("svg");

// draw a circle
    svg.append("clipPath")       // define a clip path
    	.attr("id", "clip") // give the clipPath an ID
      .append("circle")            // shape it as an ellipse
    	.attr("cx", 100)            // position the x-centre
    	.attr("cy", 80)            // position the y-centre
    	.attr("r", 80)            // set the x radius
			.attr("fill", "red")


		var g = svg.append("g")
				.datum({x:0, y:0})
				.attr("transform", function(d) { return 'translate(' + d.x + ' '+ d.y + ')'; })
				.attr("clip-path","url(#clip)")
				.call(d3.drag()
            .on("start", function(d){
							d3.select(this).raise().classed("active", true);
						})
            .on("drag", function(d){
							d3.select(this).attr("transform","translate(" + (d3.event.x) + "," + (d3.event.y) + ")" );
						})
            .on("end", function(d){
							d3.select(this).classed("active", false);
						}));


    g.append("rect")
    	.attr("x",100)
    	.attr("y",80)
    	.attr("height",100)
    	.attr("width",200)

			g.append("line")
				.attr("x1", 100)
				.attr("y1", 80)
				.attr("x2", 200)
				.attr("y2", 80)
				.style("stroke", "purple")
				.style("stroke-width", 12)
.svgClass{
border:2px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js"></script>
        <svg width="500" height="300" class="svgClass"></svg>

您可以在拖动时看到,第一次剪裁的形状一直在移动。没有进一步的剪辑。

为了方便起见,我再次重绘了外圈。检查此代码;

var svg = d3.select("svg");

    // draw a circle
        svg.append("clipPath")       // define a clip path
        	.attr("id", "clip") // give the clipPath an ID
          .append("circle")            // shape it as an ellipse
        	.attr("cx", 100)            // position the x-centre
        	.attr("cy", 80)            // position the y-centre
        	.attr("r", 80)            // set the x radius
    			.attr("fill", "red")
          
          // redraw circle to make it easy
          
          svg.append("circle")            // shape it as an ellipse
        	.attr("cx", 100)            // position the x-centre
        	.attr("cy", 80)            // position the y-centre
        	.attr("r", 80)            // set the x radius
    			.attr("fill", "red")


    		var g = svg.append("g")
    				.datum({x:0, y:0})
    				.attr("transform", function(d) { return 'translate(' + d.x + ' '+ d.y + ')'; })
    				.attr("clip-path","url(#clip)")
    				.call(d3.drag()
                .on("start", function(d){
    							d3.select(this).raise().classed("active", true);
    						})
                .on("drag", function(d){
    							d3.select(this).attr("transform","translate(" + (d3.event.x) + "," + (d3.event.y) + ")" );
    						})
                .on("end", function(d){
    							d3.select(this).classed("active", false);
    						}));


        g.append("rect")
        	.attr("x",100)
        	.attr("y",80)
        	.attr("height",100)
        	.attr("width",200)

    			g.append("line")
    				.attr("x1", 100)
    				.attr("y1", 80)
    				.attr("x2", 200)
    				.attr("y2", 80)
    				.style("stroke", "purple")
    				.style("stroke-width", 12)
.svgClass{
border:2px solid red;
}
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js"></script>
        <svg width="500" height="300" class="svgClass"></svg>

在这里您可以看到剪辑根本不起作用。我想将此拖动限制在圆圈内,如果超出剪辑边界,它应该相应地剪辑它。

谁能帮我解决这个要求?或者让我知道我在哪里做错了。

标签: javascripthtmlcssd3.js

解决方案


g拖动回调正在转换已应用剪辑路径的相同元素。这意味着g元素的剪辑路径也在被变换,这就是为什么当你拖动你的形状时剪辑的形状会四处移动。

下面的代码片段使用灰色矩形显示剪辑路径定义,使用粉色矩形显示转换后g元素的区域。圆圈保持原始剪辑形状,因为g元素的剪辑路径正在与元素的其余部分一起平移。

<svg width="300" height="300">
  <clipPath id="cut">
    <rect width="100" height="100" x="100" y="50"></rect>
  </clipPath>
    
  <rect x="100" y="50" width="100" height="100" fill="#eee"></rect>
    
  <g clip-path="url(#cut)" transform="translate(50, 50)">
    <rect x="100" y="50" width="100" height="100" fill="pink"></rect>
    <circle       
      class="consumption"
      cx="100" 
      cy="100" 
      r="50">
    </circle>
  </g>
</svg>

在下面的代码片段中,剪辑路径应用于外部g元素(未翻译并且与原始剪辑路径定义具有相同的坐标),而转换应用于内部g元素。

<svg width="300" height="300">
  <clipPath id="cut">
    <rect width="100" height="100" x="100" y="50"></rect>
  </clipPath>
    
  <rect x="100" y="50" width="100" height="100" fill="#eee"></rect>
    
  <g clip-path="url(#cut)">
    <rect x="100" y="50" width="100" height="100" fill="pink"></rect>
      
    <g transform="translate(100, 50)">
      <circle       
        class="consumption"
        cx="100" 
        cy="100" 
        r="50">
      </circle>
    </g>
  </g>
</svg>

因此,如示例中所示,您应该将剪辑路径应用于外部g元素,同时转换内部g元素。


推荐阅读