简介
D3.js是由javaScript语言编写绘图库,其原理是:通过调用一系列内置函数,生成SVG,并在网页渲染。
本文以频率分布直方图案例为例,介绍使用D3.js的流程
流程
第一步 引用D3.js库
建立一个html文件,在<head>
标签引用D3库
<!DOCTYPE html>
<html>
<head>
<!--第一步:引用d3库-->
<script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
<svg></svg>
<div></div>
<script></script>
</body>
</html>
第二步 准备原始数据
准备数据,可以是JSON字符串、JS对象或者JS数组。在开发测试阶段可以直接使用常量,在实际运行阶段应该由前端向后端发送AJAX请求,以获得数据。
在<script>
标签内写入javaScript代码,定义原始数据
//第二步:准备数据,可以是JSON字符串、JS对象或者JS数组
var str = '[{"id":1001,"state":"Alabama","county":"Autauga County","rate":5.1},{"id":1003,"state":"Alabama","county":"Baldwin County","rate":4.9},{"id":1005,"state":"Alabama","county":"Barbour County","rate":8.6},{"id":1007,"state":"Alabama","county":"Bibb County","rate":6.2},{"id":1009,"state":"Alabama","county":"Blount County","rate":5.1},{"id":1011,"state":"Alabama","county":"Bullock County","rate":7.1},{"id":1013,"state":"Alabama","county":"Butler County","rate":6.7},{"id":1015,"state":"Alabama","county":"Calhoun County","rate":6.1},{"id":1017,"state":"Alabama","county":"Chambers County","rate":5},{"id":1019,"state":"Alabama","county":"Cherokee County","rate":5},{"id":1021,"state":"Alabama","county":"Chilton County","rate":5.2},{"id":1023,"state":"Alabama","county":"Choctaw County","rate":7.9},{"id":1025,"state":"Alabama","county":"Clarke County","rate":11.1},{"id":1027,"state":"Alabama","county":"Clay County","rate":5.9},{"id":1029,"state":"Alabama","county":"Cleburne County","rate":5.5},{"id":1031,"state":"Alabama","county":"Coffee County","rate":5.6},{"id":1033,"state":"Alabama","county":"Colbert County","rate":6.5},{"id":1035,"state":"Alabama","county":"Conecuh County","rate":7.7},{"id":1037,"state":"Alabama","county":"Coosa County","rate":5.7},{"id":1039,"state":"Alabama","county":"Covington County","rate":6.7},{"id":1041,"state":"Alabama","county":"Crenshaw County","rate":5.7},{"id":1043,"state":"Alabama","county":"Cullman County","rate":4.8},{"id":1045,"state":"Alabama","county":"Dale County","rate":5.6},{"id":1047,"state":"Alabama","county":"Dallas County","rate":9.5},{"id":1049,"state":"Alabama","county":"DeKalb County","rate":5.7},{"id":1051,"state":"Alabama","county":"Elmore County","rate":4.7},{"id":1053,"state":"Alabama","county":"Escambia County","rate":6.3},{"id":1055,"state":"Alabama","county":"Etowah County","rate":5.7},{"id":1057,"state":"Alabama","county":"Fayette County","rate":6.6},{"id":1059,"state":"Alabama","county":"Franklin County","rate":5.5},{"id":1061,"state":"Alabama","county":"Geneva County","rate":5.4},{"id":1063,"state":"Alabama","county":"Greene County","rate":9.3},{"id":1065,"state":"Alabama","county":"Hale County","rate":7.6},{"id":1067,"state":"Alabama","county":"Henry County","rate":6.3},{"id":1069,"state":"Alabama","county":"Houston County","rate":5.6},{"id":1071,"state":"Alabama","county":"Jackson County","rate":5.9},{"id":1073,"state":"Alabama","county":"Jefferson County","rate":5.5},{"id":1075,"state":"Alabama","county":"Lamar County","rate":5.2},{"id":1077,"state":"Alabama","county":"Lauderdale County","rate":6},{"id":1079,"state":"Alabama","county":"Lawrence County","rate":6.4},{"id":1081,"state":"Alabama","county":"Lee County","rate":4.9},{"id":1083,"state":"Alabama","county":"Limestone County","rate":5},{"id":1085,"state":"Alabama","county":"Lowndes County","rate":10.3},{"id":1087,"state":"Alabama","county":"Macon County","rate":7.2},{"id":1089,"state":"Alabama","county":"Madison County","rate":4.9},{"id":1091,"state":"Alabama","county":"Marengo County","rate":6.9},{"id":1093,"state":"Alabama","county":"Marion County","rate":6.1},{"id":1095,"state":"Alabama","county":"Marshall County","rate":5.1},{"id":1097,"state":"Alabama","county":"Mobile County","rate":6.5},{"id":1099,"state":"Alabama","county":"Monroe County","rate":8.6},{"id":1101,"state":"Alabama","county":"Montgomery County","rate":5.6},{"id":1103,"state":"Alabama","county":"Morgan County","rate":5.2},{"id":1105,"state":"Alabama","county":"Perry County","rate":10.9},{"id":1107,"state":"Alabama","county":"Pickens County","rate":6.7},{"id":1109,"state":"Alabama","county":"Pike County","rate":6.4},{"id":1111,"state":"Alabama","county":"Randolph County","rate":5.7},{"id":1113,"state":"Alabama","county":"Russell County","rate":5.3},{"id":1115,"state":"Alabama","county":"St. Clair County","rate":5},{"id":1117,"state":"Alabama","county":"Shelby County","rate":4.2},{"id":1119,"state":"Alabama","county":"Sumter County","rate":7.3},{"id":1121,"state":"Alabama","county":"Talladega County","rate":6.4},{"id":1123,"state":"Alabama","county":"Tallapoosa County","rate":5.1},{"id":1125,"state":"Alabama","county":"Tuscaloosa County","rate":5.5},{"id":1127,"state":"Alabama","county":"Walker County","rate":7.2},{"id":1129,"state":"Alabama","county":"Washington County","rate":8.3},{"id":1131,"state":"Alabama","county":"Wilcox County","rate":13.9},{"id":1133,"state":"Alabama","county":"Winston County","rate":7},{"id":2013,"state":"Alaska","county":"Aleutians East Borough","rate":1.9},{"id":2016,"state":"Alaska","county":"Aleutians West Census Area","rate":2.2},{"id":2020,"state":"Alaska","county":"Anchorage Municipality","rate":5},{"id":2050,"state":"Alaska","county":"Bethel Census Area","rate":14.1},{"id":2060,"state":"Alaska","county":"Bristol Bay Borough","rate":5.6},{"id":2068,"state":"Alaska","county":"Denali Borough","rate":3.2},{"id":2070,"state":"Alaska","county":"Dillingham Census Area","rate":8.1},{"id":2090,"state":"Alaska","county":"Fairbanks North Star Borough","rate":4.9},{"id":2100,"state":"Alaska","county":"Haines Borough","rate":5.9},{"id":2105,"state":"Alaska","county":"Hoonah-Angoon Census Area","rate":7.3},{"id":2110,"state":"Alaska","county":"Juneau City and Borough","rate":3.6},{"id":2122,"state":"Alaska","county":"Kenai Peninsula Borough","rate":6.9},{"id":2130,"state":"Alaska","county":"Ketchikan Gateway Borough","rate":4.4},{"id":2150,"state":"Alaska","county":"Kodiak Island Borough","rate":4.8},{"id":2158,"state":"Alaska","county":"Kusilvak Census Area","rate":21.7},{"id":2164,"state":"Alaska","county":"Lake and Peninsula Borough","rate":9.2},{"id":2170,"state":"Alaska","county":"Matanuska-Susitna Borough","rate":7.4},{"id":2180,"state":"Alaska","county":"Nome Census Area","rate":13.6},{"id":2185,"state":"Alaska","county":"North Slope Borough","rate":6.9},{"id":2188,"state":"Alaska","county":"Northwest Arctic Borough","rate":16.5},{"id":2195,"state":"Alaska","county":"Petersburg Census Area","rate":5.7},{"id":2198,"state":"Alaska","county":"Prince of Wales-Hyder Census Area","rate":9.4},{"id":2220,"state":"Alaska","county":"Sitka City and Borough","rate":3},{"id":2230,"state":"Alaska","county":"Skagway Municipality","rate":3},{"id":2240,"state":"Alaska","county":"Southeast Fairbanks Census Area","rate":8.7},{"id":2261,"state":"Alaska","county":"Valdez-Cordova Census Area","rate":5.4},{"id":2275,"state":"Alaska","county":"Wrangell City and Borough","rate":5.4},{"id":2282,"state":"Alaska","county":"Yakutat City and Borough","rate":5.8},{"id":2290,"state":"Alaska","county":"Yukon-Koyukuk Census Area","rate":16.4},{"id":4001,"state":"Arizona","county":"Apache County","rate":11.8},{"id":4003,"state":"Arizona","county":"Cochise County","rate":6.5},{"id":4005,"state":"Arizona","county":"Coconino County","rate":6.4},{"id":4007,"state":"Arizona","county":"Gila County","rate":7.6},{"id":4009,"state":"Arizona","county":"Graham County","rate":7.3},{"id":4011,"state":"Arizona","county":"Greenlee County","rate":7.7},{"id":4012,"state":"Arizona","county":"La Paz County","rate":6.6},{"id":4013,"state":"Arizona","county":"Maricopa County","rate":4.9},{"id":4015,"state":"Arizona","county":"Mohave County","rate":7},{"id":4017,"state":"Arizona","county":"Navajo County","rate":8.5},{"id":4019,"state":"Arizona","county":"Pima County","rate":5.4},{"id":4021,"state":"Arizona","county":"Pinal County","rate":5.9},{"id":4023,"state":"Arizona","county":"Santa Cruz County","rate":13},{"id":4025,"state":"Arizona","county":"Yavapai County","rate":5},{"id":4027,"state":"Arizona","county":"Yuma County","rate":24.4},{"id":5001,"state":"Arkansas","county":"Arkansas County","rate":3.2},{"id":5003,"state":"Arkansas","county":"Ashley County","rate":6.3},{"id":5005,"state":"Arkansas","county":"Baxter County","rate":4.1},{"id":5007,"state":"Arkansas","county":"Benton County","rate":2.7},{"id":5009,"state":"Arkansas","county":"Boone County","rate":3.3},{"id":5011,"state":"Arkansas","county":"Bradley County","rate":5.9},{"id":5013,"state":"Arkansas","county":"Calhoun County","rate":5.1},{"id":5015,"state":"Arkansas","county":"Carroll County","rate":2.8},{"id":5017,"state":"Arkansas","county":"Chicot County","rate":6},{"id":5019,"state":"Arkansas","county":"Clark County","rate":4.5},{"id":5021,"state":"Arkansas","county":"Clay County","rate":5},{"id":5023,"state":"Arkansas","county":"Cleburne County","rate":5.7},{"id":5025,"state":"Arkansas","county":"Cleveland County","rate":4.4},{"id":5027,"state":"Arkansas","county":"Columbia County","rate":5.7},{"id":5029,"state":"Arkansas","county":"Conway County","rate":5.9},{"id":5031,"state":"Arkansas","county":"Craighead County","rate":3.1},{"id":5033,"state":"Arkansas","county":"Crawford County","rate":3.7},{"id":5035,"state":"Arkansas","county":"Crittenden County","rate":4.4},{"id":5037,"state":"Arkansas","county":"Cross County","rate":3.9},{"id":5039,"state":"Arkansas","county":"Dallas County","rate":5},{"id":5041,"state":"Arkansas","county":"Desha County","rate":5.1},{"id":5043,"state":"Arkansas","county":"Drew County","rate":5.7},{"id":5045,"state":"Arkansas","county":"Faulkner County","rate":3.7},{"id":5047,"state":"Arkansas","county":"Franklin County","rate":3.9},{"id":5049,"state":"Arkansas","county":"Fulton County","rate":3.9},{"id":5051,"state":"Arkansas","county":"Garland County","rate":4},{"id":5053,"state":"Arkansas","county":"Grant County","rate":3.2},{"id":5055,"state":"Arkansas","county":"Greene County","rate":4},{"id":5057,"state":"Arkansas","county":"Hempstead County","rate":3.7},{"id":5059,"state":"Arkansas","county":"Hot Spring County","rate":3.6},{"id":5061,"state":"Arkansas","county":"Howard County","rate":3.4},{"id":5063,"state":"Arkansas","county":"Independence County","rate":5},{"id":5065,"state":"Arkansas","county":"Izard County","rate":5.3},{"id":5067,"state":"Arkansas","county":"Jackson County","rate":5.9}]'
第三步 定义绘图方法
其实质是定义了一个函数,输入原始数据与一些设置,输出SVG对象。一般可在官网寻找与自己项目相关的案例
//第三步:定义图像绘制方式,可以在官网上寻找案例
// https://observablehq.com/@d3/histogram
function Histogram(data, {
value = d => d, // convenience alias for x
domain, // convenience alias for xDomain
label, // convenience alias for xLabel
format, // convenience alias for xFormat
type = d3.scaleLinear, // convenience alias for xType
x = value, // given d in data, returns the (quantitative) x-value
y = () => 1, // given d in data, returns the (quantitative) weight
thresholds = 40, // approximate number of bins to generate, or threshold function
normalize, // whether to normalize values to a total of 100%
marginTop = 20, // top margin, in pixels
marginRight = 30, // right margin, in pixels
marginBottom = 30, // bottom margin, in pixels
marginLeft = 40, // left margin, in pixels
width = 640, // outer width of chart, in pixels
height = 400, // outer height of chart, in pixels
insetLeft = 0.5, // inset left edge of bar
insetRight = 0.5, // inset right edge of bar
xType = type, // type of x-scale
xDomain = domain, // [xmin, xmax]
xRange = [marginLeft, width - marginRight], // [left, right]
xLabel = label, // a label for the x-axis
xFormat = format, // a format specifier string for the x-axis
yType = d3.scaleLinear, // type of y-scale
yDomain, // [ymin, ymax]
yRange = [height - marginBottom, marginTop], // [bottom, top]
yLabel = "↑ Frequency", // a label for the y-axis
yFormat = normalize ? "%" : undefined, // a format specifier string for the y-axis
color = "currentColor" // bar fill color
} = {}) {
// Compute values.
const X = d3.map(data, x);
const Y0 = d3.map(data, y);
const I = d3.range(X.length);
// Compute bins.
const bins = d3.bin().thresholds(thresholds).value(i => X[i])(I);
const Y = Array.from(bins, I => d3.sum(I, i => Y0[i]));
if (normalize) {
const total = d3.sum(Y);
for (let i = 0; i < Y.length; ++i) Y[i] /= total;
}
// Compute default domains.
if (xDomain === undefined) xDomain = [bins[0].x0, bins[bins.length - 1].x1];
if (yDomain === undefined) yDomain = [0, d3.max(Y)];
// Construct scales and axes.
const xScale = xType(xDomain, xRange);
const yScale = yType(yDomain, yRange);
const xAxis = d3.axisBottom(xScale).ticks(width / 80, xFormat).tickSizeOuter(0);
const yAxis = d3.axisLeft(yScale).ticks(height / 40, yFormat);
yFormat = yScale.tickFormat(100, yFormat);
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.attr("style", "max-width: 100%; height: auto; height: intrinsic;");
svg.append("g")
.attr("transform", `translate(${marginLeft},0)`)
.call(yAxis)
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick line").clone()
.attr("x2", width - marginLeft - marginRight)
.attr("stroke-opacity", 0.1))
.call(g => g.append("text")
.attr("x", -marginLeft)
.attr("y", 10)
.attr("fill", "currentColor")
.attr("text-anchor", "start")
.text(yLabel));
svg.append("g")
.attr("fill", color)
.selectAll("rect")
.data(bins)
.join("rect")
.attr("x", d => xScale(d.x0) + insetLeft)
.attr("width", d => Math.max(0, xScale(d.x1) - xScale(d.x0) - insetLeft - insetRight))
.attr("y", (d, i) => yScale(Y[i]))
.attr("height", (d, i) => yScale(0) - yScale(Y[i]))
.append("title")
.text((d, i) => [`${d.x0} ≤ x < ${d.x1}`, yFormat(Y[i])].join("\n"));
svg.append("g")
.attr("transform", `translate(0,${height - marginBottom})`)
.call(xAxis)
.call(g => g.append("text")
.attr("x", width - marginRight)
.attr("y", 27)
.attr("fill", "currentColor")
.attr("text-anchor", "end")
.text(xLabel));
return svg.node();
}
第四步 开始画图
调用第三步定义的函数,得到SVG对象
//第四步:开始画图,得到SVG对象
var char = Histogram(JSON.parse(str), {
value: d => d.rate,
label: "Unemployment rate (%) →",
width: 500,
height: 500,
color: "steelblue"
})
第五步 将SVG对象添加到html网页中
char
变量的outerHTML
属性就是SVG
字符串
//第五步:将SVG对象追加到html网页中
d3.select("div").html(char.outerHTML);
完整代码
<!DOCTYPE html>
<html>
<head>
<!--第一步:引用d3库-->
<script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
<svg></svg>
<div></div>
<script>
//第二步:准备数据,可以是JSON字符串、JS对象或者JS数组
var str = '[{"id":1001,"state":"Alabama","county":"Autauga County","rate":5.1},{"id":1003,"state":"Alabama","county":"Baldwin County","rate":4.9},{"id":1005,"state":"Alabama","county":"Barbour County","rate":8.6},{"id":1007,"state":"Alabama","county":"Bibb County","rate":6.2},{"id":1009,"state":"Alabama","county":"Blount County","rate":5.1},{"id":1011,"state":"Alabama","county":"Bullock County","rate":7.1},{"id":1013,"state":"Alabama","county":"Butler County","rate":6.7},{"id":1015,"state":"Alabama","county":"Calhoun County","rate":6.1},{"id":1017,"state":"Alabama","county":"Chambers County","rate":5},{"id":1019,"state":"Alabama","county":"Cherokee County","rate":5},{"id":1021,"state":"Alabama","county":"Chilton County","rate":5.2},{"id":1023,"state":"Alabama","county":"Choctaw County","rate":7.9},{"id":1025,"state":"Alabama","county":"Clarke County","rate":11.1},{"id":1027,"state":"Alabama","county":"Clay County","rate":5.9},{"id":1029,"state":"Alabama","county":"Cleburne County","rate":5.5},{"id":1031,"state":"Alabama","county":"Coffee County","rate":5.6},{"id":1033,"state":"Alabama","county":"Colbert County","rate":6.5},{"id":1035,"state":"Alabama","county":"Conecuh County","rate":7.7},{"id":1037,"state":"Alabama","county":"Coosa County","rate":5.7},{"id":1039,"state":"Alabama","county":"Covington County","rate":6.7},{"id":1041,"state":"Alabama","county":"Crenshaw County","rate":5.7},{"id":1043,"state":"Alabama","county":"Cullman County","rate":4.8},{"id":1045,"state":"Alabama","county":"Dale County","rate":5.6},{"id":1047,"state":"Alabama","county":"Dallas County","rate":9.5},{"id":1049,"state":"Alabama","county":"DeKalb County","rate":5.7},{"id":1051,"state":"Alabama","county":"Elmore County","rate":4.7},{"id":1053,"state":"Alabama","county":"Escambia County","rate":6.3},{"id":1055,"state":"Alabama","county":"Etowah County","rate":5.7},{"id":1057,"state":"Alabama","county":"Fayette County","rate":6.6},{"id":1059,"state":"Alabama","county":"Franklin County","rate":5.5},{"id":1061,"state":"Alabama","county":"Geneva County","rate":5.4},{"id":1063,"state":"Alabama","county":"Greene County","rate":9.3},{"id":1065,"state":"Alabama","county":"Hale County","rate":7.6},{"id":1067,"state":"Alabama","county":"Henry County","rate":6.3},{"id":1069,"state":"Alabama","county":"Houston County","rate":5.6},{"id":1071,"state":"Alabama","county":"Jackson County","rate":5.9},{"id":1073,"state":"Alabama","county":"Jefferson County","rate":5.5},{"id":1075,"state":"Alabama","county":"Lamar County","rate":5.2},{"id":1077,"state":"Alabama","county":"Lauderdale County","rate":6},{"id":1079,"state":"Alabama","county":"Lawrence County","rate":6.4},{"id":1081,"state":"Alabama","county":"Lee County","rate":4.9},{"id":1083,"state":"Alabama","county":"Limestone County","rate":5},{"id":1085,"state":"Alabama","county":"Lowndes County","rate":10.3},{"id":1087,"state":"Alabama","county":"Macon County","rate":7.2},{"id":1089,"state":"Alabama","county":"Madison County","rate":4.9},{"id":1091,"state":"Alabama","county":"Marengo County","rate":6.9},{"id":1093,"state":"Alabama","county":"Marion County","rate":6.1},{"id":1095,"state":"Alabama","county":"Marshall County","rate":5.1},{"id":1097,"state":"Alabama","county":"Mobile County","rate":6.5},{"id":1099,"state":"Alabama","county":"Monroe County","rate":8.6},{"id":1101,"state":"Alabama","county":"Montgomery County","rate":5.6},{"id":1103,"state":"Alabama","county":"Morgan County","rate":5.2},{"id":1105,"state":"Alabama","county":"Perry County","rate":10.9},{"id":1107,"state":"Alabama","county":"Pickens County","rate":6.7},{"id":1109,"state":"Alabama","county":"Pike County","rate":6.4},{"id":1111,"state":"Alabama","county":"Randolph County","rate":5.7},{"id":1113,"state":"Alabama","county":"Russell County","rate":5.3},{"id":1115,"state":"Alabama","county":"St. Clair County","rate":5},{"id":1117,"state":"Alabama","county":"Shelby County","rate":4.2},{"id":1119,"state":"Alabama","county":"Sumter County","rate":7.3},{"id":1121,"state":"Alabama","county":"Talladega County","rate":6.4},{"id":1123,"state":"Alabama","county":"Tallapoosa County","rate":5.1},{"id":1125,"state":"Alabama","county":"Tuscaloosa County","rate":5.5},{"id":1127,"state":"Alabama","county":"Walker County","rate":7.2},{"id":1129,"state":"Alabama","county":"Washington County","rate":8.3},{"id":1131,"state":"Alabama","county":"Wilcox County","rate":13.9},{"id":1133,"state":"Alabama","county":"Winston County","rate":7},{"id":2013,"state":"Alaska","county":"Aleutians East Borough","rate":1.9},{"id":2016,"state":"Alaska","county":"Aleutians West Census Area","rate":2.2},{"id":2020,"state":"Alaska","county":"Anchorage Municipality","rate":5},{"id":2050,"state":"Alaska","county":"Bethel Census Area","rate":14.1},{"id":2060,"state":"Alaska","county":"Bristol Bay Borough","rate":5.6},{"id":2068,"state":"Alaska","county":"Denali Borough","rate":3.2},{"id":2070,"state":"Alaska","county":"Dillingham Census Area","rate":8.1},{"id":2090,"state":"Alaska","county":"Fairbanks North Star Borough","rate":4.9},{"id":2100,"state":"Alaska","county":"Haines Borough","rate":5.9},{"id":2105,"state":"Alaska","county":"Hoonah-Angoon Census Area","rate":7.3},{"id":2110,"state":"Alaska","county":"Juneau City and Borough","rate":3.6},{"id":2122,"state":"Alaska","county":"Kenai Peninsula Borough","rate":6.9},{"id":2130,"state":"Alaska","county":"Ketchikan Gateway Borough","rate":4.4},{"id":2150,"state":"Alaska","county":"Kodiak Island Borough","rate":4.8},{"id":2158,"state":"Alaska","county":"Kusilvak Census Area","rate":21.7},{"id":2164,"state":"Alaska","county":"Lake and Peninsula Borough","rate":9.2},{"id":2170,"state":"Alaska","county":"Matanuska-Susitna Borough","rate":7.4},{"id":2180,"state":"Alaska","county":"Nome Census Area","rate":13.6},{"id":2185,"state":"Alaska","county":"North Slope Borough","rate":6.9},{"id":2188,"state":"Alaska","county":"Northwest Arctic Borough","rate":16.5},{"id":2195,"state":"Alaska","county":"Petersburg Census Area","rate":5.7},{"id":2198,"state":"Alaska","county":"Prince of Wales-Hyder Census Area","rate":9.4},{"id":2220,"state":"Alaska","county":"Sitka City and Borough","rate":3},{"id":2230,"state":"Alaska","county":"Skagway Municipality","rate":3},{"id":2240,"state":"Alaska","county":"Southeast Fairbanks Census Area","rate":8.7},{"id":2261,"state":"Alaska","county":"Valdez-Cordova Census Area","rate":5.4},{"id":2275,"state":"Alaska","county":"Wrangell City and Borough","rate":5.4},{"id":2282,"state":"Alaska","county":"Yakutat City and Borough","rate":5.8},{"id":2290,"state":"Alaska","county":"Yukon-Koyukuk Census Area","rate":16.4},{"id":4001,"state":"Arizona","county":"Apache County","rate":11.8},{"id":4003,"state":"Arizona","county":"Cochise County","rate":6.5},{"id":4005,"state":"Arizona","county":"Coconino County","rate":6.4},{"id":4007,"state":"Arizona","county":"Gila County","rate":7.6},{"id":4009,"state":"Arizona","county":"Graham County","rate":7.3},{"id":4011,"state":"Arizona","county":"Greenlee County","rate":7.7},{"id":4012,"state":"Arizona","county":"La Paz County","rate":6.6},{"id":4013,"state":"Arizona","county":"Maricopa County","rate":4.9},{"id":4015,"state":"Arizona","county":"Mohave County","rate":7},{"id":4017,"state":"Arizona","county":"Navajo County","rate":8.5},{"id":4019,"state":"Arizona","county":"Pima County","rate":5.4},{"id":4021,"state":"Arizona","county":"Pinal County","rate":5.9},{"id":4023,"state":"Arizona","county":"Santa Cruz County","rate":13},{"id":4025,"state":"Arizona","county":"Yavapai County","rate":5},{"id":4027,"state":"Arizona","county":"Yuma County","rate":24.4},{"id":5001,"state":"Arkansas","county":"Arkansas County","rate":3.2},{"id":5003,"state":"Arkansas","county":"Ashley County","rate":6.3},{"id":5005,"state":"Arkansas","county":"Baxter County","rate":4.1},{"id":5007,"state":"Arkansas","county":"Benton County","rate":2.7},{"id":5009,"state":"Arkansas","county":"Boone County","rate":3.3},{"id":5011,"state":"Arkansas","county":"Bradley County","rate":5.9},{"id":5013,"state":"Arkansas","county":"Calhoun County","rate":5.1},{"id":5015,"state":"Arkansas","county":"Carroll County","rate":2.8},{"id":5017,"state":"Arkansas","county":"Chicot County","rate":6},{"id":5019,"state":"Arkansas","county":"Clark County","rate":4.5},{"id":5021,"state":"Arkansas","county":"Clay County","rate":5},{"id":5023,"state":"Arkansas","county":"Cleburne County","rate":5.7},{"id":5025,"state":"Arkansas","county":"Cleveland County","rate":4.4},{"id":5027,"state":"Arkansas","county":"Columbia County","rate":5.7},{"id":5029,"state":"Arkansas","county":"Conway County","rate":5.9},{"id":5031,"state":"Arkansas","county":"Craighead County","rate":3.1},{"id":5033,"state":"Arkansas","county":"Crawford County","rate":3.7},{"id":5035,"state":"Arkansas","county":"Crittenden County","rate":4.4},{"id":5037,"state":"Arkansas","county":"Cross County","rate":3.9},{"id":5039,"state":"Arkansas","county":"Dallas County","rate":5},{"id":5041,"state":"Arkansas","county":"Desha County","rate":5.1},{"id":5043,"state":"Arkansas","county":"Drew County","rate":5.7},{"id":5045,"state":"Arkansas","county":"Faulkner County","rate":3.7},{"id":5047,"state":"Arkansas","county":"Franklin County","rate":3.9},{"id":5049,"state":"Arkansas","county":"Fulton County","rate":3.9},{"id":5051,"state":"Arkansas","county":"Garland County","rate":4},{"id":5053,"state":"Arkansas","county":"Grant County","rate":3.2},{"id":5055,"state":"Arkansas","county":"Greene County","rate":4},{"id":5057,"state":"Arkansas","county":"Hempstead County","rate":3.7},{"id":5059,"state":"Arkansas","county":"Hot Spring County","rate":3.6},{"id":5061,"state":"Arkansas","county":"Howard County","rate":3.4},{"id":5063,"state":"Arkansas","county":"Independence County","rate":5},{"id":5065,"state":"Arkansas","county":"Izard County","rate":5.3},{"id":5067,"state":"Arkansas","county":"Jackson County","rate":5.9}]'
//第三步:定义图像绘制方式,可以在官网上寻找案例
// https://observablehq.com/@d3/histogram
function Histogram(data, {
value = d => d, // convenience alias for x
domain, // convenience alias for xDomain
label, // convenience alias for xLabel
format, // convenience alias for xFormat
type = d3.scaleLinear, // convenience alias for xType
x = value, // given d in data, returns the (quantitative) x-value
y = () => 1, // given d in data, returns the (quantitative) weight
thresholds = 40, // approximate number of bins to generate, or threshold function
normalize, // whether to normalize values to a total of 100%
marginTop = 20, // top margin, in pixels
marginRight = 30, // right margin, in pixels
marginBottom = 30, // bottom margin, in pixels
marginLeft = 40, // left margin, in pixels
width = 640, // outer width of chart, in pixels
height = 400, // outer height of chart, in pixels
insetLeft = 0.5, // inset left edge of bar
insetRight = 0.5, // inset right edge of bar
xType = type, // type of x-scale
xDomain = domain, // [xmin, xmax]
xRange = [marginLeft, width - marginRight], // [left, right]
xLabel = label, // a label for the x-axis
xFormat = format, // a format specifier string for the x-axis
yType = d3.scaleLinear, // type of y-scale
yDomain, // [ymin, ymax]
yRange = [height - marginBottom, marginTop], // [bottom, top]
yLabel = "↑ Frequency", // a label for the y-axis
yFormat = normalize ? "%" : undefined, // a format specifier string for the y-axis
color = "currentColor" // bar fill color
} = {}) {
// Compute values.
const X = d3.map(data, x);
const Y0 = d3.map(data, y);
const I = d3.range(X.length);
// Compute bins.
const bins = d3.bin().thresholds(thresholds).value(i => X[i])(I);
const Y = Array.from(bins, I => d3.sum(I, i => Y0[i]));
if (normalize) {
const total = d3.sum(Y);
for (let i = 0; i < Y.length; ++i) Y[i] /= total;
}
// Compute default domains.
if (xDomain === undefined) xDomain = [bins[0].x0, bins[bins.length - 1].x1];
if (yDomain === undefined) yDomain = [0, d3.max(Y)];
// Construct scales and axes.
const xScale = xType(xDomain, xRange);
const yScale = yType(yDomain, yRange);
const xAxis = d3.axisBottom(xScale).ticks(width / 80, xFormat).tickSizeOuter(0);
const yAxis = d3.axisLeft(yScale).ticks(height / 40, yFormat);
yFormat = yScale.tickFormat(100, yFormat);
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.attr("style", "max-width: 100%; height: auto; height: intrinsic;");
svg.append("g")
.attr("transform", `translate(${marginLeft},0)`)
.call(yAxis)
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick line").clone()
.attr("x2", width - marginLeft - marginRight)
.attr("stroke-opacity", 0.1))
.call(g => g.append("text")
.attr("x", -marginLeft)
.attr("y", 10)
.attr("fill", "currentColor")
.attr("text-anchor", "start")
.text(yLabel));
svg.append("g")
.attr("fill", color)
.selectAll("rect")
.data(bins)
.join("rect")
.attr("x", d => xScale(d.x0) + insetLeft)
.attr("width", d => Math.max(0, xScale(d.x1) - xScale(d.x0) - insetLeft - insetRight))
.attr("y", (d, i) => yScale(Y[i]))
.attr("height", (d, i) => yScale(0) - yScale(Y[i]))
.append("title")
.text((d, i) => [`${d.x0} ≤ x < ${d.x1}`, yFormat(Y[i])].join("\n"));
svg.append("g")
.attr("transform", `translate(0,${height - marginBottom})`)
.call(xAxis)
.call(g => g.append("text")
.attr("x", width - marginRight)
.attr("y", 27)
.attr("fill", "currentColor")
.attr("text-anchor", "end")
.text(xLabel));
return svg.node();
}
//第四步:开始画图,得到SVG对象
var chart = Histogram(JSON.parse(str), {
value: d => d.rate,
label: "Unemployment rate (%) →",
width: 500,
height: 500,
color: "steelblue"
})
//第五步:将SVG对象追加到html网页中
d3.select("div").html(chart.outerHTML);
</script>
</body>
</html>
运行结果
使用浏览器打开html文件,可得如下结果