剪辑路径仅在d3中的页面加载时工作一次

时间:2017-01-14 00:37:17

标签: javascript html d3.js

我目前正在尝试在d3中实现一个clipPath到我的烛台图表。它按预期工作,只有一次,如果我在clipPath中更改rect的宽度和高度,我可以看到烛台消失,但当我将它们绘制到clipPath的边界时,它们仍然保留。

var width = 600;
var height = 500;

var marginTop = 20;
var marginBottom = 20;
var marginLeft = 60; //initial space required to the left of the chart
var marginRight = 20;

var candleWidth = 20;
var candleGap = 40;
var candleMargin = 10;
var padding = 70;
var Xpadding = 60;

var wickThickness = "2";

var hLineColor = "#b5b6b7";


var data = [{
  Date: 01 / 12 / 15,
  High: 118.81,
  Low: 116.86,
  Open: 118.75,
  Close: 117.34
}, {
  Date: 02 / 12 / 15,
  High: 118.11,
  Low: 116.08,
  Open: 117.05,
  Close: 116.28
}, {
  Date: 03 / 12 / 15,
  High: 116.79,
  Low: 114.22,
  Open: 116.55,
  Close: 115.2
}, {
  Date: 04 / 12 / 15,
  High: 119.25,
  Low: 115.11,
  Open: 115.29,
  Close: 119.03
}, {
  Date: 07 / 12 / 15,
  High: 119.86,
  Low: 117.81,
  Open: 118.98,
  Close: 118.28
}, {
  Date: 05 / 01 / 16,
  High: 105.85,
  Low: 102.41,
  Open: 105.75,
  Close: 102.71
}, {
  Date: 04 / 02 / 16,
  High: 97.33,
  Low: 95.19,
  Open: 95.86,
  Close: 96.6
}, {
  Date: 01 / 12 / 15,
  High: 118.81,
  Low: 116.86,
  Open: 118.75,
  Close: 117.34
}, {
  Date: 02 / 12 / 15,
  High: 118.11,
  Low: 116.08,
  Open: 117.05,
  Close: 116.28
}, {
  Date: 03 / 12 / 15,
  High: 116.79,
  Low: 114.22,
  Open: 116.55,
  Close: 115.2
}, {
  Date: 04 / 12 / 15,
  High: 119.25,
  Low: 115.11,
  Open: 115.29,
  Close: 119.03
}, {
  Date: 07 / 12 / 15,
  High: 119.86,
  Low: 117.81,
  Open: 118.98,
  Close: 118.28
}, {
  Date: 05 / 01 / 16,
  High: 105.85,
  Low: 102.41,
  Open: 105.75,
  Close: 102.71
}, {
  Date: 04 / 02 / 16,
  High: 97.33,
  Low: 95.19,
  Open: 95.86,
  Close: 96.6
}];

var maxi = d3.max(data, function(d) {
  return d.value;
}); // to check what the max value in the data array is ... for info purposes
console.log(maxi); //not displaying in brackets??

// .map() creates an new array based on function
var maxLow = d3.min(data.map(function(x) {
    return x["Low"];
  })) // returns the lowest value of 'low'
var maxHigh = d3.max(data.map(function(x) {
    return x["High"];
  })) // returns the highest value of 'high'
var maxMinDiff = (maxHigh - maxLow) * 0.1;
console.log(maxMinDiff);

//function that will return the lowest of two numbers a or b
function min(a, b) {
  return a < b ? a : b;
};

//function that will return the highest of two number a or b
function max(a, b) {
  return a > b ? a : b;
};

var xAxis = d3.svg.axis()
  .scale(x)
  .orient("bottom")
  .tickSize(-height);

var yAxis = d3.svg.axis()
  .scale(y)
  .orient("left")
  .ticks(5)
  .tickSize(-width);

var x = d3.scale.linear().domain([-width / 2, width / 2]).range([0, width]);

//Var Y is a function that will scale the numbers on the Y axis from an input domain into output range; height-0 which inverts or flips Y otherwise visualisation is upside down
var y = d3.scale.linear()
  .domain([maxLow - maxMinDiff, maxHigh + maxMinDiff]) //changed to reflect new variables for lowest, highest and difference to define input domain
  .range([height - marginTop - marginBottom, 0 + marginLeft + marginRight]); //range has still not been modified ... remember x,y have been reversed to reflect y,x


//this section is very similar to mashup code at #2
var zoom = d3.behavior.zoom()
  .x(x)
  .y(y)
  .scaleExtent([1, 32])
  .on("zoom", zoomed);
var chart = d3.select("body")
  .append("svg:svg") //namespace prefix
  .attr("class", "chart")
  .attr("width", width)
  .attr("height", height);

var grid = chart.append("g")
  .attr("class", "gridding");


//script to create horizontal lines for viewing
var lines = grid.selectAll("line.y")
  .data(y.ticks(20))
  .enter()
  .append("svg:line")
  .attr("class", "y")
  .attr("x1", marginLeft)
  .attr("x2", width - marginRight)
  .attr("y1", y)
  .attr("y2", y)
  .attr("stroke", hLineColor);

