11

I have a simple graph with x and y axes. I don't want the drawing area I draw within to overlap the axes.

I'm using d3 to create my chart but the clip-path does not work:

http://jsfiddle.net/EqLBJ/

var margin = {top: 19.5, right: 19.5, bottom: 19.5, left: 39.5},
    width = 960 - margin.right,
    height = 500 - margin.top - margin.bottom;

var xScale = d3.scale.linear().
    domain([xMin, xMax]). // your data minimum and maximum
    range([0, width]); // the pixels to map to, e.g., the width of the diagram.

var yScale = d3.scale.linear().
    domain([yMax, yMin]). 
    range([0, height]); 

var xAxis = d3.svg.axis().orient("bottom").scale(xScale).ticks(10, d3.format(",d")),
    yAxis = d3.svg.axis().orient("left").scale(yScale);


var chart = d3.select("#chart").append("svg")
    .attr("class", "chart")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .attr("pointer-events", "all")
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
    .call(d3.behavior.zoom().scaleExtent([0.2, 5]).on("zoom", redraw));


var rect = chart.append('svg:rect')
    .attr('width', width)
    .attr('height', height)
    .attr('fill', 'white');


var line = d3.svg.line()
        .interpolate("basis")
        .x(function(d, i) { return xScale(d.time); })
        .y(function(d) { return yScale(d.value); });

var clip = chart.append("svg:clipPath")
    .attr("id", "clip");

clip.append("svg:rect")
    .attr("id", "clip-rect")
    .attr("width", width)
    .attr("height", height);
    // .attr("fill", "white");

var path = chart.append("svg:path")
    .attr("clip-path", "url(#clip-rect)")
    .data([data])
    .attr("class", "line")
    .attr("fill", "none")
    .attr("stroke", "maroon")
    .attr("stroke-width", 2)
    .attr("d", line);

// x-axis label
chart.append("text")
    .attr("class", "x label")
    .attr("text-anchor", "end")
    .attr("x", width)
    .attr("y", height - 6)
    .text("time");

// y-axis label
chart.append("text")
    .attr("class", "y label")
    .attr("text-anchor", "end")
    .attr("y", 6)
    .attr("dy", ".75em")
    .attr("transform", "rotate(-90)")
    .text("value");

// x-axis
var xaxis = chart.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);

// y-axis
var yaxis = chart.append("g")
    .attr("class", "y axis")
    .call(yAxis);



function redraw() 
{
    console.log("here", d3.event.translate, d3.event.scale);

    path.transition()       
        .ease("linear")
        .attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")");

}
dsummersl
  • 6,588
  • 50
  • 65
Victor Parmar
  • 5,719
  • 6
  • 33
  • 36

1 Answers1

27

You want something like this:

http://jsfiddle.net/dsummersl/EqLBJ/1/

Specifically:

  • use 'clip' instead of 'clip-rect'
  • put the content you wish to clip inside a 'g' element, and specify the 'clip-path' attribute and the transforms for the 'g' element.
dsummersl
  • 6,588
  • 50
  • 65
  • A clip-path cannot legally point to a element per http://www.w3.org/TR/SVG/masking.html#EstablishingANewClippingPath – Robert Longson May 07 '12 at 21:04
  • 3
    I'm not sure what you're referring to. According to the definition of the `clip-path` attribute, it is applicable to container elements, which the `` tag happens to be a member of. See: http://www.w3.org/TR/SVG/masking.html#ClipPathProperty -- besides which, my example works so... – dsummersl May 08 '12 at 02:42
  • 2
    I was unsuccessfully trying to make clear that a while a clip-path attribute can exist on a element, the xlink:href of a clip-path cannot point to a element. – Robert Longson May 08 '12 at 08:24
  • Ah...you mean a 'clip-path' must reference a 'clipPath', otherwise it is ignored? – dsummersl May 08 '12 at 11:55
  • 1
    Yes, although I stated it rather badly, and the clipPath can't contain elements. – Robert Longson May 08 '12 at 14:01
  • We've both been guilty of poor descriptions I'd say! Anyway...in his example code the 'clip-path' references the id of the 'rect' element rather than the parent 'clippath' element, which was half the problem. – dsummersl May 08 '12 at 14:06
  • Ah so basically what I was missing was that the clipPath needed to be inside a defs element. Also I don't think that the path necessarily needs to be within a g for the clip-path to apply as pretty much all the examples that I've seen don't adhere to that (maybe bad practice?). Anyways thanks a lot snoop! – Victor Parmar May 08 '12 at 17:49
  • I wanted axis to be displayed. I found that they blocked the zoom behaviour. Assigning the axis to the chart before defining the chartBody resolved this issue. I also added attr("fill-opacity",0) to the last chartBody.append("svg:rect") to allow the axis to be displayed. – Emile Sep 12 '12 at 11:05
  • Just wanted to point out that the "defs" element isn't necessary. Or the "clip-rect" id on the svg:rect. – ari gold Nov 26 '13 at 00:35
  • how can the axis change accordingly? – Bargitta Jun 27 '16 at 10:08