D3数据可视化基础

实验目的

       近年来,可视化越来越流行,许多报刊杂志、门户网站、新闻媒体都大量使用可视化技术,使得复杂的数据和文字变得十分容易理解,即“一图胜千言”。各种数据可视化工具也如井喷式地发展,D3 正是数据可视化工具中的佼佼者,基于 JavaScript 开发,项目托管于 GitHub。从 D3诞生以来,不断受到好评,在 GitHub 上的项目仓库排行榜也不断上升。

       与传统的图形库相比,d3.js允许开发者以声明式方式将数据映射到文档对象模型(DOM)。它提供了丰富的API来操作DOM元素,通过数据绑定机制,d3.js可以实现复杂且动态的视觉效果。

实验原理

       D3 的全称是(Data-Driven Documents),是一个被数据驱动的文档,其实就是一个 JavaScript 的函数库,使用它主要是用来做数据可视化的。本次实践主要介绍D3 一些最基本的使用方法,以及生成一些比较简单的图表。D3 是一个 JavaScript 函数库。它只有一个文件,在 HTML 中引用即可。有两种方法:

(1)下载 D3.js 的文件,解压后,在 HTML 文件中包含相关的 js 文件即可。

(2)还可以直接包含网络的链接,这种方法较简单:

<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>

       但使用的时候要保持网络连接有效,不能再断网的情况下使用。D3 可以接受几乎任何数字数组,字符串,或对象(本身包含其他数组或键/值对),可以处理 JSON GeoJSON

实验环境

IE9 以上或 Firefox Chrome(推荐)等浏览器、Notepad++等编辑工具。D3.js库。

实验步骤

题目一:制作一个简单的柱形图。

1、打开Notepad++,新建文件,并编辑好html框架。

<html>
<head>
    <meta charset="utf-8">
    <title>完整的柱形图</title>
    <style>
        /* 设置柱形图的颜色 */
        .MyRect {
            fill: orange; /* 修改颜色为橙色 */
        }
        /* 设置文字的样式 */
        .MyText {
            font-size: 12px;
            text-anchor: middle;
            fill: black; /* 文字颜色为黑色 */
        }
        /* 设置坐标轴的样式 */
        .axis path,
        .axis line {
            fill: none;
            stroke: black;
            shape-rendering: crispEdges;
        }
        .axis text {
            font-family: sans-serif;
            font-size: 11px;
        }
    </style>
</head>
2、添加 SVG 画布。

      要绘图,首要需要的是一块绘图的画布HTML5 提供两种强有力的画布:SVG 和 Canvas

      SVG,指可缩放矢量图形(Scalable Vector Graphics),是用于描述二维矢量图形的一种图形格式,是由万维网联盟制定的开放标准。SVG 使用 XML 格式来定义图形,除了 IE8 之前的版本外,绝大部分浏览器都支持 SVG,可将 SVG 文本直接嵌入 HTML 中显示。

      Canvas 是通过 JavaScript 来绘制 2D 图形,是 HTML 5 中新增的元素。

      D3 虽然没有明文规定一定要在 SVG 中绘图,但是 D3 提供了众多的 SVG 图形的生成器,它们都是只支持 SVG 的。因此,建议使用 SVG 画布。在 body 标签中加入代码。

<body>
    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
    <script>
        // 画布大小
        var width = 400;
        var height = 400;

        // 在 body 里添加一个 SVG 画布
        var svg = d3.select("body")
            .append("svg")
            .attr("width", width)
            .attr("height", height);

        // 画布周边的空白
        var padding = {left: 30, right: 30, top: 20, bottom: 20};
3、定义数据和比例尺。

      在添加画布的代码后面加入如下代码。

  // 定义一个数组
        var dataset = [16, 23, 54, 46, 33, 24, 19, 37, 9];

        // x 轴的比例尺
        var xScale = d3.scale.ordinal()
            .domain(d3.range(dataset.length))
            .rangeRoundBands([0, width - padding.left - padding.right], 0.1);

        // y 轴的比例尺
        var yScale = d3.scale.linear()
            .domain([0, d3.max(dataset)])
            .range([height - padding.top - padding.bottom, 0]);
