D3 Chart SVG响应条和轴
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了D3 Chart SVG响应条和轴相关的知识,希望对你有一定的参考价值。
我已经逐步创建了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());
;
你的问题与this one基本相同。
TL; DR是:给你的<svg>
一个viewBox
属性和一个preserveAspectRatio
(例如xMinYMin meet
)属性。然后将<svg>
包裹在有<div>
的position: relative
中。
这不是唯一的解决方案,但它可能是最容易实现的(我认为)最常用的解决方案。
有关其他几种解决方案的概述和讨论,请参阅this article by Amelia Bellamy-Royds。
另外,有关SVG坐标系的深入说明,请阅读this series of articles by Sara Soueidan。
至于你对jQuery的怀疑和手机上的文字太小:
a)你可以完全避免使用jQuery
b)通过“反缩放”文本可以避免文本太小,即当整个条形图(即条形图,轴,标签)缩小时,文本会向上扩展。这有时被称为粘性文本。你可以看到一个example here。
我已经改变了我的脚本以使其工作。请参阅下面的代码:
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/以上是关于D3 Chart SVG响应条和轴的主要内容,如果未能解决你的问题,请参考以下文章