D3.js 为什么一些网格线在我的D3图表上随机消失?

D3.js 为什么一些网格线在我的D3图表上随机消失?,d3.js,svg,responsive,aliasing,D3.js,Svg,Responsive,Aliasing,我已经创建了一个精简的D3图表。我使用以下解决方案使其具有响应性(使用viewbox和preserveaspectratio): 当我调整窗口大小并使其变小时,一些网格线似乎正在消失并重新出现。我认为这在小分辨率(例如320x480手机)下看起来很糟糕。当窗口变小时,有没有办法保留网格线 HTML代码: <!--//d3 chart//--> <div class="centre-div"></div> .centre-div { margin: 0

我已经创建了一个精简的D3图表。我使用以下解决方案使其具有响应性(使用viewbox和preserveaspectratio):

当我调整窗口大小并使其变小时,一些网格线似乎正在消失并重新出现。我认为这在小分辨率(例如320x480手机)下看起来很糟糕。当窗口变小时,有没有办法保留网格线

HTML代码:

<!--//d3 chart//-->
<div class="centre-div"></div>
.centre-div {
  margin: 0 auto;
  max-width: 550px;
}

/* D3 chart css */
.axis path,
.axis line {
  fill: none;
  stroke: black;
  shape-rendering: crispEdges;
}

.axis text {
  font-family: sans-serif;
  font-size: 11px;
}
//function createScatterplot() {
//Width and height
var margin = {
  top: 15,
  right: 2,
  bottom: 2,
  left: 2
};
//define width and height as the inner dimensions of the chart area.
var width = 550 - margin.left - margin.right;
var height = 550 - margin.top - margin.bottom;
var padding = 10;

//define svg as a G element that translates the origin to the top-left corner of the chart area.

//add <svg> to the last <div class="centre-div"> tag on the html page 
//this allows me to reuse the createScatterplot() function to draw multiple charts
var svg = d3.select(d3.selectAll(".centre-div")[0].pop()).append("svg")
  //.attr("width", width + margin.left + margin.right)
  //.attr("height", height + margin.top + margin.bottom)
  //make svg responsive
  .attr("width", "100%")
  .attr("height", "100%")
  .attr("viewBox", "0 0 550 550")
  .attr("preserveAspectRatio", "xMidYMid meet")
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//With this convention, all subsequent code can ignore margins.
//http://bl.ocks.org/mbostock/3019563

//Static dataset
var dataset = [
  [5, -2, "A"],
  [-4, -9, "B"],
  [2, 5, "C"],
  [1, -3, "D"],
  [-3, 5, "E"],
  [4, 1, "F"],
  [4, 4, "G"],
  [5, 7, "H"],
  [-5, -2, "I"],
  [0, 8, "J"],
  [-6, -5, "K"]
];

//Create scale functions
var xScale = d3.scale.linear()
  .domain([-10, 11])
  .range([padding, width - padding * 2]);

var yScale = d3.scale.linear()
  .domain([-10, 11])
  .range([height - padding, padding]);

//different scale for gridlines, so last tick has no line
var xScale2 = d3.scale.linear()
  .domain([-10, 10])
  .range([padding, width - padding * 2]);

var yScale2 = d3.scale.linear()
  .domain([-10, 10])
  .range([height - padding, padding]);
//add arrowheads
defs = svg.append("defs")
defs.append("marker")
  .attr({
    "id": "arrow",
    "viewBox": "-5 -5 10 10",
    "refX": 0,
    "refY": 0,
    "markerWidth": 7, //marker size
    "markerHeight": 7, //marker size
    "orient": "auto"
  })
  .append("path")
  .attr("d", "M 0,0 m -5,-5 L 5,0 L -5,5 Z")
  .attr("fill", "#000");

//Define X axis
var xAxis = d3.svg.axis()
  .scale(xScale)
  .orient("bottom")
  .ticks(22)
  //Define Y axis
