abstrakt: D3允許你將任意的數(shù)據(jù)綁定到文檔對(duì)象模型(DOM),然后運(yùn)用數(shù)據(jù)驅(qū)動(dòng)轉(zhuǎn)換到文檔上。例如,你可以使用D3將一個(gè)數(shù)組生成一個(gè)HTML表格?;蛘撸褂孟嗤臄?shù)據(jù)來創(chuàng)建一個(gè)有平滑過渡和交互的交互式SVG條形圖。 D3不是一個(gè)旨在提供每一個(gè)可能想到的功能的單一框架。相反的,D3所解決的問題的關(guān)鍵是:高效操作基于數(shù)據(jù)的文檔。它提供了顯著的靈活性,展現(xiàn)了web標(biāo)準(zhǔn)的全部功能,比如HTML、
D3允許你將任意的數(shù)據(jù)綁定到文檔對(duì)象模型(DOM),然后運(yùn)用數(shù)據(jù)驅(qū)動(dòng)轉(zhuǎn)換到文檔上。例如,你可以使用D3將一個(gè)數(shù)組生成一個(gè)HTML表格?;蛘?,使用相同的數(shù)據(jù)來創(chuàng)建一個(gè)有平滑過渡和交互的交互式SVG條形圖。
D3不是一個(gè)旨在提供每一個(gè)可能想到的功能的單一框架。相反的,D3所解決的問題的關(guān)鍵是:高效操作基于數(shù)據(jù)的文檔。它提供了顯著的靈活性,展現(xiàn)了web標(biāo)準(zhǔn)的全部功能,比如HTML、SVG 和 CSS。D3非???,它以最小的開銷支持大型數(shù)據(jù)集以及交互與動(dòng)畫的動(dòng)態(tài)行為。D3的函數(shù)式風(fēng)格使代碼通過組件和插件的多元化集合得以重用。
Pentaho中引入D3圖形庫
通過Pentaho的插件倉庫Marketplace下載D3軟件包,具體操作加下圖:
重啟Pentaho軟件,然后查看D3可視化庫是否正確引入,見下圖:
如果出現(xiàn)上述的情況,說明D3可視化庫引入成功,小編恭喜你可以進(jìn)入D3的可視化編程啦!
D3圖形間聯(lián)動(dòng)實(shí)戰(zhàn)
繪圖效果展示和圖形聯(lián)動(dòng)說明
通過點(diǎn)擊右邊的門店柱狀圖,左邊的時(shí)段柱狀圖做相應(yīng)的聯(lián)動(dòng), 其中在圖形之間傳遞的參數(shù)是門店的ID;在此處,我想要強(qiáng)調(diào)的是:較之于Pentaho CDE的繪圖原則,D3的繪圖更顯得自由;Pentaho CDE繪制的圖形適用于一般意義上的大數(shù)據(jù)展現(xiàn),但是我們有時(shí)候需要為我們的客戶定制個(gè)性化的圖形,一旦圖形追求個(gè)性化必然會(huì)導(dǎo)致我們Pentaho提供的圖形的樣式無法滿足我們的需求,此時(shí)D3的繪圖將是我們的一條出路,但由于D3的學(xué)習(xí)曲線較為陡峭,所以國(guó)內(nèi)的大數(shù)據(jù)攻城獅一般會(huì)選擇容易實(shí)現(xiàn)的圖形庫,譬如Echarts(https://my.oschina.net/u/2453090/blog/777048)或HighCharts,但是這些都不是很好的選擇,掌握D3圖形庫的編程將成為大數(shù)據(jù)攻城獅必不可少的技能,接下來我們將通過代碼的講解對(duì)D3的可視化編程做簡(jiǎn)單的介紹,希望的小編的這篇文章對(duì)您有所幫助!
核心代碼講解
通過上文,我們假設(shè)您已將D3組件庫集成到Pentaho,那我們?nèi)绾问褂眠@個(gè)圖形庫喃?接下來小編將介紹這個(gè)強(qiáng)大的圖形庫的使用。
如上圖,它的使用更CDE的圖形庫組件沒什么區(qū)別,與CDE繪圖有所區(qū)別的是,D3的繪圖代碼需要開發(fā)者手寫,不像CDE通過屬性設(shè)置的,具體見下圖:
時(shí)段柱狀圖代碼:
function f(dataset){ var data = this.cdaResultToD3Array(dataset); var margin = {top: 50, right: 20, bottom: 30, left: 100}, width = this.getWidth() - margin.left - margin.right - 40, height = this.getHeight() - margin.top - margin.bottom; var formatPercent = d3.format("/1000K"); var x = d3.scale.ordinal() .rangeRoundBands([0, width], .1, .5); var y = d3.scale.linear() .range([height, 0]); var xAxis = d3.svg.axis() .scale(x) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("left") .tickFormat(formatPercent); var svg = d3.select("#"+this.htmlObject).append("svg") .classed("svg-container", true) //container class to make it responsive .attr("preserveAspectRatio", "xMinYMin meet") .attr("viewBox", "0 0 600 400") .classed("svg-content-responsive", true) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); data.forEach( function(d) { d.ItemSaleAmt = +d.ItemSaleAmt; } ); x.domain(data.map(function(d) { return d.HourNo; })); y.domain([0, d3.max(data, function(d) { return d.ItemSaleAmt; })]); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("transform", "rotate(-90)") .attr("y", 6) .attr("dy", ".71em") .style("text-anchor", "end") .text("時(shí)段銷售額"); svg.selectAll(".bar") .data(data) .enter().append("rect") .attr("class", "bar") .attr("x", function(d) { return x(d.HourNo); }) .attr("width", x.rangeBand()) .attr("y", function(d) { return y(d.ItemSaleAmt); }) .attr("height", function(d) { return height - y(d.ItemSaleAmt); }); function resize(e){ var width = $('#HourNoHtmlObj').width(); var height = $('#HourNoHtmlObj').height(); svg.attr('width', width); svg.attr('height', height); force.size([width, height]).resume(); } }
門店柱狀圖代碼:
function f(dataset){ var data = this.cdaResultToD3Array(dataset); console.log(data); var margin = {top: 50, right: 20, bottom: 30, left: 100}, width = this.getWidth() - margin.left - margin.right - 10, height = this.getHeight() - margin.top - margin.bottom; var formatPercent = d3.format(".00"); var x = d3.scale.ordinal() .rangeRoundBands([0, width], .1, .2); var y = d3.scale.linear() .range([height, 0]); var xAxis = d3.svg.axis() .scale(x) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("left") .tickFormat(formatPercent); var svg = d3.select("#"+this.htmlObject).append("svg") .classed("svg-container", true) .attr("preserveAspectRatio", "xMinYMin meet") .attr("viewBox", "0 0 600 400") .classed("svg-content-responsive", true) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); data.forEach( function(d) { d.Amount = +d.Amount; } ); x.domain(data.map(function(d) { return d.Name; })); y.domain([0, d3.max(data, function(d) { return d.Amount; })]); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("transform", "rotate(-90)") .attr("y", 6) .attr("dy", ".71em") .style("text-anchor", "end") .text("門店銷售額"); svg.selectAll(".bar") .data(data) .enter().append("rect") .attr("class", "bar") .attr("x", function(d) { return x(d.Name); }) .attr("width", x.rangeBand()) .attr("y", function(d) { return y(d.Amount); }) .attr("height", function(d) { return height - y(d.Amount); }); svg.selectAll(".bar").on("click", function(d/*,event*/) { if($("#HourNoHtmlObj > svg").length > 0){ $('#HourNoHtmlObj svg').remove(); Dashboards.fireChange('OutletId', d.Id); }else{ Dashboards.fireChange('OutletId', d.Id); } }); }