iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 22
1
AI & Data

D3.js資料視覺化的浪漫突進系列 第 22

Day22 D3js d3與canvas

  • 分享至 

  • twitterImage
  •  

D3js d3與canvas

用途

如果有需求必須要在Canvas上繪圖時會用上。

流程

因為其實d3確實沒提供直接繪圖於Canvas的方法,但其實與Svg不同也只是最後繪製方法,Svg是透過一堆DOM元素透過設定屬性,形成的圖表。Canvas則是使用Context透過API進行繪圖。

所以目前的方式,d3處理資料與模型同步的事,以及相對位置以及Scale的計算。Canvas負責繪圖。

實踐

簡易範例

const base = d3.select("#vis");
const chart = base.append("canvas")
  .attr("width", 400)
  .attr("height", 300);

const context = chart.node().getContext("2d");
const data = [1,2,13,20,23];

const scale = d3.scaleLinear()
  .range([10, 390])
  .domain([1,23]);

data.forEach(function(d, i) {
  context.beginPath();
  context.arc(scale(d), 75, 5, 0, 2 * Math.PI);
  context.fillStyle="red";
  context.fill();
  context.closePath();
});

下半部就是繪圖重點,其實也只是去遍歷資料,並使用CanvasAPI進行繪圖,

複雜範例

複雜範例的作法其實是在原本d3內產出的元件使用custom自訂元件,但仍然有對應資料的屬性。
當產玩這種假的元件之後,再讀出所有假元件的屬性,並繪製在Canvas上。

const base = d3.select("#vis");
const chart = base.append("canvas")
  .attr("width", 400)
  .attr("height", 300);

const context = chart.node().getContext("2d");
const data = [1,2,13,20,23];
const detachedContainer = document.createElement("custom");
const dataContainer = d3.select(detachedContainer);
drawCustom([1,2,13,20,23]);

function drawCustom(data) {
  const scale = d3.scaleLinear()
    .range([10, 390])
    .domain([1,23]);
    
 // 這邊都使用假原件來模擬真實元件產生對應的屬性。
  const dataBinding = dataContainer.selectAll("custom.rect")
    .data(data, function(d) { return d; });

  dataBinding
    .attr("size", 15)
    .attr("fillStyle", "green");

 // 加入假元件
  dataBinding.enter()
      .append("custom")
      .attr('class', 'rect')
      .attr("x", scale)
      .attr("y", 100)
      .attr("size", 8)
      .attr("fillStyle", "red");
 // 移除假元件
  dataBinding.exit()
    .attr("size", 5)
    .attr("fillStyle", "lightgrey");


  // 呼叫Canvas繪圖方法
  drawCanvas();
}
  
function drawCanvas() {
  // clear canvas
  context.fillStyle = "#fff";
  context.rect(0,0,chart.attr("width"),chart.attr("height"));
  context.fill();

  // 撈出所有假元件,並且在對假元件們進行遍歷,之後繪製出`Canvas`畫面。
  const elements = dataContainer.selectAll("custom.rect");
  elements.each(function(d) {
    const node = d3.select(this);

    context.beginPath();
    context.fillStyle = node.attr("fillStyle");
    context.rect(node.attr("x"), node.attr("y"), node.attr("size"), node.attr("size"));
    context.fill();
    context.closePath();

  });
}

結論

其實都可以使用假元件並自己實作繪圖部分,讓d3的資料同步與計算部分,在各種繪圖框架上使用。

Codepen範例

參考

d3js-and-canvas


上一篇
Day21 D3js d3.tree 樹狀資料結構視覺化
下一篇
Day23 D3js Candlestick Chart來張K線圖吧!
系列文
D3.js資料視覺化的浪漫突進30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言