摘要:子選集直接通過返回,和子選集分別通過和返回。截止上面也并不是非得用不可,就是一些插入操作,原生也是可以實現(xiàn)的。
相對于echart, highchart等其他圖表庫算是一個比較底層的可視化工具,簡單來講他不提供任何一種現(xiàn)成的圖表,所有的圖表都是我們在它的庫里挑選合適的方法構(gòu)建而成。
基于上面的理解,d3無疑會復雜很多但是也強大自由的多,另外因為d3基于svg所以修改圖表的樣式和結(jié)構(gòu)也會方便很多,但是同樣是這個原因,d3的性能比canvas類庫差了不少,dom畢竟是拖累瀏覽器性能的罪魁禍首。順口提一句,d3也是可以基于canvas構(gòu)建圖表的。但是這篇文章就不提了。
基本概念對于d3我們可以簡單的將其分個類:數(shù)據(jù)處理, dom處理,事件以及其他。 其實dom和事件其實可以合到一起。
前端做可視化的時候肯定需要對數(shù)據(jù)進行處理,d3提供了一下常用的方法。
因為d3是基于svg所以跟dom打交道肯定是必須的,這里一定程度替代了jQuery之類的功能。
事件的話其實就是一些交互比如滾輪,拖拽等等都是基礎(chǔ)功能可以進行一系列組合排序
請求就是ajax請求數(shù)據(jù)源了。
數(shù)據(jù)處理數(shù)據(jù)處理就很簡單了,就是對于數(shù)組和集合以及時間的一些處理方法, 比如數(shù)組求中位數(shù)方差等等,和lodash的一些方法有重合,但是還是偏向數(shù)學方面,方法有點多這里不一一列出了:
// array的方法 d3.min([1, 2, 3, 4]) // 1 不同于Math,min忽略NaN undefined等 d3.range(1, 10) // [1, 2 ... 10] // collection的方法 d3.entries({foo: 42, bar: true}); // [{key: "foo", value: 42}, {key: "bar", value: true}] var map = d3.map([{name: "foo"}, {name: "bar"}], function(d) { return d.name; }); map.get("foo"); // {"name": "foo"} map.get("bar"); // {"name": "bar"} map.get("baz"); // undefined // time的方法 d3.timeDays(new Date("2014-01-11"), new Date("2014-02-12")) // 獲取2014-01-11 到2014-02-12的日期數(shù)組
上面是單純的數(shù)據(jù)處理也就是工具類,但是d3的強大不僅僅在于此,d3提供了一個強大算法庫,比如力導向圖的碰撞檢測以及tick等等,這里的功能也屬于數(shù)據(jù)處理但是又跟插入dom密不可分。
d3的數(shù)據(jù)不僅僅是這些有些跟dom耦合極深沒辦法完全拎出來說, 而且d3的api極多, 這些東西很多時候也只能邊看文檔邊做。好在d3的示例很多,基本需求都能滿足。
dom處理關(guān)于dom操作d3也提供了一系列方便的接口,比如d3.select,d3.append等等, 這部分的接口相當多,個人也沒法一一說明, 只能說用法都是一樣的,和jQuery相當類似:
svg.selectAll("circle") .data(data) .enter().append("circle") .attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }) .attr("r", 2.5);
上面的代碼是把circle跟data進行數(shù)據(jù)綁定并插入對應的dom節(jié)點(引用自鏈接):
首先,svg.selectAll("circle") 返回一個空選集,因為當前 SVG 還沒有任何子元素,該選集的父節(jié)點是這個 SVG 容器。
然后將該選集與數(shù)據(jù)綁定,產(chǎn)生三個新的子選集,分別代表三種可能的狀態(tài):enter、update 和 exit。由于當前選集為空,所以 update 和 exit 子選集也為空,enter 子選集就包含了每條數(shù)據(jù)對應的元素的占位符。
update 子選集直接通過 selection.data 返回,enter 和 exit 子選集分別通過 selection.enter 和 selection.exit 返回。
那些缺少的元素通過對 enter 子選集調(diào)用 selection.append 方法來添加到 SVG 中,這樣就為每條數(shù)據(jù)添加了一個新的圓點到 SVG 中。
如上都是鏈式操作
事件不同于canvas這里可以直接觸發(fā)原生事件,讓人親切很多。
事件是指基于dom的一些交互操作,包括但不限于click等原生事件,類似jQuery,事件是通過on進行綁定的:
selection.on("click", function (d) {}) // this指向事件元素, d是綁定的數(shù)據(jù)可以直接使用
同時,d3提供了很多自定義事件諸如drag, zoom,brush等等,這時候就是通過call調(diào)用了:
const brush = d3.brushX() .extent([[50, 50], [1100, 150]]) .on("start brush", brushed) .on("end", brushended) svg.append("g") .call(brush)
上面是調(diào)用brush事件,同時調(diào)用相應的回調(diào), 都是字面意思,至于還有很多有意思的事件,都隱藏在文檔中。
其他這個其他就包含了很多東西, 比如異步請求,解析excel,動畫等等,這里不一一說明了, 但是如果發(fā)現(xiàn)有需求沒法實現(xiàn)不妨看看文檔,說不定就內(nèi)置了呢。
完整示例下面給個示例,簡單力導向圖示例jsfiddle:
核心代碼如下:
const height = 200 const width = 200 const svg = d3.select("body").append("svg") const graph = { nodes: [ { id: 1, name: "test1" }, { id: 2, name: "test2" } ], links: [ { source: 1, target: 2 } ] } const simulation = d3.forceSimulation() .force("charge", d3.forceManyBody().strength(-700).distanceMin(100).distanceMax(1000)) .force("link", d3.forceLink().id(d => d.id)) .force("center", d3.forceCenter(width / 2, height / 2)) const link = svg.selectAll("link") .data(graph.links) .enter() .append("line") .attr("class", "link") const node = svg.selectAll("node") .data(graph.nodes) .enter().append("g") .attr("class", "node") node.append("circle") .attr("r", 13) .attr("fill", "#999") node.append("text") .attr("dx", -18) .attr("dy", 8) .style("font-family", "overwatch") .style("font-size", "18px") .text(d => d.name) const ticked = function () { link.attr("x1", d => d.source.x) .attr("y1", d => d.source.y) .attr("x2", d => d.target.x) .attr("y2", d => d.target.y); node.attr("transform", d => `translate(${d.x}, ${d.y})`) } const { nodes, links } = graph simulation.nodes(nodes).on("tick", ticked) simulation.force("link").links(links)
下面簡單解析一下代碼部分,const svg = d3.select("body").append("svg") 就是上面提到的d3操作dom的部分,就是類似jQuery的插入操作, 總之我們獲取到了svg畫布, graph 是提供了數(shù)據(jù)關(guān)系模型,但是一般來講后端不會這么提供嚴格的對應關(guān)系, 這時候就需要我們隊數(shù)據(jù)進行處理以獲取合理的數(shù)據(jù)格式, 一般來講數(shù)據(jù)格式都是如上。
力導向圖的核心是forceSimulation, 如字面上的意思就是來模擬力的,這是d3的內(nèi)部算法我們基本干涉不了, 所以d3的力導向圖怎么動最后停在哪都是我們沒法精確控制的, forceSimulation 定義了力導向圖的基本形態(tài)比如key值是否居中等等, 但是到這一步還沒對數(shù)據(jù)進行任何處理。
const link 和 const node, 簡單講就是把數(shù)據(jù)和dom進行綁定插入對應的dom節(jié)點, 一直到這一步, 我們完成了基本的步驟:根據(jù)關(guān)系模型繪制對應節(jié)點, 由于不是canvas, 每個數(shù)據(jù)節(jié)點都有一個對應的dom節(jié)點, 這里可以對樣式進行精確的處理。
截止上面也并不是非得用d3不可,就是一些dom插入操作, 原生js也是可以實現(xiàn)的。 simulation.nodes(nodes).on("tick", ticked)跟simulation.force("link").links(links)才是d3真正的作用所在,它會修改原來的數(shù)據(jù)模型在上面掛載一些位置信息, 如圖所示:
可以看到,nodes和link上面分別多了不少數(shù)據(jù),暫時我們不需要了解那么多, 只要知道x和y是節(jié)點的位置信息即可,另外力導向圖會不停的tick(300次左右),每次tick,d3都會修改graph上的位置信息,它內(nèi)部肯定做了很多事情, 比如碰撞檢測等等。當每次tick觸發(fā)的時候我們都已調(diào)用一個callback,在這個callback里更新所有節(jié)點的位置信息,也就是上面代碼的ticked, 我們就是修改了node和link的位置信息也就是x1之類的, 這些都是svg提供的接口這里不多做說明了。 到這里, 一個完整的力導向圖算是完成了,雖然數(shù)據(jù)少了點但是并不妨礙我們?nèi)ダ斫馄渲械脑怼?/p> 總結(jié)
通過上面一個完整示例, 我們發(fā)現(xiàn),d3的核心并不在于繪制圖形,這些都是dom操作,而是數(shù)據(jù)的處理,數(shù)據(jù)驅(qū)動dom,到這里是不是跟現(xiàn)代mvvm又掛上鉤了,并且d3是基于dom的, 我們完全可以把d3當做一個算法庫,處理數(shù)據(jù),至于圖像的繪制完全可以交由react等框架,這是canvas類庫所做不到的。用上virtual dom性能可能還會更高一點。dom操作是昂貴的,virtual dom跟d3搭配味道可能更佳。如果把d3作為一個算法庫我們還缺少最佳實踐。還需要學習。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/94147.html
摘要:效果如圖所示鏈接地址源碼鏈接地址其實這個例子也很簡單用到的也只是的基礎(chǔ)部分我們要把一定間隔請求過來的數(shù)據(jù)進行排序并生成元素同時重用原來和新數(shù)據(jù)相對應的元素刪除不對應的說的有點繞表達能力不行其實說到這明白人都能看出來了這要用到選擇器的以及方法 showImg(http://segmentfault.com/img/bVbZY5); 效果如圖所示,demo鏈接地址源碼鏈接地址 其實這個例...
摘要:效果如圖所示鏈接地址源碼鏈接地址其實這個例子也很簡單用到的也只是的基礎(chǔ)部分我們要把一定間隔請求過來的數(shù)據(jù)進行排序并生成元素同時重用原來和新數(shù)據(jù)相對應的元素刪除不對應的說的有點繞表達能力不行其實說到這明白人都能看出來了這要用到選擇器的以及方法 showImg(http://segmentfault.com/img/bVbZY5); 效果如圖所示,demo鏈接地址源碼鏈接地址 其實這個例...
摘要:通過力導向算法計算位置,繪制出對應的力導向圖,這樣的分配是最佳位置的分布圖。力導向算法是根據(jù)自然界中電子直接互相作用的原理來實現(xiàn)的,自然界中。 前言 說到力導向可能很多小伙伴都只是會使用,不知道其中的實現(xiàn)原理,今天,我們一起來自己實現(xiàn)一套力導向算法,然后做一些技術(shù)相關(guān)的延伸。發(fā)散下思維。 什么是力導向算法? 根據(jù)百科的介紹:力導向算法是指通過對每個節(jié)點的計算,算出引力和排斥力綜合的合力...
摘要:這里我也給大家推薦一些數(shù)據(jù)可視化的圖形庫不過這些圖形庫一般需要一些的基礎(chǔ)知識輸入數(shù)據(jù)即可生成圖形,自由發(fā)揮程度較低百度出品,與很像,個人覺得略丑推薦,但不適合新手,圖表漂亮,靈活性高以上都可以先去閱讀官方文檔未完待續(xù) 如果你想建立一個自己的網(wǎng)站,你可以從網(wǎng)上搜到許多的教程:比如 wordpress gitpages 等等。 如果你想了解這個框架是怎么工作的,你可以了解以下下面的三個...
閱讀 2570·2021-11-23 09:51
閱讀 3120·2019-08-30 15:54
閱讀 1070·2019-08-30 14:14
閱讀 3542·2019-08-30 13:59
閱讀 1393·2019-08-29 17:09
閱讀 1468·2019-08-29 16:24
閱讀 2848·2019-08-29 15:43
閱讀 911·2019-08-29 12:45