在分组条形图中缩放时如何剪切矩形外的区域

D3.js-how to clip area outside rectangle while zooming in a grouped bar chart

本文关键字:何剪切 区域 条形图 缩放      更新时间:2023-09-26

这是我的代码http://jsfiddle.net/qkHK6/2174/的链接。我想隐藏或剪辑矩形外部的区域。你可以从我的视图中看到,当缩放的时候,条形线会移动到y轴的左边,所以我想剪辑那个区域。请谁来帮帮我。

var margin = {
    top: 20,
    right: 20,
    bottom: 30,
    left: 40
  },
  width = 300 - margin.left - margin.right,
  height = 400 - margin.top - margin.bottom;
//Data used for bar chart
var data = [{
  "State": "CA",
  "Under 5 Years": 2704659,
  "5 to 13 Years": 4499890,
  "14 to 17 Years": 2159981,
  "18 to 24 Years": 3853788,
  "25 to 44 Years": 10604510,
  "45 to 64 Years": 8819342,
  "65 Years and Over": 4114496
}, {
  "State": "TX",
  "Under 5 Years": 2027307,
  "5 to 13 Years": 3277946,
  "14 to 17 Years": 1420518,
  "18 to 24 Years": 2454721,
  "25 to 44 Years": 7017731,
  "45 to 64 Years": 5656528,
  "65 Years and Over": 2472223
}, {
  "State": "NY",
  "Under 5 Years": 1208495,
  "5 to 13 Years": 2141490,
  "14 to 17 Years": 1058031,
  "18 to 24 Years": 1999120,
  "25 to 44 Years": 5355235,
  "45 to 64 Years": 5120254,
  "65 Years and Over": 2607672
}, {
  "State": "FL",
  "Under 5 Years": 1140516,
  "5 to 13 Years": 1938695,
  "14 to 17 Years": 925060,
  "18 to 24 Years": 1607297,
  "25 to 44 Years": 4782119,
  "45 to 64 Years": 4746856,
  "65 Years and Over": 3187797
}, {
  "State": "IL",
  "Under 5 Years": 894368,
  "5 to 13 Years": 1558919,
  "14 to 17 Years": 725973,
  "18 to 24 Years": 1311479,
  "25 to 44 Years": 3596343,
  "45 to 64 Years": 3239173,
  "65 Years and Over": 1575308
}, {
  "State": "PA",
  "Under 5 Years": 737462,
  "5 to 13 Years": 1345341,
  "14 to 17 Years": 679201,
  "18 to 24 Years": 1203944,
  "25 to 44 Years": 3157759,
  "45 to 64 Years": 3414001,
  "65 Years and Over": 1910571
}];
var x0 = d3.scale.ordinal()
  .rangeRoundBands([0, width], .1);
var x1 = d3.scale.ordinal();
var y = d3.scale.linear()
  .range([height, 0]);

不同年龄使用的颜色

 var color = d3.scale.ordinal()
    .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c",   "#ff8c00"]);

 creating axis and bar graph

var xAxis = d3.svg.axis().scale (x0).orient("底部");

var yAxis = d3.svg.axis()
  .scale(y)
  .orient("left")
  .tickFormat(d3.format(".1s"));
var svg = d3.select("#chart").append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
  .call(d3.behavior.zoom().scaleExtent([1, 10]).on("zoom", zoom));
//d3.csv("data.csv", function(error, data) {
var ageNames = d3.keys(data[0]).filter(function(key) {
  return key !== "State";
});
console.log("ageNames=" + JSON.stringify(ageNames));
data.forEach(function(d) {
  d.ages = ageNames.map(function(name) {
    return {
      name: name,
      value: +d[name]
    };
  });
  console.log("d.ages=" + JSON.stringify(d.ages));
});
x0.domain(data.map(function(d) {
  return d.State;
}));
x1.domain(ageNames).rangeRoundBands([0, x0.rangeBand()]);
y.domain([0, d3.max(data, function(d) {
  console.log(" before retuen d.ages=" + d.ages);
  return d3.max(d.ages, function(d) {
    console.log("d.value;=" + d.value);
    return d.value;
  });
})]);
svg.append("g")
  .attr("class", "x axis")
  .attr("transform", "translate(0," + height + ")")
  .call(xAxis);
