缩放导致图形超出绘图区域边界

时间:2017-05-15 13:54:21

标签: javascript d3.js svg

我的图表存在问题。当我缩放时,线条越过画布区域的边缘并越过x / y轴。我尝试添加一个clippath,但似乎没有用。如果我在调试器中检查DOM,我可以看到clippath矩形正好位于它需要的位置。

//The canvasGroup is the area between the axis
var clipGroup = canvasGroup.append("clipPath")
                .attr("id", "canvasGroup-clipPath");

var clipRect = clipGroup.append("rect")
                .attr("width", width)
                .attr("height", height);            

//Function that does the zooming
function doZoom() 
{   
    paths.forEach(function(path)
    {               
        path.attr("transform", d3.event.transform);
    });

    gX.call(xAxis.scale(d3.event.transform.rescaleX(xScale)));
    gY.call(yAxis.scale(d3.event.transform.rescaleY(yScale)));
}   

var zoom = d3.zoom()
            .scaleExtent([1, 5])
            .translateExtent([[0, 0], [width, height]])
            .on("zoom", doZoom);

//Register the event listener             
canvasGroup.call(zoom);     

//now loop over the data sets and plot each one
//For brevity, I'm skipping the loop and only showing the call to create the line
var path = canvasGroup.append("path")
            .attr("clip-path", "url(#canvasGroup-clipPath)")    
            .attr("fill", "steelblue")                  
            .attr("class", "line")
            .attr("id", lineId + "-line")
            .style("stroke", lineColor)
            .style("stroke-width", 1)   
            .style("fill", "none");                     

paths.push(path);
path.attr("d", function(d) { return plotline(i)});

这是它的外观。 放大之前: Plot before zoom 缩放后:After zoom plot overlaps the Y axis

1 个答案:

答案 0 :(得分:3)

问题是由在表示数据的路径上设置剪切路径引起的。在应用剪切路径时,浏览器需要决定哪个坐标系应该用于<clipPath>元素的内容。这由clipPathUnits属性控制,默认为userSpaceOnUse

  

<强> userSpaceOnUse
  <clippath>元素的内容表示引用<clippath>元素时当前用户坐标系中的值(即,引用<clippath>的元素的用户坐标系元素通过clip-path属性)。

在转换doZoom()函数中的路径时,实际上是在为路径建立一个新的坐标系。并且,除了绘制路径本身之外,该坐标系还将用于计算剪切路径的位置和尺寸。因此,通过根据缩放行为变换路径,您将相同的变换应用于剪切路径,从而将其移离所需位置。

虽然很有可能将clipPathUnits属性设置为其他有效值objectBoundingBox,但这很可能不是您想要的情况,因为它会使问题更加复杂。设置此值时,<clipPath>的内容的位置和长度需要指定为边界框的fractions

了解这一切,有一个更简单的解决方案!您只需将clip-path应用于在缩放期间不会变换的元素,例如。一个父组。鉴于您提供的代码不完整,通过将剪切路径设置为canvasGroup

,这可能非常有效
// Set the clipping path on the parent group.
canvasGroup.attr("clip-path", "url(#canvasGroup-clipPath)")    

// Append the path to the group as before.
var path = canvasGroup.append("path")
               .attr("fill", "steelblue")                  
               .attr("class", "line")
               // ...