var numbers = grid.selectAll("text.yrule")
  .data(y.ticks(10))
  .enter()
  .append("svg:text")
  .attr("class", "yrule")
  .attr("x", marginLeft / 2)
  .attr("y", y)
  .attr("dy", 0)
  .attr("dx", 20)
  .style("fill", "#b5b6b7")
  .attr("text-anchor", "middle")

chart.append("chart:clipPath")
  .attr("id", "clip")
  .append("rect")
  .attr("clip-path", function(d, i) {
    return "url(#clip)";
  })
  .attr("width", width - padding)
  .attr("height", height)
  .attr("x", Xpadding - 15)




var candlestick = chart.append("g")
  .attr("class", "candlesticks")
  .attr("clip-path", "url(#clip)")



//function to build a chart using data in var data
//.call zoom and append g enable pan and zoom ... still not perfect ... don't want y axis moving etc
function buildChart(data) {






    //script for creating the candlestick wick that will lie behind the rectangle//x1 y1 represent High and x2 y2 represent Low
    //coded first to sit beneath the rectangle
    var wicks = candlestick.selectAll("wick")
      .data(data)
      .enter()
      .append("line")
      .attr("x1", function(d, i) {
        return candleMargin + marginLeft + candleWidth / 2 + (candleGap * i);
      })
      .attr("x2", function(d, i) {
        return candleMargin + marginLeft + candleWidth / 2 + (candleGap * i);
      })
      .attr("y1", function(d) {
        return y(max(d.High, d.Low));
      }) //return which ever is highest value H or L using var y for scaling
      .attr("y2", function(d) {
        return y(min(d.High, d.Low));
      }) //return which ever is lowest value H or L using var y for scaling
      .attr("stroke", function(d) {
        return d.Open > d.Close ? "#a01f1b" : "#1ba048";
      })
      .attr("stroke-width", wickThickness);



    //script for creating rectangle representing Open and Close positions
    //                            chart.selectAll("rect")
    var candle = candlestick.selectAll("rect")
      .data(data)
      .enter()
      .append("rect")
      .attr("clip-path", "url(#clip)")
      .attr("x", function(d, i) {
        return candleMargin + marginLeft + (candleGap * i);
      })
      .attr("y", function(d) {
        return y(max(d.Open, d.Close));
      }) //top left hand corner of rectangle coordinates
      .attr("height", function(d) {
        return y(min(d.Open, d.Close)) - y(max(d.Open, d.Close));
      })
      .attr("width", function(d) {
        return candleWidth
      })
      .attr("fill", function(d) {
        return d.Open > d.Close ? "#a01f1b" : "#1ba048";
      })
      .call(d3.behavior.zoom().x(x).on("zoom", function() {
        candlestick.attr("transform", "translate(" + d3.event.translate + ")")
      }));

  } //closing brackets for buildChart function
buildChart(data);


function zoomed() {
  svg.select(".x.axis").call(xAxis);
  svg.select(".y.axis").call(yAxis);
  //svg.select(".rect").call(chart);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

这是ClipPath的代码并添加到我的矩形组

  chart.append("clipPath")
                     .attr("id","clip")
                     .append("rect")
                     .attr("width", width-padding)
                     .attr("height", height)
                     .attr("x", Xpadding-15)




                var candlestick = chart.append("g")
                .attr("class", "candlesticks")
                .attr("clip-path", "url(#clip)")

如果您运行代码片段,您会看到如果将任何矩形平移到左侧或右侧(clipPath的边界是轴线),矩形将不会被遮盖,现在如果您改变宽度或者剪辑蒙版的高度值你可以清楚地看到被遮挡的矩形,即半个矩形被移除但是当我平移缩放没有任何反应时

1 个答案:

答案 0 :(得分:0)

您的问题基本上与this one重复。我打算关闭它但是因为那个不是d3并且在你的代码中看到了一堆其他不良做法我决定输入一个答案。

首先,您的剪辑路径无法正常工作,因为您正在将translate应用于要剪切的对象,然后剪辑路径将跟随{{1}也是。简单的解决方案是将其包装在另一个translate中。

g

第二,您的日期不是日期,而是分割等式。你没有使用它们,所以我没有把它搞得一团糟。

第三次,您似乎正在遭受太多的利润,我不知道在哪里应用它们。以理智的方式开始您的图表构建(通过创建带有边距的var candlestick = chart.append("g") .attr("clip-path", "url(#clip)") .append("g") .attr("class", "candlesticks"); ),然后只处理宽度/高度。我喜欢从Bostock的classic bar chart示例的前30行开始,然后为新的可视化构建它。

第四,您可能希望在整个图表上应用缩放/平移,而不仅仅是蜡烛上的鼠标事件。

把这一切放在一起:

&#13;
&#13;
g
&#13;
&#13;
&#13;