簡體   English   中英

D3圖表SVG響應條和軸

[英]D3 Chart SVG Responsive Bars and Axis

我已逐步創建了D3圖表。 我進行了一些更改以使SVG響應。 我現在的目標是使條形圖更具響應性,以便在屏幕尺寸較小(寬度)時更易於閱讀。 我在頁面的底部和底部粘貼了該代碼段,重點關注的是我認為解決方案隱藏的部分。

 var data = [ {"area": "one ", "value": 18000}, {"area": "Two ", "value": 17000}, {"area": "three ", "value": 80000}, {"area": "four ", "value": 55000}, {"area": "five ", "value": 100000}, {"area": "six", "value": 50000}, {"area": "seven", "value": 50000} ]; var margin = {top: 10, right: 10, bottom: 70, left: 30}; var width = 1900 - margin.left - margin.right; var height = 400 - margin.top - margin.bottom; //A fully-responsive chart area var svg = d3.select("#chart-div") .append("svg") .attr("width","100%") .attr("height","500px") .attr("viewBox","0 0 "+ (width+margin.left+margin.right)+ " "+ (height+margin.top+margin.bottom) ) .append("g") .attr("transform","translate("+ margin.left+","+margin.top+")"); var tooltip = d3.select("body").append("div").attr("class", "toolTip"); var x = d3.scaleLinear().range([0, width]); var y = d3.scaleBand().range([height, 0]); var g = svg.append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); data.sort(function(a, b) { return a.value - b.value; }); x.domain([0, d3.max(data, function(d) { return d.value; })]); y.domain(data.map(function(d) { return d.area; })).padding(0.1); g.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(x).ticks(5).tickFormat(function(d) { return parseInt(d / 1000); }).tickSizeInner([-height])); g.append("g") .attr("class", "y axis") .call(d3.axisLeft(y)); g.selectAll(".bar") .data(data) .enter().append("rect") .attr("class", "bar") .attr("x", 0) .attr("height", y.bandwidth()) .attr("y", function(d) { return y(d.area); }) .attr("width", function(d) { return x(d.value); }) .on("mousemove", function(d){ tooltip .style("left", d3.event.pageX - 50 + "px") .style("top", d3.event.pageY - 70 + "px") .style("display", "inline-block") .html((d.area) + "<br>" + "£" + (d.value)); }) .on("mouseout", function(d){ tooltip.style("display", "none");}); 
 @import url('https://fonts.googleapis.com/css?family=Roboto'); body { margin: 15px; background-color: #F1F3F3; font-family: 'Roboto'!important; } .bar { fill: #6F257F; } .axis path, .axis line { fill: none; stroke: #D4D8DA; stroke-width: 1px; shape-rendering: crispEdges; } .x path { display: none; } .toolTip { position: absolute; display: none; min-width: 80px; height: auto; background: none repeat scroll 0 0 #ffffff; border: 1px solid #6F257F; padding: 14px; text-align: center; } .svg-container { display: inline-block; position: relative; width: 100%; padding-bottom: 100%; /* aspect ratio */ vertical-align: top; overflow: hidden; } .svg-content-responsive { display: inline-block; position: absolute; top: 10px; left: 0; } 
 <script src="https://d3js.org/d3.v4.min.js"></script> <div id="chart-div" style="width:100%;height:100%;"></div> 

我使用以下代碼更改了部分代碼:

var parentwidth = $("#chart-div").parent().width(); 
var margin = {top: 10, right: 10, bottom: 70, left: 30};
var width = parentwidth - margin.left - margin.right;
var height = 400 - margin.top - margin.bottom;

我實際上在使用jQuery的parentwidth

我實際上在考慮是否:

a)在這種情況下可以避免使用jQuery。

b)理想情況下,使條的縮放比例不同,以便用戶可以輕松閱讀所有內容(小文本是個問題): 在此處輸入圖片說明

我正在測試下面的功能,但可能會遇到與某些Chrome插件相關的錯誤,以避免跨域錯誤。 如果以下是最佳解決方案,我可以更新問題:

function resize() {
  var width = parseInt(d3.select("#chart").style("width")) - margin.left - margin.right,
  height = parseInt(d3.select("#chart").style("height")) - margin.top - margin.bottom;

  // Update the range of the scale with new width/height
  xScale.range([0, width]);
  yScale.rangeRoundBands([height, 0], 0.1);

  // Update the axis and text with the new scale
  svg.select(".x.axis")
    .call(xAxis)
    .attr("transform", "translate(0," + height + ")")
    .select(".label")
      .attr("transform", "translate(" + width / 2 + "," + margin.bottom / 1.5 + ")");

  svg.select(".y.axis")
    .call(yAxis);

  // Update the tick marks
  xAxis.ticks(Math.max(width/75, 2), " $");

  // Force D3 to recalculate and update the line
  svg.selectAll(".bar")
    .attr("width", function(d) { return xScale(d["total"]); })
    .attr("y", function(d) { return yScale(d["Name"]); })
    .attr("height", yScale.rangeBand());
};

您的問題基本上與問題相同。

的TL; DR是:給你的<svg>一個viewBox屬性和preserveAspectRatio (例如xMinYMin meet )屬性。 然后將<svg>包裝在具有以下position: relative<div>position: relative

這不是唯一的解決方案,但是它可能是最容易實現的,並且(我認為)最常用。

有關其他幾種解決方案的概述和討論,請參閱Amelia Bellamy-Royds撰寫的本文

另外,要深入了解SVG坐標系,請閱讀Sara Soueidan撰寫的系列文章

至於您對jQuery的疑問以及手機上的文字太小:

a)您可以完全避免使用jQuery

b)您可以通過“反縮放”文本來避免文本過小,即當整個條形圖 (即條形圖,軸,標簽)縮小時, 文本就會放大。 這有時稱為粘性文本 您可以在此處查看示例

