如何限制缩放以防止缩放轴?

时间:2019-01-15 22:24:46

标签: d3.js svg

我尝试过尝试缩放范围,但无法防止不必要的行为。有什么建议吗?

  var zoom = d3.zoom()
       .scaleExtent([1, 500])
       .translateExtent([[0, 0], [width, height]])
       .extent([[0, 0], [2000, height]])
       .on("zoom", zoomed);

请参见示例https://jsfiddle.net/sjp700/v1986fkt/或github上的项目

https://github.com/Steve-Pegg/Visual-Planning-Tool

谢谢

1 个答案:

答案 0 :(得分:0)

这里最简单,最常见的解决方案是使用clipPath

首先,添加<clipPath>元素:

var clip = svg.append("clipPath")
    .attr("id", "clip")
    .append("rect")
    .attr("width", graphW)
    .attr("height", graphH);

在不包含轴的<g>元素内绘制矩形非常方便:因此,只需在该选择中引用<clipPath>

var g = svg.append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
    .attr("clip-path", "url(#clip)");

这是您所做的更改的代码:

 var flatDatar = [{
     group: "group1",
     label: "label1",
     start: "2018-09-01",
     finish: "2018-10-01",
     timeRange: "",
     val: "Func 1",
     labelVal: "A",
     description: "Activity 1",
     clas: "x1"
   },
   {
     group: "group1",
     label: "label2",
     start: "2018-07-01",
     finish: "2018-08-01",
     timeRange: "",
     val: "Func 2",
     labelVal: "B",
     description: "Activity 2",
     clas: "x2"
   },
   {
     group: "group1",
     label: "label3",
     start: "2018-01-01",
     finish: "2018-02-01",
     timeRange: "",
     val: "Func 1",
     labelVal: "A",
     description: "Activity 3",
     clas: "x3"
   },
   {
     group: "group1",
     label: "label4",
     start: "2018-04-01",
     finish: "2018-06-01",
     timeRange: "",
     val: "Func 2",
     labelVal: "A",
     description: "Activity 4",
     clas: "x4"
   },
   {
     group: "group1",
     label: "label5",
     start: "2018-11-01",
     finish: "2018-12-01",
     timeRange: "",
     val: "Func 3",
     labelVal: "A",
     description: "Activity 5",
     clas: "x5"
   },
   {
     group: "group2",
     label: "label6",
     start: "2018-01-01",
     finish: "2018-02-01",
     timeRange: "",
     val: "Func 4",
     labelVal: "C",
     description: "Activity 6",
     clas: "x6"
   },
   {
     group: "group2",
     label: "label7",
     start: "2018-03-27",
     finish: "2018-04-01",
     timeRange: "",
     val: "Func 5",
     labelVal: "A",
     description: "Activity 7",
     clas: "x7"
   },
   {
     group: "group2",
     label: "label8",
     start: "2018-05-01",
     finish: "2018-07-01",
     timeRange: "",
     val: "Func 4",
     labelVal: "E",
     description: "Activity 8",
     clas: "x8"
   },
   {
     group: "group2",
     label: "label9",
     start: "2018-09-01",
     finish: "2018-10-01",
     timeRange: "",
     val: "Func 2",
     labelVal: "A",
     description: "Activity 9",
     clas: "x9"
   },
   {
     group: "group2",
     label: "label10",
     start: "2018-11-01",
     finish: "2018-12-01",
     timeRange: "",
     val: "Func 3",
     labelVal: "B",
     description: "Activity 10",
     clas: "x10"
   },
   {
     group: "group2",
     label: "label11",
     start: "2018-06-01",
     finish: "2018-07-01",
     timeRange: "",
     val: "Func 5",
     labelVal: "C",
     description: "Activity 11",
     clas: "x11"
   },
   {
     group: "group3",
     label: "label12",
     start: "2018-08-01",
     finish: "2018-09-01",
     timeRange: "",
     val: "Func 4",
     labelVal: "D",
     description: "Activity 12",
     clas: "x12"
   },
   {
     group: "group3",
     label: "label13",
     start: "2018-10-01",
     finish: "2018-11-01",
     timeRange: "",
     val: "Func 2",
     labelVal: "E",
     description: "Activity 13",
     clas: "x13"
   },
   {
     group: "group3",
     label: "label14",
     start: "2018-07-01",
     finish: "2018-08-01",
     timeRange: "",
     val: "Func 5",
     labelVal: "F",
     description: "Activity 14",
     clas: "x14"
   },
   {
     group: "group3",
     label: "label15",
     start: "2018-02-01",
     finish: "2018-04-01",
     timeRange: "",
     val: "Func 4",
     labelVal: "D",
     description: "Activity 12",
     clas: "x15"
   },
   {
     group: "group3",
     label: "label16",
     start: "2018-10-01",
     finish: "2019-01-01",
     timeRange: "",
     val: "Func 2",
     labelVal: "E",
     description: "Activity 13",
     clas: "x16"
   },
   {
     group: "group3",
     label: "label17",
     start: "2019-03-01",
     finish: "2019-05-01",
     timeRange: "",
     val: "Func 5",
     labelVal: "F",
     description: "Activity 14",
     clas: "x17"
   }
 ];




 var flatData = [{
     group: "group1",
     label: "label1",
     start: "2018-09-01",
     finish: "2018-10-01",
     timeRange: "",
     val: "Func 1",
     labelVal: "A",
     lines: ["label1", "label2", "label3", "label4", "label5"],
     description: "Activity 1",
     cost: 1000
   },
   {
     group: "group2",
     label: "label6",
     start: "2018-01-01",
     finish: "2018-02-01",
     timeRange: "",
     val: "Func 4",
     labelVal: "C",
     lines: ["label6", "label7", "label8", "label9", "label10", "label11"],
     description: "Activity 6",
     cost: 1000
   },
   {
     group: "group3",
     label: "label12",
     start: "2018-07-01",
     finish: "2018-08-01",
     timeRange: "",
     val: "Func 5",
     labelVal: "F",
     lines: ["label12", "label13", "label14", "label15", "label16", "label17"],
     description: "Activity 14"
   }
 ];

 var timeParse = d3.timeParse("%Y-%m-%d");

 for (var i = 0, ilen = flatDatar.length; i < ilen; i++) {
   flatDatar[i].start = timeParse(flatDatar[i].start)
   flatDatar[i].finish = timeParse(flatDatar[i].finish)
 };

 var width = 1000,
   height = 600,
   graphW = 1000,
   xTickFormat = {},
   graphH = 600,
   nLines = flatDatar.length,
   minLabelFont = 10,
   maxLineHeight = 13,
   maxHeight = 640

 var margin = {
   top: 26,
   right: 100,
   bottom: 30,
   left: 90
 }

 graphW = width - margin.left - margin.right;
 graphH = d3.min([nLines * maxLineHeight, maxHeight - margin.top - margin.bottom]);
 height = graphH + margin.top + margin.bottom;

 var labels = getlabels()

 function getlabels() {

   var labels = [];

   var _loop4 = function _loop4(i, len) {
     labels = labels.concat(flatData[i].lines.map(function(d) {
       return flatData[i].group + '+&+' + d;
     }));
   };

   for (var i = 0, len = flatData.length; i < len; i++) {
     _loop4(i, len);
   }

   labels = labels.filter((v, i, a) => a.indexOf(v) === i);

   return labels
 }

 var border = 1;
 var bordercolor = 'black';

 var svg = d3.select("body")
   .append("svg")
   .attr("border", border)
   .attr("width", width)
   .attr("height", height);

 var clip = svg.append("clipPath")
   .attr("id", "clip")
   .append("rect")
   .attr("width", graphW)
   .attr("height", graphH);

 var borderPath = svg.append("rect")
   .attr("x", 0)
   .attr("y", 0)
   .attr("height", height)
   .attr("width", width)
   .style("stroke", bordercolor)
   .style("fill", "none")
   .style("stroke-width", border);

 svg.transition().duration(100).attr('width', width).attr('height', height);

 var g = svg.append("g")
   .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
   .attr("clip-path", "url(#clip)");


 var yScale = d3.scalePoint()
   .domain(labels)
   .range([graphH / labels.length * 0.5, graphH * (1 - 0.5 / labels.length)]);

 var grpScale = d3.scaleOrdinal()

 var xScale = d3.scaleTime()
   .domain([d3.min(flatDatar, function(d) {
     return d.start;
   }), d3.max(flatDatar, function(d) {
     return d.finish;
   })])
   .range([0, graphW]);

 var xGrid = d3.axisTop()
   .scale(xScale)
   .tickSize(graphH);

 var yAxis = d3.axisRight()
   .scale(yScale)
   .tickSize(0);

 var grpAxis = d3.axisLeft()
   .scale(grpScale)
   .tickSize(0)

 var axises = svg.append('g').attr('class', 'axises');
 axises.append('g').attr('class', 'x-grid');
 axises.append('g').attr('class', 'y-axis');
 axises.append('g').attr('class', 'grp-axis');

 svg.select('.axises').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');



 svg.select('g.x-grid')
   .attr('transform', 'translate(0,' + graphH + ')')
   .transition().duration(100)
   .call(xGrid);


 var fontVerticalMargin = 0.6;

 var fontSize = Math.min(12, graphH / flatDatar.length * fontVerticalMargin * Math.sqrt(2));

 yAxis.tickValues(labels);

 svg.select('g.y-axis')
   .transition().duration(100)
   .attr('transform', 'translate(' + graphW + ', 0)')
   .style('font-size', fontSize + 'px')
   .call(yAxis);

 var minHeight = d3.min(grpScale.range(), function(d, i) {
   return i > 0 ? d - grpScale.range()[i - 1] : d * 2;
 });


 grpAxis.tickFormat(function(d) {
     return d
   })
   .ticks(0);

 grpScale.domain(flatData.map(function(d) {
   return d.group;
 }));

 var cntLines = 0;
 grpScale.range(flatData.map(function(d) {
   var pos = (cntLines + d.lines.length / 2) / nLines * graphH;
   cntLines += d.lines.length;
   return pos;
 }));



 svg.select('g.grp-axis')
   .transition()
   .duration(100)
   .style('font-size', fontSize + 'px')
   .call(grpAxis);



 var lineHeight = graphH / nLines * 0.8;

 function zoomed() {}

 console.log(flatDatar)


 var zoom = d3.zoom()
   //   .scaleExtent([1, 500])
   //  .translateExtent([[0, 0], [width, height]])
   // .extent([[0, 0], [2000, height]])
   .on("zoom", zoomed);

 var group = g.selectAll(".rectangle")
   .data(flatDatar);

 var gEnter = group.enter()
   .append("g")
   .attr("class", "rectangle")
   .attr("fill", "yellow")
   .attr("transform", function(d) {
     console.log("label " + d.label)
     return "translate(" + xScale(d.start) + "," + (yScale(d.group + '+&+' + d.label) - lineHeight / 2) + ")";
   })

   .append("svg")
   .attr("height", lineHeight)
   .attr("class", "interval")
   .attr("width", function(d) {
     return xScale(d.finish) - xScale(d.start)
   });


 gEnter.append("rect")
   .attr("class", "rectband " + function(d) {
     return d.clas;
   })
   .attr("width", function(d) {
     return xScale(d.finish) - xScale(d.start)
   })
   .attr("height", lineHeight)
   .style("opacity", .5) // set the element opacity
   .style("stroke", "black");

 gEnter.append("text")
   .attr("class", "interval")
   .attr("x", 6)
   .attr("y", 9)
   .style("pointer-events", "none")
   .style("fill", "black")
   .attr("font-size", 11)
   .attr("font-family", "Cambria")
   .text(function(d) {
     return (d.description);
   });


 function sjp() {

   console.log("clicked")
   flatDatar.push({
     group: "group4",
     start: "2019-04-01",
     finish: "2019-08-01",
     description: "Temp"
   })
   console.log(flatDatar)
   group = group.merge(gEnter);
   zoomed()
 }


 //---------------
 svg.call(zoom).on("dblclick.zoom", sjp);


 var xt;

 function zoomed() {

   xt = xScale;
   var t = d3.event.transform
   if (typeof t !== 'undefined') {
     xt = t.rescaleX(xScale);

   }

   svg.select('.x-grid').call(xGrid.scale(xt));

   svg.selectAll(".rectangle, .circle").remove();
   svg.selectAll(".interval").remove();
   svg.selectAll(".clas").remove();

   var group = g.selectAll(".rectangle")
     .data(flatDatar);

   var gEnter = group.enter()
     .append("g")
     .attr("class", "rectangle")
     .attr("fill", "yellow")
     .attr("transform", function(d) {
       console.log(d.label)
       return "translate(" + xt(d.start) + "," + (yScale(d.group + '+&+' + d.label) - lineHeight / 2) + ")";
     })

     .append("svg")
     .attr("height", lineHeight)
     .attr("class", "interval")
     .attr("width", function(d) {
       return xt(d.finish) - xt(d.start)
     });


   gEnter.append("rect")
     .attr("class", "rectband " + function(d) {
       return d.clas;
     })
     //  .merge(gEnter)
     .attr("width", function(d) {
       return xt(d.finish) - xt(d.start)
     })
     .attr("height", lineHeight)
     .style("opacity", .5) // set the element opacity
     .style("stroke", "black");

   gEnter.append("text")
     .attr("class", "interval")
     .attr("x", 6)
     .attr("y", 9)
     .style("pointer-events", "none")
     .style("fill", "black")
     .attr("font-size", 11)
     .attr("font-family", "Cambria")
     .text(function(d) {
       return (d.description);
     });


 }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>