43

好的,我开始对 D3 更加熟悉了,但在某些事情上仍然有些模糊。我现在正在尝试绘制网格线,但我意识到我可能正在破解而不是正确地做它。我尝试使用教程添加一些网格线,但最终得到了很多代码,我似乎在编排这些代码,以便让它正确排列。我想知道是否有人可以指出我写这篇文章的更好方法......

原始代码是这样的。

        <script type="text/javascript">

            //Width and height
            var w = 800;
            var h = 400;
            var padding = 20;
            var border=1;
            var bordercolor='black';


            var dataset = [
                            [5, 20], [480, 90], [250, 50], [100, 33], [330, 95],[-50,-100],[50,-45],
                            [410, 12], [475, 44], [25, 67], [85, 21], [220, 88],[-480, -467], [3,-90],[468,481]
                          ];

                // create scale functions
                var xScale = d3.scale.linear()
                                 .domain([d3.min(dataset, function(d) { return d[0]; }), d3.max(dataset, function(d) { return d[0]; })])
                                 .range([padding, w - padding * 2]);

            var yScale = d3.scale.linear()
                                 .domain([d3.min(dataset, function(d) { return d[0]; }), d3.max(dataset, function(d) { return d[1]; })])
                                 .range([h - padding, padding]);

                var rScale = d3.scale.linear()
                .domain(  [-100,      d3.max(dataset, function(d) { return d[1];            })]   )
                .range([2,5]);

            //Create SVG element
            var svg = d3.select("body")
                        .append("svg")
                        .attr("width", w)
                        .attr("height", h)
                        .attr("border",border)
                        ;

            //define X axis   this is rly a function, remember, variables can hold functions in JS
                var xAxis = d3.svg.axis()
                        .scale(xScale)
                        .orient("bottom")
                        .ticks(1)
                        .tickSize(-h, 0, 0)
                        ;   //Set rough # of ticks


            //Define Y axis
                var yAxis = d3.svg.axis()
                        .scale(yScale)
                        .orient("left")
                        .ticks(1)
                        .tickSize(-w, 0, 0)
                        ;




                //create the circles
            svg.selectAll("circle")
               .data(dataset)
               .enter()
               .append("circle")
               .attr("cx", function(d) {
                    return xScale(d[0]);
               })
               .attr("cy", function(d) {
                    return yScale(d[1]);
               })
               .attr("r", 3);





  //   draw axes here
   svg.append("g")
    .attr("class", "axis") //assign "axis" class
    .attr("transform", "translate(0," + (h - padding) +")")
    .call(xAxis);



       svg.append("g")
    .attr("class", "axis") //assign "axis" class
    .attr("transform", "translate(" + padding + ",0)"       )
    .call(yAxis);
// end draw axes here
        </script>

我在第二个链接中添加的代码在这里

var vis = svg.append("svg:g")
    .attr("transform", "translate(20,0)")


var rules = vis.append("svg:g").classed("rules", true)


rules.append("svg:g").classed("grid x_grid", true)
    .attr("transform", "translate(-20,"+h+")")
    .call(d3.svg.axis()
      .scale(xScale)
      .orient("bottom")
      .ticks(4)
      .tickSize(-h,0,0)
      .tickFormat("")
    )

rules.append("svg:g").classed("grid y_grid", true)
    .call(d3.svg.axis()
      .scale(yScale)
      .orient("left")
      .ticks(5)
      .tickSize(-w,0,0)
      .tickFormat("")
    )

rules.append("svg:g").classed("labels x_labels", true)
    .attr("transform", "translate(-20,"+ h +")")
    .call(d3.svg.axis()
      .scale(xScale)
      .orient("bottom")
      .ticks(4)
      .tickSize(0)
            .tickFormat("")
      // .tickFormat(d3.time.format("%Y/%m"))
    )

rules.append("svg:g").classed("labels y_labels", true)
    .call(d3.svg.axis()
      .scale(yScale)
      .orient("left")
      .ticks(5)
      .tickSubdivide(1)
      .tickSize(0, 0, 0)
            .tickFormat("")
    )

再次,非常感谢任何帮助

4

