当前位置: 移动技术网 > IT编程>开发语言>JavaScript > D3.js入门教程之比例尺

D3.js入门教程之比例尺

2019年03月24日  | 移动技术网IT编程  | 我要评论

d3.js入门教程之比例尺,在数据可视化的过程中,往往需要将一个值转换为另一个值。例如要绘制一个历年产值的柱状图,我们需要把3000万的产值投射为屏幕上300个像素的高度。以数学上的“函数”为例:y=2x+1。在这里,x的取值范围假定为[0, 2],这称为“定义域”。则y的取值范围为[1, 5],这称为“值域”。通过一个函数式提供了定义域到值域的对应关系,d3提供了将一个量转换为另一个量的方法,称为“比例尺”(scale)。

比例尺是d3的基本概念,每一种比例尺都要指定一个定义域(domain)和值域(range)。比例尺分为两种情况:
(1)连续的定义域对应连续的(或离散的)值域——定量比例尺;
(2)离散的定义域对应离散的值域——序数比例尺;

一、定量比例尺

1. 线性比例尺:计算线性对应关系。将连续的定义域对应到连续的值域上。

d3.scalelinear()——创建一个线性比例尺; linear(x)——输入定义域x的值,返回值域对应的值; linear.invert(y)——输入值域内的值,返回定义域内对应的值; linear.domain([numbers])——获取或定义定义域; linear.range([values])——获取或定义值域; linear.rangeround([values])——等同于range(),获取或定义值域。比例尺的输出值会进行四舍五入的运算,得到一个整数; linear.clamp([boolean])——定义当比例尺得到一个超过定义域的值的时候,是否进行转换。默认为flase表示可以接受超出范围的值; linear.nice([count])——将定义域的范围扩展到比较理想的形式; linear.ticks([count])——设定或获取定义域内具有代表性的值得数目,count默认为10。该方法主要用于获取坐标轴的刻度; linear.tickformat(count[, format])——设置定义域内具有代表性值的表现形式,主要用于坐标轴上;

<script>
        var linear = d3.scalelinear() // 创建线性比例尺
                .domain([0, 500]) // 定义域
                .range([0, 100]);   // 值域

        console.log(linear(50)); // 输出定义域50所对应的值域值:10
        console.log(linear.invert(50)); // 输出值域50所对应的定义域的值:250
        console.log(linear.domain()); // 获取定义域
        console.log(linear.range()); // 获取值域

        console.log(linear(1000)); // 输出200
        linear.clamp(true); // 禁止接受超值范围的输入
        console.log(linear(1000)); // 只输出定义域最大值500所对应的值域:100

        linear.rangeround([0, 100]);
        console.log(linear(13.33)); // 本身的输出是2.66,四舍五入为3

        linear.domain([0.12300000, 0.488888888]).nice();
        console.log(linear.domain()); // [0.1, 0.5]

        linear = d3.scalelinear()
                .domain([-20, 20])
                .range([0, 100]);
        var ticks = linear.ticks(5);
        console.log(ticks); // [-20, -10, 0, 10, 20]
        var tickformat = linear.tickformat(5, "+"); // 给数字添加符号,0或正数添加+,负数添加-
        //for(var i=0; i

定义域和值域也可以定义多个数字,但是两者数量必须相等。

2. 指数比例尺和对数比例尺:用于计算指数对应关系和对数对应关系。将连续的定义域对应到连续的值域上。
方法和线性比例尺一样,指数比例尺(scalepow)多了一个exponent([value]),用于指定指数。对数比例尺(scalelog)多了一个方法名为base([value]),用于设定对数。


<script>
        // 指数比例尺
        var pow = d3.scalepow().exponent(2);
        console.log(pow(10)); // 100

        // 对数比例尺
        var log = d3.scalelog().base(10);
        console.log(log(100)); // 2

        // domain和range的意义
        var pow1 = d3.scalepow().exponent(3)
                .domain([0, 3])
                .range([0, 90]);
        console.log(pow1(1.5)); // 11.25
    </script>