4、定义坐标轴。
        // 定义 x 轴
        var xAxis = d3.svg.axis()
            .scale(xScale)
            .orient("bottom");

        // 定义 y 轴
        var yAxis = d3.svg.axis()
            .scale(yScale)
            .orient("left");
5、添加矩形和文字元素。
        // 矩形之间的空白
        var rectPadding = 4;

        // 添加矩形元素
        var rects = svg.selectAll(".MyRect")
            .data(dataset)
            .enter()
            .append("rect")
            .attr("class", "MyRect")
            .attr("transform", "translate(" + padding.left + "," + padding.top + ")")
            .attr("x", function(d, i) {
                return xScale(i) + rectPadding / 2;
            })
            .attr("y", function(d) {
                return yScale(d);
            })
            .attr("width", xScale.rangeBand() - rectPadding)
            .attr("height", function(d) {
                return height - padding.top - padding.bottom - yScale(d);
            });
		// 添加文字元素
        var texts = svg.selectAll(".MyText")
            .data(dataset)
            .enter()
            .append("text")
            .attr("class", "MyText")
            .attr("transform", "translate(" + padding.left + "," + padding.top + ")")
            .attr("x", function(d, i) {
                return xScale(i) + rectPadding / 2;
            })
            .attr("y", function(d) {
                return yScale(d);
            })
            .attr("dx", function() {
                return (xScale.rangeBand() - rectPadding) / 2;
            })
            .attr("dy", function(d) {
                return 20;
            })
            .text(function(d) {
                return d;
            });
        
6、添加坐标轴的元素
        // 添加 x 轴
        svg.append("g")
            .attr("class", "axis")
            .attr("transform", "translate(" + padding.left + "," + (height - padding.bottom) + ")")
            .call(xAxis);

        // 添加 y 轴
        svg.append("g")
            .attr("class", "axis")
            .attr("transform", "translate(" + padding.left + "," + padding.top + ")")
            .call(yAxis);
    </script>
</body>
</html>

    最后运行结果如下图所示。

题目二:制作动态的柱形图。

      D3 提供了 4 个方法用于实现图形的过渡:

      1) transition()启动过渡效果。其前后是图形变化前后的状态(形状、位置、颜色等等)。D3 会自动对两种颜色(红色和铁蓝色)之间的颜色值(RGB值)进行插值计算,得到过渡用的颜色值。

      2) duration()指定过渡的持续时间,单位为毫秒。如 duration(3000),指持续3秒。

      3) ease()指定过渡的方式,常用的有:linear:普通的线性变化;circle:慢慢地到达变换的最终状态;elastic:带有弹跳的到达最终状态;bounce:在最终状态处弹跳几次。

      4) delay()指定延迟的时间,表示一定时间后才开始转变,单位同样为毫秒。此函数可以对整体指定延迟,也可以对个别指定延迟。

     下面我们将在题目一完成的柱形图的基础上稍作修改,做成一个带动态效果的柱形图。把题目一中添加矩形元素和添加文字元素的代码换成如下代码,就可以启动过渡效果,让各柱形和文字缓慢升至目标高度,并且在目标处跳动几次。

        // 添加矩形元素
        var rects = svg.selectAll(".MyRect")
            .data(dataset)
            .enter()
            .append("rect")
            .attr("class", "MyRect")
            .attr("transform", "translate(" + padding.left + "," + padding.top + ")")
            .attr("x", function(d, i) {
                return xScale(i) + rectPadding / 2;
            })
			.attr("width",xScale.rangeBand()-rectPadding)
            .attr("y", function(d) {
			    var min=yScale.domain()[0];
                return yScale(min);
            })
            .attr("height", function(d) {
                return 0;
            });
			.transition()
			.delay(function(d,i){
			    return i*200;
			})
			.duration(2000)
			.ease("bounce")
			.attr("y",function(d){
				return yScale(d);
			})
			.attr("height", function(d) {
                return height - padding.top - padding.bottom - yScale(d);
            });
		// 添加文字元素
        var texts = svg.selectAll(".MyText")
            .data(dataset)
            .enter()
            .append("text")
            .attr("class", "MyText")
            .attr("transform", "translate(" + padding.left + "," + padding.top + ")")
            .attr("x", function(d, i) {
                return xScale(i) + rectPadding / 2;
            })
			.attr("dx", function() {
                return (xScale.rangeBand() - rectPadding) / 2;
            })
			.attr("dy", function(d) {
                return 20;
            })
			 .text(function(d) {
                return d;
            });
            .attr("y", function(d) {
			    var min=yScale.domain()[0];
                return yScale(min);
            })
            .transition()
			.delay(function(d,i){
			    return i*200;
            });
			.duration(2000)
			.ease("bounce")
			.attr("y",function(d){
				return yScale(d);
			})