svg.append("g")
  .attr("class", "y axis")
  .call(yAxis)
  .append("text")
  .attr("transform", "rotate(-90)")
  .attr("y", 6)
  .attr("dy", ".5em")
  .style("text-anchor", "end")
  .text("Population");
var allStates = svg.append("g")
  .attr("class", "allStates");

var state = allStates.selectAll(".state")
  .data(data)
  .enter().append("g")
  .attr("class", "state")
  .attr("transform", function(d) {
    return "translate(" + x0(d.State) + ",0)";
  });
state.selectAll("rect")
  .data(function(d) {
    return d.ages;
  })
  .enter().append("rect")
  .attr("width", x1.rangeBand())
  .attr("x", function(d) {
    return x1(d.name);
  })
  .attr("y", function(d) {
    return y(d.value);
  })
  .attr("height", function(d) {
    return height - y(d.value);
  })
  .style("fill", function(d) {
    return color(d.name);
  });
var legnColorGap = height / 17.5;
var legend = svg.selectAll(".legend")
  .data(ageNames.slice().reverse())
  .enter().append("g")
  .attr("class", "legend")
  .attr("transform", function(d, i) {
    return "translate(0," + i * legnColorGap + ")";
  });
var lwidth = width / 75,
  lht = height / 22,
  lwidth1 = lwidth + 2;
legend.append("rect")
  .attr("x", width - lwidth1)
  .attr("width", lwidth)
  .attr("height", lht)
  .style("fill", color);
var textht = lht / 2,
  textwd = textht + lwidth;
legend.append("text")
  .attr("x", width - textwd)
  .attr("y", textht)
  .attr("dy", ".35em")
  .style("text-anchor", "end")
  .text(function(d) {
    return d;
  });

  //Zooming Function 
function zoom() {
  svg.select(".allStates").attr("transform", "translate(" + d3.event.translate[0] + ",0)scale(" + d3.event.scale + ",1)");
  svg.select(".x.axis").attr("transform", "translate(" + d3.event.translate[0] + "," + (height) + ")").call(xAxis.scale(x0.rangeRoundBands([0, width * d3.event.scale], .5 * d3.event.scale)));
  svg.select(".y.axis").call(yAxis);
}

更新后的jsfield

这归结为一些修改。首先,您需要了解SVG clip-path,这是一种定义SVG形状的方法,该形状可以屏蔽或裁剪另一个形状(在本例中是您的图表)。如链接文档中所示,clip-path需要一个<defs>元素,其中包含一个<clipPath>。在您的例子中,<clipPath>需要包含<rect>,其边界被设置为覆盖可见区域。

为了创建<defs>,我添加了:

var mask = svg.append("defs")
  .append("clipPath")
  .attr("id", "mask")
  .style("pointer-events", "none")
    .append("rect")
    .attr({
      x: 0,
      y: 0,
      width: width,
      height: height + margin.bottom,
    })
最后,要使用上面的蒙版裁剪图表,需要调用
.attr("clip-path", "url(#mask)")

被遮罩的东西

你设置东西的方式是,没有一个SVG <g>包含两个需要蒙版的东西(即图表和x轴)。所以我添加了<g>,并重新洗牌,以便将轴和图表(allStates)添加到其中:

var masked = svg.append("g")
  .attr("clip-path", "url(#mask)")
masked.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);
var allStates = masked
  .append("g")
    .attr("class", "allStates");

怎么样?

function zoom() {
svg.select(".allStates").attr("transform", "translate(" + d3.event.translate[0] + ",0)scale(" + d3.event.scale + ",1)");
svg.select(".x.axis").attr("transform", "translate(" + d3.event.translate[0] + "," + (height) + ")").call(xAxis.scale(x0.rangeRoundBands([0, width * d3.event.scale], .5 * d3.event.scale)));
//svg.select(".y.axis").call(yAxis);
svg.select(".y.axis").attr("transform", "translate(" + (d3.event.translate[0]-d3.event.scale) + ", 0)")
}

我只是添加了最后一行,以便在缩放时将Y轴向左移动。