在指数和对数比例尺情况下,定义domain和range的意义在于,d3会先把定义域按照指数关系计算出来,并对应到值域上面去。比如上面的代码,定义了指数为3,定义域为[0, 3]。实际上,d3建立了一个定义域的指数计算,即[0, 27],并通过线性比例尺将其对应到[0, 90]上面去。然后计算了1.5的3次方为3.375,线性过去以后就是11.25。

3. 量化比例尺和分位比例尺:将连续的定义域对应到离散的值域
量化比例尺(scalequantize)将连续的定义域自动对应到离散的值域上。比如定义域为[0, 10],值域为[“red”, “green”, “blue”, “yellow”, “black”]。则转换为:

[0, 2)——red [2, 4)——green [4, 6)——blue [6, 8)——yellow [8, 10)——black
例如下面的代码输入为5个不同灰度的圆:

<script>
        var color = d3.scalequantize()
                .domain([0, 50])
                .range(["#000", "#222", "#444", "#666", "#888"]);

        // 定义圆半径
        var r = [45, 35, 25, 15, 5]; 

        // 添加svg元素
        var svg = d3.select("body").append("svg")
                .attr("width", 400)
                .attr("height", 400);

        // 画圆
        svg.selectall("circle")
                .data(r)
                .enter()
                .append("circle")
                .attr("cx", function(d, i){ return 50+i*30; })
                .attr("cy", 50)
                .attr("r", function(d){ return d; })
                .attr("fill", function(d){ return color(d); });
    </script>

分位比例尺(scalequantile),和量化比例尺一样,也是将连续的定义域定义到离散的值域上。和量化比例尺不同的是,量化比例值只考虑定义域的起止值,然后根据值域平均切割。而分位比例尺考虑定义域中的所有的值。如下:


<script>
        // 量化比例尺
        var quantize = d3.scalequantize()
                .domain([0, 10])
                .range([1, 100]);
        // 分位比例尺
        var quantile = d3.scalequantile()
                .domain([0, 2, 4, 10])
                .range([1, 100]);

        console.log(quantize(3)); // 1
        console.log(quantile(3)); // 100
    </script>

对于scalequantize而言,值域为1和100,则定义域进行两段的平均切割。定义域[0, 10]的平均切割就是中位数5。而scalequantile而言,值域也是离散值1和100,但定义域为[0, 2, 4, 10]。那么它的中位数就是(2+4)/2=3。如果定义域为[0, 2, 4, 9, 10],则它的中位数就是4。如果不确定分位比例尺的分位数,可以通过方法scalequantile.quantiles()来获取。

4. 阈值比例尺:设定n个阈值,将值域分成n+1个。连续的定义域对应离散的自值域。阈值比例尺(threshold),比如下面的例子:


<script>
        var threshold = d3.scalethreshold()
                .domain([10, 20, 30])
                .range(["red", "green", "blue", "black"]);

        console.log(threshold(5)); // red
        console.log(threshold(15)); // green
        console.log(threshold(25)); // blue
        console.log(threshold(35)); // black
    </script>

二、序数比例尺

序数比例尺实现离散的定义域到离散的值域的对应关系。

d3.scaleordinal()——创建一个序数比例尺; ordinal(x)——根据定义域的x的值获取值域对应的值; ordinal.domain([values])——获取或设置定义域; ordinal.range([values])——获取或定义值域;

<script>
        var ordinal = d3.scaleordinal()
                .domain([1, 2, 3, 4, 5])
                .range([10, 20, 30, 40, 50]);
        console.log(ordinal(1)); // 10
        console.log(ordinal(3)); // 30
        console.log(ordinal(5)); // 50
        console.log(ordinal(8)); // 不在定义域内,输出为10
    </script>						

                    

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网