可运行程序,自行查看结果。

题目三:制作饼形图。

       饼图是数据可视化中常见的一种图表,用于显示各部分与整体之间的比例关系。它由若干个扇形组成,每个扇形的角度和面积大小表示数据项在总数据集中的比重。

       交互设计在饼图中的应用,主要是为了提高用户体验,让用户能够以更加直观和动态的方式理解和分析数据。常见的交互设计原理包括:

       实时反馈 :当用户进行交互操作时,如点击扇形区域,图表应立即反映出相应的变化。
       信息层级 :合理安排交互信息的优先级,确保关键信息能迅速传达给用户。
       简单直观 :交互操作应符合用户习惯,易于理解和操作,避免复杂的操作流程。
       引导用户探索 :通过颜色、动画等视觉元素引导用户的注意力,让用户自然地发现数据间的关联和趋势。

       布局是 D3 中一个十分重要的概念。布局的作用是:将不适合用于绘图的数据转换成了适合用于绘图的数据。

       D3 总共 提供 了 12 个布 局: 饼状 图( Pie)、 力导 向图 ( Force )、 弦图(Chord)、树状图(Tree)、集群图(Cluster)、捆图(Bundle)、打包图(Pack)、直方(Histogram)、分区图(Partition)、堆栈图(Stack)、矩阵树图(Treemap)、层级图(Hierarchy)。 12 个布局中,层级图(Hierarchy)不能直接使用。集群图、打包图、分区图、树状图、矩阵树图是由层级图扩展来的。这些布局的作用都是将某种数据转换成有利于可视化的另一种数据。

       在布局的应用中,最简单的就是饼状图。

1、定义一个饼状图布局

       定义布局的代码为:var pie = d3.layout.pie();此时 pie 可以当做函数使用。然后将数组dataset(里面是要可视化的数据)作为 pie()的参数,返回值 piedata 就是转换后的数据。var piedata = pie(dataset)

<html>
<head>
    <meta charset="utf-8">
    <title>饼状图</title>
	
    <style>
        /* 设置文本样式 */
        text {
            font-family: sans-serif;
            font-size: 12px;
            fill: white; /* 文本颜色为白色 */
        }
    </style>
</head>
<body>


    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
    <script>
        // 画布大小
        var width = 400;
        var height = 400;

        // 数据集
        var dataset = [11, 6, 34, 27, 13, 9];

        // 创建 SVG 画布
        var svg = d3.select("body")
            .append("svg")
            .attr("width", width)
            .attr("height", height);

        // 定义饼状图布局
        var pie = d3.layout.pie();

        // 将数据集转换为饼状图所需的数据格式
        var piedata = pie(dataset);
