D3.js和坐标系

时间:2012-09-07 18:54:56

标签: javascript d3.js

尝试D3,并遇到一些问题。不确定什么是忍受坐标系的最佳方法。 请在下面找到来源。

编辑:小提琴here

  1. 我按yScale -> .range([ height - padding, padding]);而不是.range([ padding - height - padding]);模拟倒置坐标。这是最好的方式吗?如果svg中的所有对象都需要正确定向,那么最好应用于最外层的元素吗?

    var svg = d3.select("#chart").append("svg")
    .attr("width", width + margin.right + margin.left)
    .attr("height", height + margin.top + margin.bottom)
    .append("g") <---

  2. 较大的矩形({“X”:100,“Y”:100,“W”:40,“H”:40})位于轴外。所以,我做错了什么。

  3. 任何有助于使此图形包含在轴内,并具有适当的缩放和方向的帮助都非常受欢迎。

    的index.html

    <!DOCTYPE html>
    <html>
      <head>
        <title>Test</title>
        <script type="text/javascript" src="d3.v2.min.js"></script>
        <link type="text/css" rel="stylesheet" href="style.css"/>
      </head>
      <body>
        <div id="chart"></div>
        <script type="text/javascript" src="script.js"></script>
      </body>
    </html>
    

    的script.js

    var margin = {top: 10, right: 20, bottom: 20, left: 10},
        width = 960 - margin.right - margin.left, 
        height = 480 - margin.top - margin.bottom
        padding = 40; 
    
    
    var data = [
        {"X":10, "Y": 10, "W":10, "H": 10}, 
        {"X":100, "Y": 100, "W":40, "H": 40}
    ]
    
    var xScale = d3.scale.linear()
             .domain([0, d3.max(data, function(d) { return d.X; })])
         .range([padding, width - padding]),
        yScale = d3.scale.linear()
             .domain([0, d3.max(data, function(d) { return d.Y; })])
         .range([  height -  padding, padding]);
    
    var xAxis = d3.svg.axis().scale(xScale).orient("bottom"),
        yAxis = d3.svg.axis().scale(yScale).orient("left");
    
    
    var svg = d3.select("#chart").append("svg")
        .attr("width", width + margin.right + margin.left)
        .attr("height", height + margin.top + margin.bottom)
      .append("g")
        .attr("transform", "translate(" 
                + margin.left  + "," 
                + margin.top + ")");
    
    svg.selectAll("rect")
            .data(data)
          .enter().append("rect")
            .attr("x", function(d) { return xScale(d.X); }) 
            .attr("y", function (d) { return  yScale(d.Y); })
            .attr("width", function (d) { return  (d.W); })
            .attr("height", function (d) { return  (d.H); })
    
    //Create X axis
    svg.append("g")
        .attr("class", "axis")
        .attr("transform", "translate(0," + (height - padding) + ")")
        .call(xAxis);
    
    //Create Y axis
    svg.append("g")
        .attr("class", "axis")
        .attr("transform", "translate(" + padding + ",0)")
        .call(yAxis);
    

1 个答案:

答案 0 :(得分:3)

Re 1:是的,这是最好的方式。

另请注意,当您“翻转”这样的比例然后将宽度输入其中时,D3将不会保存您的培根,这将是负面的:当使用SVG高度属性时,这些将被标记为非法SVG内容并且浏览器会对一个毛球进行barf(不显示你想要的东西)。

Re 2。:一旦你纠正了你的负宽度/高度,你可以通过将你的s包裹在一个剪裁矩形中来防止'在区域外绘图';这可以通过将它们放在一个单独的组中来完成,然后为您的输出区域分配一个剪切矩形。

对于#1,请参阅回复您的问题到邮件列表:

http://bl.ocks.org/3671490

修复了所有错误并显示正确的矩形。

样式问题:您的代码只能通过单次调用xScale / yScale转换宽度和高度而不是首先计算域空间中的绝对坐标,然后通过缩放转换来计算宽度时使用线性轴/输出空间中的高度。为了表明新方法也适用于日志空间,这里是使用日志/日志比例的上述要点的副本:

http://bl.ocks.org/3671592

代码是“粗略的”,因为所有计算都是明确完成的,并且没有'不变量'被移到.attr()调用之外:x1 / y1 / x2 / y2得到多次计算,每个.attr()需要两次他们在将数据提供给d3.selection.data()之前,通过设置数据(预先计算/排序/交换/需要的任何内容)来解决这类问题。

经验教训:在使用SVG时,您需要做更多的工作才能完全与规模无关;如果你想要更快的代码,你需要准备你的数据,以便输出将产生有效的SVG(这里:'处理'输入= [{X:80,Y:80,W:10,H:-60]]) ,特别是宽度和高度的正值(或类似地,x2> x1和y2> y1)