var yAxis = d3.svg.axis()
  .scale(yScale)
  .orient("left")
  .ticks(22)

//create scatterplot crosses
svg.selectAll("line.diag1")
  .data(dataset)
  .enter()
  .append("line")
  .attr({
    "class": "diag1",
    "x1": function(d) {
      return xScale(d[0]) - 4;
    },
    "y1": function(d) {
      return yScale(d[1]) - 4;
    },
    "x2": function(d) {
      return xScale(d[0]) + 4;
    },
    "y2": function(d) {
      return yScale(d[1]) + 4;
    },
    "stroke": "#006CCA",
    "opacity": "1",
    "stroke-width": "2px"
  });
svg.selectAll("line.diag2")
  .data(dataset)
  .enter()
  .append("line")
  .attr({
    "class": "diag2",
    "x1": function(d) {
      return xScale(d[0]) + 4;
    },
    "y1": function(d) {
      return yScale(d[1]) - 4;
    },
    "x2": function(d) {
      return xScale(d[0]) - 4;
    },
    "y2": function(d) {
      return yScale(d[1]) + 4;
    },
    "stroke": "#006CCA",
    "opacity": "1",
    "stroke-width": "2px"
  });

//Create X axis
svg.append("g")
  .attr("class", "axis")
  .style("stroke-width", 2)
  .attr("transform", "translate(0," + 11 * (height) / 21 + ")")
  .call(xAxis)
  //add x label
  .append("text")
  .attr("class", "label")
  .attr("x", width)
  .attr("y", 15)
  .attr("font-style", "italic")
  .attr("font-weight", "bold")
  .style("text-anchor", "end")
  .text("x");

//Create Y axis
svg.append("g")
  .attr("class", "axis")
  .style("stroke-width", 2)
  .attr("transform", "translate(" + 10 * (width - padding) / 21 + ",0)")
  .call(yAxis)
  //add y label
  .append("text")
  .attr("class", "label")
  .attr("x", -10)
  .attr("y", -5)
  .attr("font-style", "italic")
  .attr("font-weight", "bold")
  .style("text-anchor", "end")
  .text("y");

//add arrowheads to axis ends   
//add line on top of x-axis and arrowhead
svg.append("line")
  .attr({
    "x1": 0,
    "y1": 11 * height / 21,
    "x2": width - padding * 1.5,
    "y2": 11 * height / 21,
    "stroke": "black",
    "stroke-width": "2px",
    "marker-end": "url(#arrow)"
  });
//add line on top of y-axis and arrowhead
svg.append("line")
  .attr({
    "x1": 10 * (width - padding) / 21,
    "y1": height,
    "x2": 10 * (width - padding) / 21,
    "y2": 0.4 * padding,
    "stroke": "black",
    "stroke-width": "2px",
    "marker-end": "url(#arrow)"
  });

//Assuming that you have Mike Bostock's standard margins defined and you have defined a linear scale for the y-axis the following code will create horizontal gridlines without using tickSize().   
//https://stackoverflow.com/questions/15580300/proper-way-to-draw-gridlines

//create horizontal grid lines      
var gridwidth = 19 * width / 20;
var gridheight = 19 * height / 20;
svg.selectAll("line.horizontalGrid").data(yScale2.ticks(20)).enter()
  .append("line")
  .attr({
    "class": "horizontalGrid",
    "x1": 0,
    "x2": gridwidth,
    "y1": function(d) {
      return yScale(d);
    },
    "y2": function(d) {
      return yScale(d);
    },
    "fill": "none",
    "shape-rendering": "crispEdges",
    "stroke": "black",
    "stroke-width": "1px",
    "opacity": "0.3"
  });
//create vertical gridlines
svg.selectAll("line.verticalGrid").data(xScale2.ticks(20)).enter()
  .append("line")
  .attr({
    "class": "verticalGrid",
    "y1": height - gridheight,
    "y2": height,
    "x1": function(d) {
      return xScale(d);
    },
    "x2": function(d) {
      return xScale(d);
    },
    "fill": "none",
    "shape-rendering": "crispEdges",
    "stroke": "black",
    "stroke-width": "1px",
    "opacity": "0.3"
  });