2、绘制图形

       SVG 有一个叫做路径 <path>的元素,它可以结合使用直线,曲线等来制作各种不规则的复杂的图形。通过布局转换后的数据 piedata 很难计算得到路径值。为此,我们需要用到生成器。这里要用到的叫做弧生成器,能够生成弧的路径,因为饼图的每一部分都是一段弧。

        // 定义弧生成器
        var outerRadius = 150; // 外半径
        var innerRadius = 0; // 内半径,为 0 则中间没有空白
        var arc = d3.svg.arc()
            .innerRadius(innerRadius)   //设置内半径
            .outerRadius(outerRadius);   //设置外半径

       弧生成器返回的结果赋值给 arcarc 可以当做一个函数使用,把 piedata 作为参数传入,即可得到路径值。

       接下来,在 <svg> 里添加分组元素(g),每一个分组用于存放一段弧的相关元素。再对每个 <g> 元素,添加 <path>

        // 添加分组元素,每个分组对应一段弧
        var arcs = svg.selectAll("g")
            .data(piedata)
            .enter()
            .append("g")
            .attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")");

        // 添加路径元素,绘制弧
        arcs.append("path")
            .attr("fill", function(d, i) {
                return color(i); // 根据索引设置颜色
            })
            .attr("d", function(d) {
                return arc(d); // 使用弧生成器生成路径
            });

        定义颜色比例尺。color 是一个颜色比例尺,它能根据传入的索引号获取相应的颜色值。

        // 定义颜色比例尺
        var color = d3.scale.category10();

       然后在每一个弧线中心添加文本。

        // 添加文本元素,显示数据值
        arcs.append("text")
            .attr("transform", function(d) {
                return "translate(" + arc.centroid(d) + ")"; // 将文本定位到弧的中心
            })
            .attr("text-anchor", "middle")
            .text(function(d) {
                return d.data; // 显示数据值
            });

        // 打印数据集和转换后的数据到控制台
        console.log("原始数据集:", dataset);
        console.log("转换后的数据:", piedata);
    </script>
</body>
</html>

      运行结果如下:

题目四:制作交互式的饼形图。

       交互是指用户输入了某种指令后程序就可做出某种响应。对可视化图表来说,交互能使图表更加生动,能表现更多内容。例如,拖动图表中某些图形、鼠标滑到图形上出现提示框、用触屏放大或缩小图形等等。用户用于交互的工具一般有三种:鼠标、键盘、触屏。

       在 D3 中,每一个选择集都有 on()函数,用于添加事件监听器。on()的第一个参数是监听的事件,第二个参数是监听到事件后响应的内容,第二个参数是一个函数。鼠标常用的事件有:

       click - 鼠标单击某元素时,相当于 mousedown mouseup 组合在一起。

       mouseover - 光标放在某元素上。

       mouseout - 光标从某元素上移出来时。

       mousemove - 鼠标被移动的时候。

       mousedown - 鼠标按钮被按下。

       mouseup - 鼠标按钮被松开。

       下面开始进行简单的交互式饼形图制作,目标是在上面的饼形图的基础上加入mouseover 和 mouseout 事件,mouseover 某部分时变换成黄色,mouseout 时恢复原色。在代码中加入如下代码。

        // 添加分组元素,每个分组对应一段弧
        var arcs = svg.selectAll("g")
            .data(piedata)
            .enter()
            .append("g")
            .attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")");
			        // 添加路径元素,绘制弧
        arcs.append("path")
            .attr("fill", function(d, i) {
                return color(i); // 根据索引设置颜色
            })
            .attr("d", function(d) {
                return arc(d); // 使用弧生成器生成路径
            })
            .on("mouseover", function(d, i) {
                d3.select(this)
                    .attr("fill", "yellow"); // 鼠标悬停时变为黄色
            })
            .on("mouseout", function(d, i) {
                d3.select(this)
                    .transition()
                    .duration(500)
                    .attr("fill", color(i)); // 鼠标移出时恢复原色
            });

        // 添加文本元素,显示数据值
        arcs.append("text")
            .attr("transform", function(d) {
                return "translate(" + arc.centroid(d) + ")"; // 将文本定位到弧的中心
            })
            .attr("text-anchor", "middle")
            .text(function(d) {
                return d.data; // 显示数据值
            });

      运行结果为:

实验心得

       通过本次实验,不仅可以掌握D3.js的基本使用方法,还学会了如何为图表添加动态效果和交互功能。D3.js的灵活性和强大功能让我对数据可视化产生了浓厚的兴趣,未来希望能够进一步深入学习D3.js,探索更多复杂的可视化技术,并将其应用到实际项目中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值