网页图表创建指南
在网页开发中,创建各种类型的图表是一项常见且重要的任务。本文将介绍如何使用相关工具和技术创建不同类型的网页图表,包括柱状图、直方图、力导向图等,并实现图表的交互功能。
1. NVD3与数据处理基础
NVD3要求数据采用特定格式。我们需要创建数据适配器函数,以及创建和配置特定图表的函数。通过调用 webviz/create-chart 函数,我们可以填充HTML元素并显示图表。 create-chart 函数接受以下参数:
- 加载数据的URL
- 创建图表的元素路径
- 创建图表的函数
- 将数据转换为点和组的函数
该函数利用这些参数请求数据、创建图表并将数据与之关联。
以下是一些相关工具的链接:
- D3官网: http://d3js.org/
- NVD3官网: http://nvd3.org/
- 替代方案C2: http://keminglabs.com/c2/
2. 使用NVD3创建柱状图
柱状图适用于比较数据集中不同类别数据的总和或计数。下面以比较四种不同饮食喂养的小鸡体重为例,介绍创建柱状图的步骤。
2.1 准备工作
- 在
project.clj文件中使用与创建散点图相同的依赖和插件。 - 使用之前提到的
sum-by函数。 - 下载小鸡体重数据集的JSON文件: http://www.ericrochester.com/clj-data-analysis/data/chick-weight.json ,并保存到项目的
resources/data/目录下。
2.2 操作步骤
- 编写处理函数 :返回一个D3页面,包含创建DIV和SVG元素的代码,并调用后续定义的ClojureScript函数。
(defn bar-chart []
(d3-page "Bar Chart"
"webviz.barchart.bar_chart();"
[:div#barchart.chart [:svg]]))
- 添加路由 :
(defroutes
site-routes
(GET "/barchart" [] (bar-chart))
(GET "/barchart/data.json" []
(redirect "/data/chick-weight.json"))
(route/resources "/")
(route/not-found "Page not found"))
- 创建ClojureScript文件 :在
src-cljs/webviz/barchart.cljs中添加命名空间声明。
(ns webviz.barchart
(:require [webviz.core :as webviz]))
- 数据转换 :将数据转换为NVD3期望的
Group和Point数据结构的两个类别。
(defn count-point [pair]
(let [[diet items] pair]
(webviz/Point. diet (count items) 1)))
(defn get-diet-counts [diet-groups]
(apply array (map count-point diet-groups)))
(defn weight-point [pair]
(let [[diet items] pair
weight-total (sum-by #(.-weight %) items)]
(webviz/Point. diet weight-total 1)))
(defn get-diet-weights [diet-groups]
(apply array (map weight-point diet-groups)))
- JSON转换函数 :将JSON输入转换为NVD3的JavaScript对象。
(defn json->nv-groups [json]
(let [diet-groups (group-by #(.-diet %) json)]
(array (webviz/Group.
"Chick Counts"
(get-diet-counts diet-groups))
(webviz/Group.
"Chick Weights"
(get-diet-weights diet-groups)))))
- 创建图表函数 :
(defn ^:export bar-chart []
(webviz/create-chart "/barchart/data.json"
"#barchart svg"
#(.multiBarChart js/nv.models)
json->nv-groups))
2.3 工作原理
通过利用之前创建的 create-chart 函数,避免了创建图表时的大量样板代码。设置网页资源通常需要以下步骤:
1. 在服务器上定义资源(如 bar-chart )。
2. 定义访问该资源的路由。
3. 创建ClojureScript文件。
4. 在ClojureScript中编写数据转换函数。
5. 在ClojureScript中创建图表。
3. 使用NVD3创建直方图
直方图常用于展示数据的分布情况。下面以展示鲍鱼数据集的长度分布为例,介绍创建直方图的步骤。
3.1 准备工作
- 在
project.clj文件中使用与创建散点图相同的依赖和插件。 - 下载鲍鱼数据集的JSON文件: http://www.ericrochester.com/clj-data-analysis/data/abalone.json ,并保存到项目的
resources/data/目录下。
3.2 操作步骤
- 编写处理函数 :
(defn hist-plot []
(d3-page "Histogram"
"webviz.histogram.histogram();"
[:div#histogram.chart [:svg]]))
- 添加路由 :
(defroutes
site-routes
(GET "/histogram" [] (hist-plot))
(GET "/histogram/data.json" []
(redirect "/data/abalone.json"))
(route/resources "/")
(route/not-found "Page not found"))
- 创建ClojureScript文件 :在
src-cljs/webviz/histogram.cljs中添加命名空间声明。
(ns webviz.histogram
(:require [webviz.core :as webviz]))
- 数据分组函数 :
(defn get-bucket-number [mn size x]
(Math/round (/ (- x mn) size)))
(defn inc-bucket [mn size buckets x]
(let [b (get-bucket-number mn size x)]
(assoc buckets b (inc (buckets b)))))
(defn get-buckets [coll n]
(let [mn (reduce min coll)
mx (reduce max coll)
bucket-size (/ (- mx mn) n)
first-center (+ mn (/ bucket-size 2.0))
centers (map #(* (inc %) first-center)
(range n))
initial (reduce #(assoc %1 %2 0) {}
(range n))]
(->> coll
(reduce (partial inc-bucket mn bucket-size)
initial)
seq
(sort-by first)
(map second)
(map vector centers))))
- 数据转换函数 :
(defn ->point [pair]
(let [[bucket count] pair]
(webviz/Point. (inc bucket) count 1)))
(defn data->nv-groups [data]
(let [lengths (map #(.-length %) data)
buckets (apply array
(map ->point
(get-buckets
lengths 10)))]
(array (webviz/Group. "Abalone Lengths" buckets))))
- 初始化图表函数 :
(defn make-chart [] (.multiBarChart (.-models js/nv)))
- 创建图表函数 :
(defn ^:export histogram []
(webviz/create-chart
"/histogram/data.json"
"#histogram svg"
make-chart
data->nv-groups
:transition true))
3.3 工作原理
此过程与之前的类似,不同之处在于需要将数据划分为桶。通过获取桶中的最小值和最大值,计算差值并除以桶的数量,得到每个桶的宽度。利用这些信息确定每个数据点所属的桶,并进行计数。同时,获取每个桶的中心值用于标记图表中的列。
4. 使用力导向布局可视化图形
力导向布局是一种流行的可视化数据图的方法,它通过模拟带电粒子和弹簧的物理过程,创建美观的可视化效果,减少交叉线并使所有边的长度大致相同,从而清晰展示图中的关系。下面以美国人口普查种族数据的K-means聚类图为例,介绍创建力导向图的步骤。
4.1 准备工作
- 在
project.clj文件中使用与创建散点图相同的依赖和插件。 - 下载美国人口普查种族数据聚类图的JSON文件: http://www.ericrochester.com/clj-data-analysis/data/clusters.json ,并保存到项目的
resources/data/目录下。
4.2 操作步骤
- 编写处理函数 :
(defn force-layout-plot []
(d3-page "Force-Directed Layout"
"webviz.force.force_layout();"
[:div#force.chart [:svg]]))
- 添加路由 :
(defroutes
site-routes
(GET "/force" [] (force-layout-plot))
(GET "/force/data.json" []
(redirect "/data/clusters.json"))
(route/resources "/")
(route/not-found "Page not found"))
- 添加样式 :在
resources/css/style.css中添加以下样式:
#force { width: 650px; height: 500px; }
#force .node { stroke: #fff; stroke-width: 1.5px; }
#force .link { stroke: #999; stroke-opacity: 1; }
- 创建ClojureScript文件 :在
src-cljs/webviz/force.cljs中添加命名空间声明。
(ns webviz.force)
- 创建力导向图 :
(defn create-force [width height]
(-> js/d3 .-layout
(.force)
(.charge -120)
(.linkDistance 30)
(.size (array width height))))
- 创建SVG元素 :
(defn create-svg [width height]
(-> js/d3
(.select "#force svg")
(.attr "width" width)
(.attr "height" height)))
- 设置节点和边并启动动画 :
(defn start-force [force graph]
(-> force
(.nodes (aget graph "nodes"))
(.links (aget graph "links"))
.start))
- 创建边和节点 :
(defn create-links [svg graph]
(-> svg
(.selectAll "line.link")
(.data (aget graph "links"))
(.enter)
(.append "line")
(.attr "class" "link")
(.style "stroke-width"
#(.sqrt js/Math (inc (aget % "value"))))))
(defn create-nodes [svg force color graph]
(-> svg
(.selectAll "circle.node")
(.data (aget graph "nodes"))
(.enter)
(.append "circle")
(.attr "class" "node")
(.attr "r" 5)
(.attr "data-n" #(aget % "n"))
(.style "fill" #(color (aget % "group")))
(.call (aget force "drag"))))
- 定义tick处理函数 :
(defn on-tick-handler [link node]
(fn []
(-> link
(.attr "x1" #(-> % .-source .-x))
(.attr "y1" #(-> % .-source .-y))
(.attr "x2" #(-> % .-target .-x))
(.attr "y2" #(-> % .-target .-y)))
(-> node
(.attr "cx" #(aget % "x"))
(.attr "cy" #(aget % "y")))))
- 添加节点标题 :
(defn set-title [node]
(-> node
(.append "title")
(.text #(aget % "name"))))
- 渲染图形 :
(def census-graph (atom nil))
(defn render-graph [color force svg graph]
(swap! census-graph (fn [] graph))
(start-force force graph)
(let [link (create-links svg graph)
node (create-nodes svg force color graph)]
(set-title node)
(.on force "tick" (on-tick-handler link node))))
- 导出函数 :
(defn ^:export force-layout []
(let [width 650, height 500]
(.json js/d3 "force/data.json"
(partial
render-graph
(.category20c (aget js/d3 "scale"))
(create-force width height)
(create-svg width height)))))
4.3 工作原理
这是一个纯D3可视化的示例,典型的D3可视化过程包括以下步骤:
1. 创建图表控制器: create-force 函数负责创建图表的控制器。
2. 选择容器: create-svg 函数选择用于渲染图形的SVG元素。
3. 选择包含数据点的元素: create-links 和 create-nodes 函数通过调用 selectAll 选择线条节点和圆形节点。
4. 关联数据与图表: create-links 和 create-nodes 函数将边和节点与元素关联, start-force 函数将两者的副本传递给力对象。
5. 创建HTML元素: create-links 和 create-nodes 函数使用 append 和 attr 为各自的数据类型创建HTML元素。
由于力导向布局是动画形式的,还需要创建tick处理函数来更新浏览器中对象的最新位置。
总结
本文介绍了使用NVD3和D3创建不同类型网页图表的方法,包括柱状图、直方图和力导向图,并实现了图表的交互功能。通过遵循上述步骤和代码示例,你可以在网页中创建出美观且实用的图表。
流程图示例
graph TD
A[准备数据] --> B[创建处理函数]
B --> C[添加路由]
C --> D[创建ClojureScript文件]
D --> E[编写数据转换函数]
E --> F[创建图表函数]
F --> G[显示图表]
表格示例
| 图表类型 | 数据来源 | 关键步骤 |
|---|---|---|
| 柱状图 | 小鸡体重数据集 | 编写处理函数、添加路由、创建ClojureScript文件、数据转换、创建图表 |
| 直方图 | 鲍鱼数据集 | 编写处理函数、添加路由、创建ClojureScript文件、数据分组、数据转换、创建图表 |
| 力导向图 | 美国人口普查种族数据聚类图 | 编写处理函数、添加路由、添加样式、创建ClojureScript文件、创建力导向图、创建SVG元素、设置节点和边、创建边和节点、定义tick处理函数、添加节点标题、渲染图形 |
5. 使用D3创建交互式可视化图表
在网页开发中,使图表具有交互性可以极大地提升用户体验。下面我们将基于之前创建的美国人口普查种族数据的力导向图,为其添加交互功能,当用户悬停在节点上时,在数据面板中显示该节点的人口普查数据。
5.1 准备工作
基于之前创建的力导向图进行扩展。
5.2 操作步骤
- 编写处理函数 :返回一个包含数据面板的D3页面。
(defn interactive-force-plot []
(d3-page "Interactive Force-Directive Layout"
(str "webviz"
".int_force"
".interactive_force_layout();")
[:div
[:div#force.chart [:svg]]
[:div#datapane]]))
- 添加路由 :
(defroutes
site-routes
(GET "/int-force" [] (interactive-force-plot))
(GET "/int-force/data.json" []
(redirect "/data/clusters.json"))
(route/resources "/")
(route/not-found "Page not found"))
- 添加样式 :在
resources/css/style.css中添加数据面板的样式。
#datapane { float: right; width: 250px; }
#datapane dt { font-weight: bold; }
- 创建ClojureScript文件 :在
src-cljs/webviz/int_force.cljs中添加命名空间声明。
(ns webviz.int-force
(:require [clojure.browser.dom :as dom]
[webviz.force :as force]
[goog.events :as gevents]))
- 封装数据面板元素函数 :为每个普查项添加DT/DD元素组合。
(defn dl-item [title data key]
(let [val2000 (aget data (str key "-2000"))]
(str "<dt>" title "</dt>"
"<dd>" (.round js/Math (aget data key))
" <em>(2000: "
(.round js/Math val2000)
")</em>"
"</dd>")))
- 构建数据面板HTML函数 :
(defn update-data [node]
(let [data (aget node "data")
content
(str "<h2>" (aget node "name") "</h2>"
"<dl>"
(dl-item "Total" data "race-total")
(dl-item "White" data "race-white")
(dl-item "African-American" data
"race-black")
(dl-item "Native American" data
"race-indian")
(dl-item "Asian" data "race-asian")
(dl-item "Hawaiian" data "race-hawaiian")
(dl-item "Other" data "race-other")
(dl-item "Multi-racial" data
"race-two-more")
"</dl>")]
(dom/remove-children :datapane)
(dom/append
(dom/get-element :datapane)
(dom/html->dom content))))
- 定义鼠标悬停事件处理函数 :
(defn on-mouseover [ev]
(let [target (.-target ev)]
(if (= (.-nodeName target) "circle")
(let [n (+ (.getAttribute target "data-n"))]
(update-data
(aget (.-nodes @force/census-graph) n))))))
- 创建图表并添加事件处理函数 :
(defn ^:export interactive-force-layout []
(force/force-layout)
(gevents/listen (dom/get-element "force")
(.-MOUSEOVER gevents/EventType)
on-mouseover))
5.3 工作原理
此交互功能的实现原理与网页上的常规交互相同。我们监听用户在特定HTML标签上触发的事件,这里监听鼠标悬停在图中节点上的事件,并在步骤7中将事件处理函数绑定到该事件。当事件触发时,调用事件处理函数 on-mouseover ,该函数获取用户鼠标悬停节点的数据,并调用 update-data 和 dl-item 函数构建HTML结构以显示该节点的数据。
在这个过程中,我们使用了Google Closure库的事件模块来绑定事件,使用ClojureScript的 clojure.browser.dom 命名空间来动态删除和创建HTML元素,同时通过 js: 前缀与JavaScript对象或模块进行交互。
总结与拓展
通过本文的介绍,我们掌握了使用NVD3和D3创建多种类型网页图表的方法,包括柱状图、直方图、力导向图,并为图表添加了交互功能。这些技术可以帮助我们在网页中展示数据,提升用户体验。
在实际应用中,我们可以根据具体需求对图表进行更多的定制和优化,例如调整图表的样式、添加更多的交互效果等。同时,还可以探索更多的数据可视化技术和工具,进一步丰富我们的网页应用。
流程图示例
graph TD
A[创建力导向图] --> B[添加数据面板]
B --> C[添加样式]
C --> D[创建ClojureScript文件]
D --> E[封装数据面板元素函数]
E --> F[构建数据面板HTML函数]
F --> G[定义鼠标悬停事件处理函数]
G --> H[创建图表并添加事件处理函数]
H --> I[实现交互功能]
表格示例
| 功能 | 关键代码 | 作用 |
|---|---|---|
| 数据面板元素封装 | dl-item 函数 | 为每个普查项添加DT/DD元素组合 |
| 数据面板HTML构建 | update-data 函数 | 根据节点数据构建数据面板的HTML结构 |
| 鼠标悬停事件处理 | on-mouseover 函数 | 获取鼠标悬停节点的数据并更新数据面板 |
| 交互功能实现 | interactive-force-layout 函数 | 创建图表并添加鼠标悬停事件处理函数 |
超级会员免费看
1274

被折叠的 条评论
为什么被折叠?