//remove last ticks and zero ticks
svg.selectAll(".tick")
  .filter(function(d) {
    return d === 11;
  })
  .remove();
svg.selectAll(".tick")
  .filter(function(d) {
    return d === 0;
  })
  .remove();
//add a custom origin identifier
svg.append("text")
  .attr({
    "class": "origintext",
    "x": 455 * width / 1000,
    "y": 552 * height / 1000,
    "text-anchor": "end",
    "font-size": "65%"
  })
  .text("0");

//add labels to points plotted
svg.selectAll("textlabels")
  .data(dataset)
  .enter()
  .append("text")
  .text(function(d) {
    return d[2];
  })
  .attr("x", function(d) {
    return xScale(d[0]) + 5;
  })
  .attr("y", function(d) {
    return yScale(d[1]) - 5;
  })
  .attr("font-weight", "bold")
  .attr("font-size", "12px")
  .attr("fill", "black");

//}
JS代码:

<!--//d3 chart//-->
<div class="centre-div"></div>
.centre-div {
  margin: 0 auto;
  max-width: 550px;
}

/* D3 chart css */
.axis path,
.axis line {
  fill: none;
  stroke: black;
  shape-rendering: crispEdges;
}

.axis text {
  font-family: sans-serif;
  font-size: 11px;
}
//function createScatterplot() {
//Width and height
var margin = {
  top: 15,
  right: 2,
  bottom: 2,
  left: 2
};
//define width and height as the inner dimensions of the chart area.
var width = 550 - margin.left - margin.right;
var height = 550 - margin.top - margin.bottom;
var padding = 10;

//define svg as a G element that translates the origin to the top-left corner of the chart area.

//add <svg> to the last <div class="centre-div"> tag on the html page 
//this allows me to reuse the createScatterplot() function to draw multiple charts
var svg = d3.select(d3.selectAll(".centre-div")[0].pop()).append("svg")
  //.attr("width", width + margin.left + margin.right)
  //.attr("height", height + margin.top + margin.bottom)
  //make svg responsive
  .attr("width", "100%")
  .attr("height", "100%")
  .attr("viewBox", "0 0 550 550")
  .attr("preserveAspectRatio", "xMidYMid meet")
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//With this convention, all subsequent code can ignore margins.
//http://bl.ocks.org/mbostock/3019563

//Static dataset
var dataset = [
  [5, -2, "A"],
  [-4, -9, "B"],
  [2, 5, "C"],
  [1, -3, "D"],
  [-3, 5, "E"],
  [4, 1, "F"],
  [4, 4, "G"],
  [5, 7, "H"],
  [-5, -2, "I"],
  [0, 8, "J"],
  [-6, -5, "K"]
];

//Create scale functions
var xScale = d3.scale.linear()
  .domain([-10, 11])
  .range([padding, width - padding * 2]);

var yScale = d3.scale.linear()
  .domain([-10, 11])
  .range([height - padding, padding]);

//different scale for gridlines, so last tick has no line
var xScale2 = d3.scale.linear()
  .domain([-10, 10])
  .range([padding, width - padding * 2]);

var yScale2 = d3.scale.linear()
  .domain([-10, 10])
  .range([height - padding, padding]);
//add arrowheads
defs = svg.append("defs")
defs.append("marker")
  .attr({
    "id": "arrow",
    "viewBox": "-5 -5 10 10",
    "refX": 0,
    "refY": 0,
    "markerWidth": 7, //marker size
    "markerHeight": 7, //marker size
    "orient": "auto"
  })
  .append("path")
  .attr("d", "M 0,0 m -5,-5 L 5,0 L -5,5 Z")
  .attr("fill", "#000");

