2016-08-11 2 views
4

Я создал урезанный вниз JSFiddle моей диаграммы D3. Я сделал это реагировать (с ViewBox и preserveaspectratio) с использованием раствора на: responsive D3 chartПочему некоторые линии сетки случайным образом исчезают на моей отзывчивой диаграмме D3?

При изменении размера окна и сделать его меньше, некоторые из линий сетки, кажется, исчезать и появляться. Я предполагаю, что это будет выглядеть плохо при небольших разрешениях (например, мобильный телефон 320x480). Есть ли способ сохранить мои сетки, когда размер окна меньше?

HTML код:

<!--//d3 chart//--> 
<div class="centre-div"></div> 

CSS код:

.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; 
} 

JS код:

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

//} 

ответ

4

Это является сглаживание эф что произойдет, потому что способ получения линий зависит от разных факторов. Основными из них являются ширина, положение и режим обводки. Для использования shape-rendering: crispEdges в SVG спецификация состояний:

Для достижения четких краев, агент пользователя может отключить сглаживание для всех линий ...

В зависимости от масштаба и перевода строки можно вычислить между двумя экраном пикселей, в то время как ширина масштабируемого штриха недостаточно широка, чтобы окрасить любой из этих соседних пикселей экрана. Таким образом, линии кажутся случайным образом исчезают и появляются снова.

Дополнительные пояснения можно найти в "Why is SVG stroke-width : 1 making lines transparent?" или в моих answer до "Drew a straight line, but it is crooked d3".

Для вашего кода вы можете изменить поведение рендеринга, используя shape-rendering: geometricPrecision вместо crispEdges при рисовании линий сетки. Посмотрите обновленный JSFiddle для рабочего примера.

 Смежные вопросы

  • Нет связанных вопросов^_^