6 回答 6

75

假设您定义了Mike Bostock 的标准边距,并且您已经为 y 轴定义了线性比例,则以下代码将创建水平网格线而不使用tickSize().

svg.selectAll("line.horizontalGrid").data(yScale.ticks(4)).enter()
    .append("line")
        .attr(
        {
            "class":"horizontalGrid",
            "x1" : margin.right,
            "x2" : width,
            "y1" : function(d){ return yScale(d);},
            "y2" : function(d){ return yScale(d);},
            "fill" : "none",
            "shape-rendering" : "crispEdges",
            "stroke" : "black",
            "stroke-width" : "1px"
        });
于 2013-07-26T00:32:13.827 回答
19

我建议使用 d3.svg.axis().scale() 将网格绑定到您的坐标。我根据你的代码画了一个简单的例子:http: //jsfiddle.net/temirov/Rt65L/1/

网格示例

要点是使用现有的刻度 x 和 y,并使用刻度作为网格。由于 yAxis 和 xAxis 已经定义,我们可以重复使用它们。以下是相关代码:

//Draw a grid
var numberOfTicks = 6;

var yAxisGrid = yAxis.ticks(numberOfTicks)
    .tickSize(w, 0)
    .tickFormat("")
    .orient("right");

var xAxisGrid = xAxis.ticks(numberOfTicks)
    .tickSize(-h, 0)
    .tickFormat("")
    .orient("top");

svg.append("g")
    .classed('y', true)
    .classed('grid', true)
    .call(yAxisGrid);

svg.append("g")
    .classed('x', true)
    .classed('grid', true)
    .call(xAxisGrid);
于 2014-03-26T04:33:52.257 回答
11

您可以使用ticks()刻度的功能来获取刻度值,然后在数据调用中使用它们来绘制线条。

var ticks = xScale.ticks(4);
rules.selectAll("path.xgrid").data(ticks).enter()
     .append("path")
     .attr("d", function(d) {
       return "M" + xScale(d) + " " + padding + "L" + xScale(d) + " " + (h-padding);
     });

您可能更喜欢为网格线使用线生成器,而不是手动创建路径。这同样适用于 y 网格线,只是 y 坐标是恒定的并且范围从 0 到图形宽度。您可能需要调整开始值和结束值以使其看起来“不错”。

于 2013-03-22T21:54:07.267 回答
2

在 d3fc 项目中,我们创建了一个网格线组件,它的渲染方式与 D3(v4) 轴完全相同。

下面是一个用法示例:

var width = 500, height = 250;
var container = d3.select("#gridlines")
    .append("svg")
    .attr("width", width)
    .attr("height", height);

var xScale = d3.scaleLinear()
  .range([0, 100]);

var yScale = d3.scaleLinear()
  .range([0, 100]);

var gridline = fc.annotationSvgGridline()
  .xScale(xScale)
  .yScale(yScale);

container.append("g")
  .call(gridline);

呈现如下:

在此处输入图像描述

网格线的间距由相关轴提供的刻度确定。

披露:我是 d3fc 项目的核心贡献者!

于 2016-03-18T06:09:05.853 回答
1

按照@arete 的想法,您可以使用以下方法来避免不必要地重新绘制网格线:

function createsGrid(data) {
       var grid = gridLine.selectAll("line.horizontalGrid").data(scaleY.ticks());

       grid.enter()
       .append("line")
       .attr("class","horizontalGrid");

       grid.exit().remove();

       grid.attr({
               "x1":0,
               "x2": width,
               "y1": function (d) { return scaleY(d); },
               "y2": function (d) { return scaleY(d); }
                });
}

并在您的 CSS 文件中定义以下内容

line.horizonalGrid{
  fill : none;
 shape-rendering : crispEdges;
 stroke : black;
 stroke-width : 1.5px;
} 
于 2014-07-23T22:59:31.620 回答
1

你可以只使用innerTickSize,而不是tickSize:

            var xAxis = d3.svg.axis()
                    .scale(xScale)
                    .orient("bottom")
                    .ticks(1)
                    .innerTickSize(-h);
于 2015-11-12T03:10:58.197 回答