//Define X axis
var xAxis = d3.svg.axis()
  .scale(xScale)
  .orient("bottom")
  .ticks(22)
  //Define Y axis
var yAxis = d3.svg.axis()
  .scale(yScale)
  .orient("left")
  .ticks(22)

//create scatterplot crosses
svg.selectAll("line.diag1")
  .data(dataset)
  .enter()
  .append("line")
  .attr({
    "class": "diag1",
    "x1": function(d) {
      return xScale(d[0]) - 4;
    },
    "y1": function(d) {
      return yScale(d[1]) - 4;
    },
    "x2": function(d) {
      return xScale(d[0]) + 4;
    },
    "y2": function(d) {
      return yScale(d[1]) + 4;
    },
    "stroke": "#006CCA",
    "opacity": "1",
    "stroke-width": "2px"
  });
svg.selectAll("line.diag2")
  .data(dataset)
  .enter()
  .append("line")
  .attr({
    "class": "diag2",
    "x1": function(d) {
      return xScale(d[0]) + 4;
    },
    "y1": function(d) {
      return yScale(d[1]) - 4;
    },
    "x2": function(d) {
      return xScale(d[0]) - 4;
    },
    "y2": function(d) {
      return yScale(d[1]) + 4;
    },
    "stroke": "#006CCA",
    "opacity": "1",
    "stroke-width": "2px"
  });

//Create X axis
svg.append("g")
  .attr("class", "axis")
  .style("stroke-width", 2)
  .attr("transform", "translate(0," + 11 * (height) / 21 + ")")
  .call(xAxis)
  //add x label
  .append("text")
  .attr("class", "label")
  .attr("x", width)
  .attr("y", 15)
  .attr("font-style", "italic")
  .attr("font-weight", "bold")
  .style("text-anchor", "end")
  .text("x");

//Create Y axis
svg.append("g")
  .attr("class", "axis")
  .style("stroke-width", 2)
  .attr("transform", "translate(" + 10 * (width - padding) / 21 + ",0)")
  .call(yAxis)
  //add y label
  .append("text")
  .attr("class", "label")
  .attr("x", -10)
  .attr("y", -5)
  .attr("font-style", "italic")
  .attr("font-weight", "bold")
  .style("text-anchor", "end")
  .text("y");

//add arrowheads to axis ends   
//add line on top of x-axis and arrowhead
svg.append("line")
  .attr({
    "x1": 0,
    "y1": 11 * height / 21,
    "x2": width - padding * 1.5,
    "y2": 11 * height / 21,
    "stroke": "black",
    "stroke-width": "2px",
    "marker-end": "url(#arrow)"
  });
//add line on top of y-axis and arrowhead
svg.append("line")
  .attr({
    "x1": 10 * (width - padding) / 21,
    "y1": height,
    "x2": 10 * (width - padding) / 21,
    "y2": 0.4 * padding,
    "stroke": "black",
    "stroke-width": "2px",
    "marker-end": "url(#arrow)"
  });

//Assuming that you have Mike Bostock's standard margins defined and you have defined a linear scale for the y-axis the following code will create horizontal gridlines without using tickSize().   
//https://stackoverflow.com/questions/15580300/proper-way-to-draw-gridlines

//create horizontal grid lines      
var gridwidth = 19 * width / 20;
var gridheight = 19 * height / 20;
svg.selectAll("line.horizontalGrid").data(yScale2.ticks(20)).enter()
  .append("line")
  .attr({
    "class": "horizontalGrid",
    "x1": 0,
    "x2": gridwidth,
    "y1": function(d) {
      return yScale(d);
    },
    "y2": function(d) {
      return yScale(d);
    },
    "fill": "none",
    "shape-rendering": "crispEdges",
    "stroke": "black",
    "stroke-width": "1px",
    "opacity": "0.3"
  });
//create vertical gridlines
svg.selectAll("line.verticalGrid").data(xScale2.ticks(20)).enter()
  .append("line")
  .attr({
    "class": "verticalGrid",
    "y1": height - gridheight,
    "y2": height,
    "x1": function(d) {
      return xScale(d);
    },
    "x2": function(d) {
      return xScale(d);
    },
    "fill": "none",
    "shape-rendering": "crispEdges",
    "stroke": "black",
    "stroke-width": "1px",
    "opacity": "0.3"
  });

//remove last ticks and zero ticks
svg.selectAll(".tick")
  .filter(function(d) {
    return d === 11;
  })
  .remove();
svg.selectAll(".tick")
  .filter(function(d) {
    return d === 0;
  })
  .remove();
//add a custom origin identifier
svg.append("text")
  .attr({
    "class": "origintext",
    "x": 455 * width / 1000,
    "y": 552 * height / 1000,
    "text-anchor": "end",
    "font-size": "65%"
  })
  .text("0");

//add labels to points plotted
svg.selectAll("textlabels")
  .data(dataset)
  .enter()
  .append("text")
  .text(function(d) {
    return d[2];
  })
  .attr("x", function(d) {
    return xScale(d[0]) + 5;
  })
  .attr("y", function(d) {
    return yScale(d[1]) - 5;
  })
  .attr("font-weight", "bold")
  .attr("font-size", "12px")
  .attr("fill", "black");

//}
//函数createScatterplot(){
//宽度和高度
var保证金={
前15名,
右:2,,
底部:2,
左:2
};
//将宽度和高度定义为图表区域的内部尺寸。
变量宽度=550-margin.left-margin.right;
变量高度=550-margin.top-margin.bottom;
var=10;
//将svg定义为将原点转换为图表区域左上角的G元素。
//添加到html页面上的最后一个标记
//这允许我重用createScatterplot()函数来绘制多个图表
var svg=d3.select(d3.selectAll(“.center div”)[0].pop()).append(“svg”)
//.attr(“宽度”,宽度+边距。左侧+边距。右侧)
//.attr(“高度”,高度+边距。顶部+边距。底部)
//使svg具有响应性
.attr(“宽度”、“100%”)
.attr(“高度”、“100%”)
.attr(“视图框”,“0 0 550”)
.attr(“保存Aspectratio”、“xMidYMid会议”)
.附加(“g”)
.attr(“转换”、“平移”(+margin.left+)、“+margin.top+”);
//使用此约定,所有后续代码都可以忽略边距。
//http://bl.ocks.org/mbostock/3019563
//静态数据集
变量数据集=[
[5,-2,“A”],
[-4,-9,“B”],
[2,5,“C”],
[1,-3,“D”],
[-3,5,“E”],
[4,1,“F”],
[4,4,“G”],
[5,7,“H”],
[-5,-2,“I”],
[0,8,“J”],
[-6,-5,“K”]
];
//创建比例函数
var xScale=d3.scale.linear()
.domain([-10,11])
.范围([填充,宽度-填充*2]);
var yScale=d3.scale.linear()
.domain([-10,11])
.范围([高度-填充,填充]);
//网格线的比例不同,所以最后一个记号没有线
var xScale2=d3.scale.linear()
.domain([-10,10])
.范围([填充,宽度-填充*2]);
var yScale2=d3.scale.linear()
.domain([-10,10])
.范围([高度-填充,填充]);
//添加箭头
defs=svg.append(“defs”)
定义附加(“标记”)
艾特先生({
“id”:“箭头”,
“查看框”:“-5-5 10”,
“refX”:0,
“参考文献”:0,
“markerWidth”:7,//标记大小
“标记高度”:7,//标记大小
“定向”:“自动”
})
.append(“路径”)
.attr(“d”,“M 0,0 M-5,-5 L 5,0 L-5,5 Z”)
.attr(“填充”和“#000”);
//定义X轴
var xAxis=d3.svg.axis()
.scale(xScale)
.orient(“底部”)
.滴答声(22)
//定义Y轴
var yAxis=d3.svg.axis()
.刻度(yScale)
.东方(“左”)
.滴答声(22)
//创建散点图交叉点
svg.selectAll(“line.diag1”)
.数据(数据集)
.输入()
.附加(“行”)
艾特先生({
“类”:“diag1”,
“x1”:功能(d){
返回xScale(d[0])-4;
},
“y1”:功能(d){
返回yScale(d[1])-4;
},
“x2”:功能(d){
返回xScale(d[0])+4;
},
“y2”:功能(d){
返回yScale(d[1])+4;
},
“笔划”:“#006CCA”,
“不透明度”:“1”,
“笔划宽度”:“2px”
});
svg.selectAll(“line.diag2”)
.数据(数据集)
.输入()
.附加(“行”)
艾特先生({
“类”:“diag2”,
“x1”:功能(d){
返回xScale(d[0])+4;
},
“y1”:功能(d){
返回yScale(d[1])-4;
},
“x2”:功能(d){
返回xScale(d[0])-4;
},
“y2”:功能(d){
返回yScale(d[1])+4;
},
“笔划”:“#006CCA”,
“不透明度”:“1”,
“笔划宽度”:“2px”
});
//创建X轴
svg.append(“g”)
.attr(“类”、“轴”)
.样式(“笔划宽度”,2)
.attr(“变换”、“平移(0、+11*(高度)/21+”)
.呼叫(xAxis)
//添加x标签
.append(“文本”)
.attr(“类别”、“标签”)
.attr(“x”,宽度)
.attr(“y”,15)
.attr(“字体样式”、“斜体”)
.attr(“字体大小”、“粗体”)
.style(“文本锚定”、“结束”)
.文本(“x”);
//创建Y轴
svg.append(“g”)
.attr(“类”、“轴”)
.样式(“笔划宽度”,2)
.attr(“变换”、“平移”(+10*(宽度填充)/21+”,0)”
.呼叫(yAxis)
//添加y标签
.append(“文本”)
.attr(“类别”、“标签”)
.attr(“x”,-10)
.attr(“y”,-5)
.attr(“字体样式”、“斜体”)
.attr(“字体大小”、“粗体”)
.style(“文本锚定”、“结束”)
.文本(“y”);
//将箭头添加到轴端点
//在x轴和箭头顶部添加线
svg.append(“行”)
艾特先生({
“x1”:0,
“y1”:11*高/21,
“x2”:宽度-填充*1.5,
“y2”:11*高/21,
“笔划”:“黑色”,
“笔划宽度”:“2px”,
“标记结束”:“url(#箭头)”
});
//在y轴和箭头顶部添加线
svg.append(“行”)
艾特先生({
“x1”:10*(宽度-填充)/21,
“y1”:高度,
“x2”:10*(宽度-填充)/21,
“y2”:0.4*填充,
“笔划”:“黑色”,
“笔划宽度”:“2px”,
“标记结束”:“url(#箭头)”
});
//假设已定义Mike Bostock的标准边距,并且已定义y轴的线性比例,则以下代码将在不使用tickSize()的情况下创建水平网格线。
//https://stackoverflow.com/questions/15580300/proper-way-to-draw-gridlines
//创建水平轴网线
var gridwidth=19*width/20;
变量gridheight=19*height/20;
svg.selectAll(“line.horizontalGrid”).data(yScale2.ticks(20)).enter()
.附加(“行”)
艾特先生({
“类”:“水平网格”,
“x1”:0,
“x2”:网格宽度,
“y1”:功能(d){
返回yScale(d);
},
“y2”:功能(d){
返回yScale(d);
},
“填充”:“无”,
“形状渲染”:“边缘”,
“笔划”:“黑色”,
“笔划宽度”:“1px”,
“不透明度”:“0.3”
});
//创建垂直网格线
selectAll(“line.verticalGrid”).data(xScale2.ticks(20)).enter()
.附加(“行”)
艾特先生({
“类”:“垂直网格”,
“y1”:高度-网格高度,
“y2”:他说