起始:
最近由于公司项目要求,揭示板界面重构,要适配70寸、55寸等的安卓5.1、4.4版本等的1G内存电视正常显示。经过内存占用筛选,确定用d3.js去替换以前的canvas+fabric.min.js,减少内存占用;因为之前的界面定时刷新会导致内存占用越来越大,从而崩掉;替换后内存占用由原来的670M左右减低并稳定在340M左右,降低了一倍左右,并且稳定性更好,渲染界面更快。
内存占用(MB)测试:
(1)直接打开谷歌:433~296,297.1
(2)html+css+js 谷歌打开此网页:452->359 再次刷新此网页:415->370 多次刷新:383->349
(3)svg 谷歌打开此网页:369->237 再次刷新此网页:308->250 多次刷新:307->256
(4)d3.js 谷歌打开此网页:356->241 再次刷新此网页:314->241 多次刷新:312->250
(5)揭示板打开此网页(新-d3):506->336, 306.7 再次刷新此网页:430->316; 404->309 多次刷新:412->318; 407->313.6
(5-1)揭示板打开此网页(新-d3,加上定时刷新):506->386 再次刷新此网页:392->362 多次刷新:423->368,等一段时间444
(5-2)揭示板打开此网页(新-d3,完整的-加上定时刷新):464->335 再次刷新此网页:393->337 多次刷新:452->343,等一段时间335.1
(5-3)揭示板页面打开了40分钟(调试): 不去股道操作:XX分钟前294,XX分钟后158.6 股道操作,改变数据:340->296.9,等一段时间293.2, 273.7
(6)揭示板打开此网页(旧-canvas):594->506 再次刷新此网页:549->657 多次刷新:694->661
svg - polygon:
- 左上角: 距离外部svg左边的距离 距离上边的距离
- 左下角: 距离左边的距离 距离上边的距离
- 右下角 距离左边的距离 距离上边的距离
- 右上角 距离左边的距离 距离上边的距离
下面是操手之前在网上找到文档,花了一些时间了解和实践。
- d3.v3.js
- alignedleft.com/tutorials/d…
斯科特·默里(Scott Murray)D3教程
引用
<script type="text/javascript" src="d3/d3.v3.js"></script>
添加元素
d3.select("body").append("p").text("New paragraph!");
链接方式
d3.select("body")
.append("p")
.text("New paragraph!");
去无链
var body = d3.select("body");
var p = body.append("p");
p.text("New paragraph!");
绑定数据
1.数据
var dataset = [ 5, 10, 15, 20, 25 ];
2.DOM元素的选择
d3.select("body").selectAll("p")
.data(dataset)
.enter()
.append("p")
.text("New paragraph!");
.selectAll("p")—选择DOM中的所有段落。由于尚不存在,因此将返回一个空选择。将这个空的选择视为代表即将存在的段落。
.data(dataset)—计算并解析我们的数据值。我们的数据集中有五个值,因此,此点之后的所有操作都会执行五次,每个值一次。
.enter()—要创建新的数据绑定元素,必须使用enter()。此方法先查看DOM,然后再查看传递给它的数据。如果数据值多于相应的DOM元素,则enter() 创建一个新的占位符元素,您可以在上面处理魔术。然后,它将对这个新占位符的引用移交给链中的下一步。
.append("p")—接受由创建的占位符选择enter(),并将p元素插入DOM。万岁!然后,它将对刚创建的元素的引用交给链中的下一步。
.text("New paragraph!")—引用新创建的内容p并插入文本值。
数据在哪里?
console.log(d3.selectAll("p"))
打印: New paragraph! New paragraph! New paragraph! New paragraph! New paragraph!
使用数据
让我们将最后一行更改为:
.text(function(d) { return d; });
打印: 5 10 15 20 25
高功能
如果您不熟悉编写自己的函数(即方法),则函数定义的基本结构为:
function(input_value) {
//Calculate something here
return output_value;
}
我们上面使用的功能非常简单,没什么花哨的
function(d) {
return d;
}
并封装在D3的text()函数中,因此我们函数返回的任何内容都将传递给text()。
.text(function(d) {
return d;
});
想要保留数据
不起作用
.text("I can count up to " + d);
如果不d使用匿名函数,d则没有任何价值。可以将其d视为一个孤独的小占位符值,它只需要一个温暖,包含亲切关怀函数的寄生虫的拥抱即可。
可以改为:
.text(function(d) { // <-- Note tender embrace at left
return "I can count up to " + d;
});
打印: I can count up to 5 I can count up to 10 I can count up to 15 I can count up to 20 I can count up to 25
超越文字
再增加一行
.style("color", "red");
打印:现在所有文字均为红色
.style("color", function(d) {
if (d > 15) { //Threshold of 15
return "red";
} else {
return "black";
}
});
打印:注意前三行是黑色的,但是一旦d超过任意阈值15,文本就会变成红色。
绘图div
开始继续使用我们的简单数据集:
var dataset = [ 5, 10, 15, 20, 25 ];
共享样式放入一个名为的类中bar:
div.bar {
display: inline-block;
width: 20px;
height: 75px; /* We'll override this later */
background-color: teal;
}
或者
div class="bar"></div>
设定属性-attr()
attr()
<p class="caption">
<select id="country">
<img src="logo.png" width="100px" alt="Logo" />
总共包含五个属性(和相应的值),所有这些都可以使用设置attr(): class | caption id | country src | logo.png width | 100px alt | Logo
要给我们的divsa类bar,我们可以使用:
.attr("class", "bar")
课堂笔记-classed()
classed()该方法可用于快速应用元素或从元素中删除类。上面的代码行可以重写为:
.classed("bar", true)
回到bar
div.bar {
display: inline-block;
width: 20px;
height: 75px;
background-color: teal;
}
var dataset = [ 5, 10, 15, 20, 25 ];
d3.select("body").selectAll("div")
.data(dataset)
.enter()
.append("div")
.attr("class", "bar");
打印:您应该看到五个垂直条,为我们数据集中的每个点生成一个垂直条,尽管它们之间没有空格,但它们看起来像一个大矩形。
设定样式-style()
style()
<div style="height: 75px;"></div>
将其添加到D3代码的末尾:
.style("height", function(d) {
return d + "px";
});
打印:当D3遍历每个数据点时,的值d将设置为相应数据点的值。因此,我们将height值设置为d(当前数据值)加上px(以指定单位为像素)。产生的高度将是5px,10px,15px,20px和25px。
把这些条子弄高一些:
.style("height", function(d) {
var barHeight = d * 5; //Scale up by factor of 5
return barHeight + "px";
});
data()的力量
var dataset = [ 25, 7, 5, 26, 11, 8, 25, 14, 23, 19,
14, 11, 22, 29, 11, 13, 12, 17, 18, 10,
24, 18, 25, 9, 3 ];
d3.select("body").selectAll("div")
.data(dataset) // <-- The answer is here!
.enter()
.append("div")
.attr("class", "bar")
.style("height", function(d) {
var barHeight = d * 5;
return barHeight + "px";
});
输入data()十个值,它将循环十次。给它一百万个值,它将循环一百万次。(耐心一点。)
这就是强大的力量data()–足够聪明,可以遍历您向其抛出的任何数据集的全长,在链中执行其下方的每个方法,同时更新每个方法所处的上下文,因此d始终引用当前数据在循环中的那一点。
随机数据
var dataset = []; //Initialize empty array
for (var i = 0; i < 25; i++) { //Loop 25 times
var newNumber = Math.random() * 30; //New random number (0-30)
dataset.push(newNumber); //Add new number to array
}
01.创建一个名为的空数组dataset。 02.启动一个for循环,该循环执行25次。 03.每次,它都会生成一个新的随机数,其值在0到30之间。 04.该新数字将附加到dataset数组中。(push()是一个将新值附加到数组末尾的数组方法。)
console.log(dataset) 。您应该看到25个随机数据值的完整数组。 打印: [29.008557153312662, 27.358102895412994, 1.8531420247113806, 16.458962264131355, 26.23005996178159, 21.423858033433216, 23.02974585678495, 14.492293735898214, 1.4009596341184483, 4.870038095128395, 29.705936448111455, 29.545566415279104, 23.387205995731414, 18.928408390390054, 23.580675188245568, 0.8581797024793425, 22.09853928963049, 8.800467041052556, 9.877315663211355, 2.9875160127928657, 11.943283651942558, 27.60897370588235, 29.809121268489193, 9.074583100012381, 5.488617241879057]
请注意,它们都是十进制或浮点值(14.793717765714973),而不是像我们最初使用的整数或整数(14)。如果您需要整数,则可以使用JavaScript的Math.round()方法。
var newNumber = Math.round(Math.random() * 30);
确实已四舍五入为整数
SVG底漆
使用SVG更可靠,视觉上一致且速度更快。可以使用Illustrator之类的矢量绘图软件来生成SVG文件,但是我们需要学习如何使用代码生成它们。
SVG元素
必须先创建SVG元素,然后才能绘制任何内容。可以将SVG元素视为在其上呈现视觉效果的画布。(在这方面,SVG在概念上类似于HTML的canvas元素。)至少,最好指定width和height值。如果未指定这些内容,则SVG将在其封闭元素中占用尽可能多的空间。
<svg width="500" height="50">
</svg>
另请注意,浏览器假定像素为默认度量单位。我们指定的尺寸500和50,不500px和50px。我们可以指定px明确的,或任意数量的其它支持单位,其中包括em,pt,in,cm,和mm。
简单形状
其中包括rect,circle,ellipse,line,text,和path。 增大的x值向右移动,而增大的y值向下移动。
rect绘制一个矩形。使用x与y指定左上角的坐标,width并height指定尺寸。这个矩形填充了我们SVG的整个空间:
<rect x="0" y="0" width="500" height="50"/>
circle画一个圆。使用cx和cy指定中心的坐标,并r指定半径。该圆位于我们500像素宽的SVG的cx中心,因为其(“ center-x”)值为250。
<circle cx="250" cy="25" r="25"/>
ellipse相似,但需要为每个轴指定单独的半径值。而是r使用rx和ry。
<ellipse cx="250" cy="25" rx="100" ry="25"/>
line画一条线。使用x1与y1指定线的一端的坐标,x2并y2指定另一端的坐标。一个stroke颜色必须为行中指定可见。
<line x1="0" y1="0" x2="500" y2="50" stroke="black"/>
text呈现文本。使用x指定的左边缘的位置,并y指定类型的垂直位置的基线。
<text x="250" y="25">Easy-peasy</text>
text除非另有说明,否则它将继承其父元素的CSS指定的字体样式。 我们可以重写该格式,如下所示:
<text x="250" y="25" font-family="sans-serif" font-size="25" fill="gray">Easy-peasy</text>
设置SVG元素的样式
默认样式是不带笔触的黑色填充。 SVG的常见属性是:
- fill—颜色值。与CSS一样,颜色可以指定为
- 命名的颜色- orange
- 十六进制值-#3388aa或#38a
- RGB值- rgb(10, 150, 20)
- 具有Alpha透明度的RGB — rgba(10, 150, 20, 0.5)
- stroke —颜色值。
- stroke-width —数值测量(通常以像素为单位)。
- opacity —一个介于0.0(完全透明)和1.0(完全不透明)之间的数值。
text:
- font-family
- font-size
与CSS平行的另一种方式是,将样式应用于SVG元素有两种方法:直接(内联)作为元素的属性,或使用CSS样式规则;为CSS样式目标的新类。
分层和绘图顺序
SVG中没有“层”,也没有真正的深度概念。SVG不支持CSS的z-index属性,因此形状只能在二维x / y平面内排列。
透明度
应用透明度的方法有两种:使用带alpha的RGB颜色或设置一个opacity值。
请注意,使用时rgba(),透明度将分别应用于fill和stroke颜色。 要将透明度应用于整个元素,请设置一个opacity属性。
绘制SVG
SVG元素的所有属性都指定为attribute。
<element property="value"/>
创建SVG
d3.select("body").append("svg");
建议:
var svg = d3.select("body").append("svg");
通过创建一个新的变量svg,我们可以捕获交回的参考文献append()。
为了简化您的工作,我建议将width和height值放入代码顶部的变量中
//Width and height
var w = 500;
var h = 50;
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
数据驱动的形状
var dataset = [ 5, 10, 15, 20, 25 ];
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle");
data()遍历每个数据点,circle为每个数据点创建一个. 请记住,selectAll()将返回对所有circles的空引用(尚不存在),data()将我们的数据绑定到我们将要创建的元素,enter()返回对新元素的占位符引用,append()最后circle向DOM中添加a 。
//完整的代码
//Width and height
var w = 500;
var h = 50;
//Data
var dataset = [ 5, 10, 15, 20, 25 ];
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", 500)
.attr("height", 50);
var circles = svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle");
circles.attr("cx", function(d, i) {
return (i * 50) + 25;
})
.attr("cy", h/2)
.attr("r", function(d) {
return d;
});
生成:
<svg width="500" height="50">
<circle cx="25" cy="25" r="5"></circle>
<circle cx="75" cy="25" r="10"></circle>
<circle cx="125" cy="25" r="15"></circle>
<circle cx="175" cy="25" r="20"></circle>
<circle cx="225" cy="25" r="25"></circle>
</svg>
逐步看一下代码:
circles.attr("cx", function(d, i) {
return (i * 50) + 25;
})
(0 * 50) + 25 returns 25 (1 * 50) + 25 returns 75 (2 * 50) + 25 returns 125 (3 * 50) + 25 returns 175 (4 * 50) + 25 returns 225
漂亮的颜色,哦!
.attr("fill", "yellow")
.attr("stroke", "orange")
.attr("stroke-width", function(d) {
return d/2;
});
数据类型
变数
变量是数据,是最小的数据构建块。变量是所有其他数据结构的基础,这些数据结构只是变量的不同配置。 请知道它是一种松散类型的语言,这意味着您不必预先指定将在变量中存储哪种类型的信息。但是,JavaScript会根据您为其分配的信息类型自动键入变量。
数组
var numbers = [ 5, 10, 15, 20, 25 ];
ID | Value
------------
0 | 5
1 | 10
2 | 15
3 | 20
4 | 25
做什么数组()
没有数组和强大的for()循环,基于代码的数据可视化将是不可能的。
for (var i = 0; i < numbers.length; i++) {
console.log(numbers[i]); //Print value to console
}
对象
数组非常适合简单的值列表,但是对于更复杂的数据集,您将需要将数据放入对象中。
var fruit = {
kind: "grape",
color: "red",
quantity: 12,
tasty: true
};
对象+数组
var fruits = [
{
kind: "grape",
color: "red",
quantity: 12,
tasty: true
},
{
kind: "kiwi",
color: "brown",
quantity: 98,
tasty: true
},
{
kind: "banana",
color: "yellow",
quantity: 0,
tasty: true
}
];
JSON格式
var jsonFruit = {
"kind": "grape",
"color": "red",
"quantity": 12,
"tasty": true
};
GeoJSON
正如JSON只是现有JavaScript对象语法的形式化一样,GeoJSON是JSON对象的形式化语法,已针对存储地理数据进行了优化。
var geodata = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [ 150.1282427, -24.471803 ]
},
"properties": {
"type": "town"
}
}
]
};
制作条形图
首先回顾我们之前使用div元素制作的条形图。然后,我们将修改该代码以使用SVG绘制条形图,从而使我们在视觉呈现方面更具灵活性。
新图表
var w = 500;
var h = 100;
var barPadding = 1; // <-- New!
var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13,
11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ];
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", function(d, i) {
return i * (w / dataset.length);
})
.attr("y", function(d) {
return h - (d * 4);
})
.attr("width", w / dataset.length - barPadding)
.attr("height", function(d) {
return d * 4;
});
颜色
.attr("fill", "teal");
使用数据驱动颜色
.attr("fill", function(d) {
return "rgb(0, 0, " + (d * 10) + ")";
});
标签
需要在可视化文件中以文本形式显示实际数据值。
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
将text使用text()方法将代码扩展为在每个元素内包含一个数据值
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d) {
return d;
})
.attr("text-anchor", "middle")
.attr("x", function(d, i) {
return i * (w / dataset.length) + (w / dataset.length - barPadding) / 2;
})
.attr("y", function(d) {
return h - (d * 4) + 14;
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "white");
制作散点图
我们仅绘制了带有简单数据的条形图-只是一维数字集。 但是,当您有两组要相互绘制的值时,则需要第二个维度。散点图是一种常见的可视化类型,在两个不同的轴上代表两组对应的值:水平和垂直,x和y。
数据
var dataset = [
[5, 20], [480, 90], [250, 50], [100, 33], [330, 95],
[410, 12], [475, 44], [25, 67], [85, 21], [220, 88]
];
可以看到这10行中的每行将对应于我们可视化中的一个点。[5, 20]例如,对于row ,我们将其5用作x值,并将其20用于y。
散点图
//Width and height
var w = 500;
var h = 100;
var dataset = [
[5, 20], [480, 90], [250, 50], [100, 33], [330, 95],
[410, 12], [475, 44], [25, 67], [85, 21], [220, 88]
];
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function(d) {
return d[0];
})
.attr("cy", function(d) {
return d[1];
})
.attr("r", 5);
尺寸
.attr("r", function(d) {
return Math.sqrt(h - d[1]);
});
标签
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d) {
return d[0] + "," + d[1];
})
.attr("x", function(d) {
return d[0];
})
.attr("y", function(d) {
return d[1];
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "red");
秤
“比例尺是从输入域映射到输出范围的函数。” D3比例尺是您定义其参数的功能。创建它们后,您可以调用scale函数,将其传递给数据值,然后它很好地返回缩放后的输出值。您可以定义和使用任意多个比例尺。
苹果和像素
var dataset = [ 100, 200, 300, 400, 500 ];
我们一直将数据值直接用作显示值,而忽略了单位差异。因此,如果售出了500个苹果,则相应的条形图将为500像素高。
那可能行得通,但是下个月(卖出600个苹果)又如何呢?一年后,卖出了1800个苹果?您的观众将不得不购买更大的显示器,以便能够看到那些非常高的苹果条的全高!(嗯,苹果棒!)
域和范围
- 输入!领域!
- 输出!范围!
创建一个标度,输入域为100,500,输出范围为10,350。如果您给该刻度定值100,它将返回10。如果你给了它500,它会吐回来的350。
正常化
归一化是根据可能的最小值和最大值将数值映射到介于0和1之间的新值的过程。例如,一年中有365天,则天数310对应于全年的约0.85或85%。
创建比例
通过访问D3的比例尺生成器,d3.scale然后输入所需的比例尺类型。
var scale = d3.scale.linear();
我们可以100,500通过将这些值domain()作为数组传递给方法来将刻度的输入域设置为:
scale.domain([100, 500]);
使用类似的方式设置输出范围range():
scale.range([10, 350]);
这些步骤可以如上所述单独进行,也可以链接成一行代码:
var scale = d3.scale.linear()
.domain([100, 500])
.range([10, 350]);
无论哪种方式,我们的秤都可以使用!
scale(100); //Returns 10
scale(300); //Returns 180
scale(500); //Returns 350
缩放散点图
例如min()和max()快速分析我们的数据集。例如,这循环遍历数组中的每个x值并返回最大的一个值:
var xScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[0]; })])
.range([0, w]);
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[1]; })])
.range([0, h]);
// 返回缩放值(而不是原始值):
.attr("cx", function(d) {
return xScale(d[0]);
})
.attr("cy", function(d) {
return yScale(d[1]);
})
.attr("x", function(d) {
return xScale(d[0]);
})
.attr("y", function(d) {
return yScale(d[1]);
})
完整代码:
//Width and height
var w = 500;
var h = 100;
var dataset = [
[5, 20], [480, 90], [250, 50], [100, 33], [330, 95],
[410, 12], [475, 44], [25, 67], [85, 21], [220, 88]
];
//Create scale functions
var xScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[0]; })])
.range([0, w]);
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[1]; })])
.range([0, h]);
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function(d) {
return xScale(d[0]);
})
.attr("cy", function(d) {
return yScale(d[1]);
})
.attr("r", function(d) {
return Math.sqrt(h - d[1]);
});
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d) {
return d[0] + "," + d[1];
})
.attr("x", function(d) {
return xScale(d[0]);
})
.attr("y", function(d) {
return yScale(d[1]);
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "red");
完善情节
var padding = 20;
//Width and height
var w = 500;
var h = 300;
var padding = 20;
var dataset = [
[5, 20], [480, 90], [250, 50], [100, 33], [330, 95],
[410, 12], [475, 44], [25, 67], [85, 21], [220, 88],
[600, 150]
];
//Create scale functions
var xScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[0]; })])
.range([padding, w - padding * 2]);
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[1]; })])
.range([h - padding, padding]);
var rScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[1]; })])
.range([2, 5]);
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function(d) {
return xScale(d[0]);
})
.attr("cy", function(d) {
return yScale(d[1]);
})
.attr("r", function(d) {
return rScale(d[1]);
});
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d) {
return d[0] + "," + d[1];
})
.attr("x", function(d) {
return xScale(d[0]);
})
.attr("y", function(d) {
return yScale(d[1]);
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "red");
其他方法
d3.scale.linear() 还有其他几种方便的方法,在这里值得一提:
- nice()—这告诉比例尺采用您给定的任何输入域,range()并将两端扩展到最接近的舍入值。“例如,对于[0.20147987687960267,0.996679553296417]的域,好的域是[0.2,1]。”
- rangeRound()—rangeRound()代替使用,range()并且刻度尺输出的所有值都将四舍五入到最接近的整数。如果您希望形状具有精确的像素值,这将很有用,以避免因抗锯齿而产生的模糊边缘。
- clamp()—默认情况下,线性刻度可以返回超出指定范围的值。例如,如果给定值超出其预期的输入域,则小数位将返回也在输出范围之外的数字。.clamp(true)但是,调用刻度会强制所有输出值都在指定范围内。意思是,过多的值将四舍五入到范围的低值或高值(以最接近的那个为准)。
其他秤
除了linear比例尺(上面已讨论过)外,D3还内置了其他几种比例尺方法:
- identity — 1:1比例,主要用于像素值
- sqrt —平方根刻度
- pow —功率秤(对健身房有益)
- log —对数刻度
- quantize —一种线性标度,其输出范围具有离散值,适用于要将数据分类到“存储桶”中的情况
- quantile —与上述类似,但其输入域具有离散值(当您已有“存储桶”时)
- ordinal—序数标度使用非定量值(如类别名称)进行输出;比较苹果和橙子的完美选择
轴数
斧头介绍
与缩放功能很像,D3的轴实际上是您定义其参数的功能。与刻度不同,调用轴函数时,它不返回值,而是生成轴的可视元素,包括线条,标签和刻度线。
请注意,轴功能是特定于SVG的,因为它们生成SVG元素。此外,轴还打算用于定量刻度(与顺序刻度相反)。
设置轴
使用d3.svg.axis()创建一个通用的轴功能:
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
//D3的call()功能将选择作为输入,并将该选择移交给任何功能。call()将该选择移交给该xAxis函数,因此我们的轴在new中生成g。
svg.append("g")
.call(d3.svg.axis()
.scale(xScale)
.orient("bottom"));
清理它
svg.append("g")
.attr("class", "axis") //Assign "axis" class
.call(xAxis);
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
}
我们可以transform将整个轴组推到最下面:
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + (h - padding) + ")")
.call(xAxis);
注意使用(h - padding),因此组的顶部边缘设置为h,整个图像的高度减去padding我们之前创建的值。
检查壁虱
您可以使用以下命令自定义轴的各个方面,从大致的滴答声开始ticks():
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(5); //Set rough # of ticks
为什么不呢?
是时候标记垂直轴了!将其添加到代码顶部附近
//Define Y axis
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.ticks(5);
// 靠近底部的位置:
//Create Y axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + padding + ",0)")
.call(yAxis);
// 请注意,标签将被定向left,并且yAxis组将按g数量转换到右侧padding。
最后的润色
为了向您证明我们的新轴是动态且可扩展的,我想从使用静态数据集切换为使用随机数:
//Dynamic, random dataset
var dataset = [];
var numDataPoints = 50;
var xRange = Math.random() * 1000;
var yRange = Math.random() * 1000;
for (var i = 0; i < numDataPoints; i++) {
var newNumber1 = Math.round(Math.random() * xRange);
var newNumber2 = Math.round(Math.random() * yRange);
dataset.push([newNumber1, newNumber2]);
}
// 该代码初始化一个空数组,然后循环50次,每次选择两个随机数,然后将该对值加(“推”)到dataset数组中。
//完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Demo: Axes</title>
<script type="text/javascript" src="../d3/d3.v3.min.js"></script>
<style type="text/css">
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
}
</style>
</head>
<body>
<script type="text/javascript">
//Width and height
var w = 500;
var h = 300;
var padding = 20;
var dataset = [
[5, 20], [480, 90], [250, 50], [100, 33], [330, 95],
[410, 12], [475, 44], [25, 67], [85, 21], [220, 88],
[600, 150]
];
//Create scale functions
var xScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[0]; })])
.range([padding, w - padding * 2]);
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[1]; })])
.range([h - padding, padding]);
var rScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[1]; })])
.range([2, 5]);
//Define X axis
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Create circles
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function(d) {
return xScale(d[0]);
})
.attr("cy", function(d) {
return yScale(d[1]);
})
.attr("r", function(d) {
return rScale(d[1]);
});
//Create labels
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d) {
return d[0] + "," + d[1];
})
.attr("x", function(d) {
return xScale(d[0]);
})
.attr("y", function(d) {
return yScale(d[1]);
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "red");
//Create X axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + (h - padding) + ")")
.call(xAxis);
</script>
</body>
</html>
格式化刻度标签
我们一直在使用整数-整数-既好又简单。但是数据通常比较混乱,在这种情况下,您可能希望对轴标签的格式进行更多控制。输入tickFormat(),使您可以指定数字的格式。
var formatAsPercentage = d3.format(".1%");
然后,告诉您的轴对其刻度使用该格式化功能,例如:
xAxis.tickFormat(formatAsPercentage);