D3.js和坐标系 [英] D3.js and coordinate system

查看:78
本文介绍了D3.js和坐标系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



编辑:小提琴


  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 ,高度+ margin.top + margin.bottom)

    .append( g)< ---


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


任何帮助使该图包含在轴内,具有适当比例和方向的方法都受到高度赞赏。



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},
宽度= 960-margin.right-margin.left,
高度= 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 dX;})]))
.range([padding,width-padding]),
yScale = d3。 scale.linear()
.domain([0,d3.max(data,function(d){return dY;})]))
.range([高度-填充,填充]);

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(dX);})
.attr( y,function(d){return yScale(dY);})
.attr( width,function (d){return(dW);})
.attr( height,function(d){return(dH);})

//创建X轴
svg.append( g)
.attr( class, axis)
.attr( transform, translate(0, +(height-padding)+) )
.call(xAxis);

//创建Y轴
svg.append( g)
.attr( class, axis)
.attr( transform , translate( + padding +,0))
.call(yAxis);


解决方案

Re 1 .:是的,这是最好的方法



还请注意,当您翻转这样的秤然后将宽度送入其中时,D3不会保存您的培根,这将变成负数:使用那些对于SVG高度属性,这些属性将被标记为非法SVG内容,浏览器将驳回一个毛发球(不显示您想要的内容)。



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)


Trying D3, and have some issues. Not sure what is the best way to endure coordinate system. Please find the source below.

EDIT: Fiddle here

  1. I simulated the inverted coordinate by yScale -> .range([ height - padding, padding]); Instead of .range([ padding - height - padding]); . Is this the best way. If all the objects in the svg needs to be correctly oriented, is it best to apply to the outermost element?

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

  2. The bigger rectangle ({"X":100, "Y": 100, "W":40, "H": 40}), is outside the axis. So, I am doing something wrong.

Any help to make this graph to contain within the axis, with proper scaling and orientation is highly appreciated.

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);

解决方案

Re 1.: yes, that is the best way.

Also note that D3 will not save your bacon when you 'flip' a scale like that and then feed widths into it, which will come out negative: when using those for SVG height attributes, those will be flagged as illegal SVG content and the browser will barf a hairball (not show what you want).

Re 2.: once you have corrected your negative widths / heights, then you can prevent 'plotting outside the area' by wrapping your s in a clipping rectangle; this can be done by placing them in a separate group, which is then assigned a clipping rect matching your output area.

For #1, see also in reply to your question to the mailing list:

http://bl.ocks.org/3671490

has all bugs fixed and showing a proper rect.

Style issue: your code would only have worked with a linear axis as you convert width and height via a single call to xScale/yScale instead of calculating the absolute coordinates in domain space first, then convert both via scale to calculate the width / height in output space. To show that the new approach works in log space too, here's a copy of the above gist using log/log scales instead:

http://bl.ocks.org/3671592

The code is 'rough' in that all calculations are explicitly done and no 'invariants' are moved outside the .attr() calls: x1/y1/x2/y2 get calculated several times as each .attr() needs two of them. This sort of thing is usually 'solved' by setting up the data (precalculating / sorting / swapping / whatever is needed) before feeding it to d3.selection.data().

Lesson learned: you need to do more work to be completely scale agnostic when working with SVG; if you want faster code instead, you need to prepare your data so that the output will produce valid SVG (here: 'processed' input = [{X:80,Y:80,W:10,H:-60]]), in particular positive values for width and height (or similarly x2 > x1 and y2 > y1 for )

这篇关于D3.js和坐标系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