我已經更改了腳本以使其正常運行。 請查看下面的代碼段:

 var margin = {top: 20, right: 20, bottom: 50, left: 100}, width = parseInt(d3.select("#chart").style("width")) - margin.left - margin.right, height = parseInt(d3.select("#chart").style("height")) - margin.top - margin.bottom; var yScale = d3.scale.ordinal() .rangeRoundBands([height, 0], 0.1); var xScale = d3.scale.linear() .range([0, width]); var dollarFormatter = d3.format(",.0f") var yAxis = d3.svg.axis() .scale(yScale) .orient("left"); var xAxis = d3.svg.axis() .scale(xScale) .orient("bottom") .tickFormat(function(d) { return "$" + dollarFormatter(d);}); var svg = d3.select("#chart") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var tip = d3.tip() .attr('class', 'd3-tip') .offset([-10, 0]) .html(function(d) { return "<div><span>Name:</span> <span style='color:white'>" + d.Name + "</span></div>" + "<div><span>Sub-Category:</span> <span style='color:white'>" + d["Sub-Category"] + "</span></div>" + "<div><span>Total Sales:</span> <span style='color:white'>" + "$"+ dollarFormatter(d.total) + "</span></div>"; }) svg.call(tip); //Get CSV, JSON from URL //var url = "http://bl.ocks.org/josiahdavis/raw/7d84b2f1837eab9c24d9/top.csv"; var data = [ { "metric": "Sales", "Category": "Furniture", "Sub-Category": "Bookcases", "Name": "Tom Stivers", "total": 1889.8, "Type": "Customer" }, { "metric": "Sales", "Category": "Furniture", "Sub-Category": "Bookcases", "Name": "Keith Herrera", "total": 2020.161, "Type": "Customer" }, { "metric": "Sales", "Category": "Furniture", "Sub-Category": "Bookcases", "Name": "Jack O'Briant", "total": 2122.545, "Type": "Customer" }, { "metric": "Sales", "Category": "Furniture", "Sub-Category": "Bookcases", "Name": "Nora Paige", "total": 2154.9, "Type": "Customer" }, { "metric": "Sales", "Category": "Furniture", "Sub-Category": "Bookcases", "Name": "Anna Gayman", "total": 2396.2656, "Type": "Customer" }, { "metric": "Sales", "Category": "Furniture", "Sub-Category": "Bookcases", "Name": "Tracy Blumstein", "total": 3083.43, "Type": "Customer" }, { "metric": "Sales", "Category": "Furniture", "Sub-Category": "Bookcases", "Name": "Maribeth Schnelling", "total": 3406.664, "Type": "Customer" }, { "metric": "Sales", "Category": "Furniture", "Sub-Category": "Bookcases", "Name": "Greg Tran", "total": 4007.84, "Type": "Customer" }, { "metric": "Sales", "Category": "Furniture", "Sub-Category": "Bookcases", "Name": "Quincy Jones", "total": 4404.9, "Type": "Customer" }, { "metric": "Sales", "Category": "Furniture", "Sub-Category": "Bookcases", "Name": "Peter Fuller", "total": 6232.624, "Type": "Customer" }]; //d3.csv(url, format, function(error, data){ //if (error) throw error; // Filter to select a subset var subset = data.filter(function(el){ return (el["metric"] === "Sales") && (el["Sub-Category"] === "Bookcases") && (el["Type"] === "Customer"); }); // Sort the data so bar chart is sorted in decreasing order subset = subset.sort(function(a, b) { return a["total"] - b["total"]; }); console.log(JSON.stringify(subset, null, 2)); yScale.domain(subset.map(function(d) { return d["Name"]; })); xScale.domain([0, d3.max(subset, function(d) { return d["total"]; })]); svg.append("g") .attr("class", "y axis") .call(yAxis); svg.append("g") .attr("class", "x axis") .call(xAxis) .attr("transform", "translate(0," + height + ")") .append("text") .attr("class", "label") .attr("transform", "translate(" + width / 2 + "," + margin.bottom / 1.5 + ")") .style("text-anchor", "middle") .text("Sales"); svg.selectAll(".bar") .data(subset) .enter().append("rect") .attr("class", "bar") .attr("width", function(d) { return xScale(d["total"]); }) .attr("y", function(d) { return yScale(d["Name"]); }) .attr("height", yScale.rangeBand()) .on('mouseover', tip.show) .on('mouseout', tip.hide);; //}); // Define responsive behavior function resize() { var width = parseInt(d3.select("#chart").style("width")) - margin.left - margin.right, height = parseInt(d3.select("#chart").style("height")) - margin.top - margin.bottom; // Update the range of the scale with new width/height xScale.range([0, width]); yScale.rangeRoundBands([height, 0], 0.1); // Update the axis and text with the new scale svg.select(".x.axis") .call(xAxis) .attr("transform", "translate(0," + height + ")") .select(".label") .attr("transform", "translate(" + width / 2 + "," + margin.bottom / 1.5 + ")"); svg.select(".y.axis") .call(yAxis); // Update the tick marks xAxis.ticks(Math.max(width/75, 2), " $"); // Force D3 to recalculate and update the line svg.selectAll(".bar") .attr("width", function(d) { return xScale(d["total"]); }) .attr("y", function(d) { return yScale(d["Name"]); }) .attr("height", yScale.rangeBand()); }; // Call the resize function whenever a resize event occurs d3.select(window).on('resize', resize); // Call the resize function resize(); // Define the format function function format(d) { d.total = +d.total; return d; } 
 @import url('https://fonts.googleapis.com/css?family=Roboto'); body { margin: 5px; background-color: #F1F3F3; font-family: 'Roboto'!important; } .bar { fill: #14405F; } .bar:hover { fill: #33A1EE; } .axis { font: 10px sans-serif; } .axis path, .axis line { fill: none; stroke: #D4D8DA; stroke-width: 1px; shape-rendering: crispEdges; } .x path { display: none; } #chart { width: 100%; height: 100%; position: absolute; } .d3-tip { line-height: 1; font: 14px sans-serif; padding: 12px; background: rgba(0, 0, 0, 0.8); color: rgb(185, 185, 185); border-radius: 2px; } /* .toolTip { position: absolute; display: none; min-width: 80px; height: auto; background: none repeat scroll 0 0 #ffffff; border: 1px solid #6F257F; padding: 14px; text-align: center; } */ 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> <script src="https://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script> <svg id="chart"></svg> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM