自訂視覺化 API 2.0 參考資料

呼叫 looker.plugins.visualizations.add 函式是進入 Visualization API 的進入點。這個函式接受圖表物件,可完整定義自訂圖表。

以下是圖表範例:

looker.plugins.visualizations.add({
    create: function(element, config){
        element.innerHTML = "<h1>Ready to render!</h1>";
    },
    updateAsync: function(data, element, config, queryResponse, details, doneRendering){
        var html = "";
        for(var row of data) {
            var cell = row[queryResponse.fields.dimensions[0].name];
            html += LookerCharts.Utils.htmlForCell(cell);
        }
        element.innerHTML = html;
        doneRendering()
    }
});

環境

由於 Visualization API 是純 JavaScript,因此您可以使用任何 JavaScript 程式庫,以圖表呈現資料。

JavaScript 程式碼會在沙箱 iframe 中執行,與 Looker 執行個體分開。不過,自訂圖表作者仍須確保編寫的程式碼安全無虞。

與所有網頁開發作業一樣,支援不同網路瀏覽器 (Chrome、Edge、Firefox) 有時可能會發生問題。Visualization API 適用於 Looker 支援的所有瀏覽器,但您必須確保自訂程式碼支援瀏覽器。舉例來說,大多數瀏覽器都支援 ES6 的用法,例如 let 或 ()=>,但 IE11 或使用 PhantomJS 算繪 PDF 時可能會發生錯誤。

安裝

如要安裝自訂圖表,請依序前往「管理」>「平台」>「圖表」表單,定義資訊清單。資訊清單包含不重複的字串 ID、人類可讀的標籤、視覺化效果的 URI,以及您需要的任何依附元件連結 (例如:d3、jQuery、underscore)。

自訂視覺化效果應以 HTTPS 內容的形式,從 Looker 外部提供。如果您是從第一版自訂圖表 API 遷移,looker/plugins/visualizations 目錄中可能會有檔案。您仍可存取這個位置,並提供視覺化內容的相對路徑,但建議您將內容遷移至其他位置。由於 /plugins 目錄不在共用檔案系統中,叢集環境將無法存取所有節點上的視覺化檔案。

視覺化物件

圖表物件會使用下列必要、選用和新增屬性。

必要屬性

  • create function

    系統會在頁面上首次繪製圖表時,呼叫這個函式一次。請務必設定您希望圖表一律提供的內容。您可以載入程式庫,或建立一組日後會用到的元素和控制項。

    查看 create 函式的詳細資料 →

  • updateAsync / update 函式

    每當圖表狀態可能需要變更時,系統就會呼叫這個函式。這個函式一律會在 create 之後呼叫,而且可能會呼叫多次,因此應盡可能加快速度。

    呼叫這個函式的原因有很多,但通常是因為要視覺化的查詢有所變更、設定選項有所變更,或圖表大小有所調整。

    這個函式有同步和非同步版本,您只需要指定其中一個。(同時定義兩者會發生錯誤)。由於 iframe 的性質,非同步方法在 PDF 算繪方面更可靠。

    查看這些 update 函式的詳細資料 →

選用屬性

  • options object

    這個物件會詳細說明使用者可在圖表上設定的選項。

    查看公開設定 UI 的詳細資料 →

  • destroy function API V2 尚未實作

    在圖表從頁面中移除前呼叫的函式。請使用這個函式清除所有事件監聽器或其他狀態。舉例來說,如果使用者關閉視窗,系統可能就不會呼叫這個函式。

新增廣告屬性

將視覺化效果傳遞至 looker.plugins.visualizations.add 後,Looker 會自動將下列屬性新增至物件。在 create、update、updateAsync 和 destroy 函式的結構定義中,您可以使用 this 參照這些函式。

  • addError 函式

    圖表程式碼可能會呼叫這個函式,指示 UI 顯示錯誤訊息,而非圖表。並採用 error 物件。

    錯誤訊息新增後會持續顯示,直到呼叫 clearErrors 為止。

    範例:

    this.addError({
        title: "Two Dimensions Required",
        message: "This really great visualization requires two dimensions."
    });
    
  • clearErrors function

    您的視覺化程式碼可能會呼叫這個函式,清除使用 addError 新增的任何錯誤。

    範例:

    this.clearErrors();
    
  • trigger 函式

    可呼叫的函式,用於觸發視覺化以外的事件。

    查看活動詳細資料 →

    範例:

    this.trigger("limit", [20]);
    

create 函式

create 函式會傳遞兩個參數:element 和 config。

create: function(element, config){
  // Your update code here.
},

參數

  • element DOMElement

    代表容器的 DOM 元素,用於算繪視覺化內容。

  • config 物件

    代表使用者為這個圖表設定的任何設定選項值。

    範例:{my_configuration_option: "User Value"}

updateAsync 和 update 函式

建議使用 updateAsync 方法更新圖表。這個方法可讓圖表執行非同步動作,例如載入檔案或傳送網頁要求。

這個版本的函式有一個額外參數,也就是轉譯完成時要呼叫的回呼:

updateAsync: function(data, element, config, queryResponse, details, done){
    // An example of an asynchronous update, fetching a file.
    d3.request("https://example.com/fun-file.docx").response(function(xhr) {
        // Your update code here that uses this file.
        done();
    });
}

圖表算繪完成時,Looker 會收到通知,以便最佳化 PDF 算繪,並確保正確擷取圖表圖片。

部分舊版圖表會使用 update 函式。這項函式仍可運作,但並非首選方法,因為使用這項函式代表 Looker 不會在圖表完全算繪時收到通知。update 函式會傳遞五個參數:

update: function(data, element, config, queryResponse, details){
  // Your update code here.
}

參數

  • data 陣列

    代表查詢中目前資料的資料列陣列。可以是 null。

    每一列都是一個物件,其鍵代表欄位名稱,值則代表「儲存格」物件。以下是處理儲存格物件的詳細資料。

  • element DOMElement

    代表容器的 DOM 元素,用於算繪視覺化內容。

  • config object

    這個物件代表使用者為這個圖表設定的任何設定選項值。

    示例:{my_configuration_option: "User Value"}

  • queryResponse 物件

    代表目前查詢中繼資料的物件,例如欄位的中繼資料。可以是 null。

  • details object

    目前轉譯背景的詳細資料。包含圖表算繪原因和變更內容的相關資訊。這項資訊通常只用於進階案例。

    對於使用新版資訊主頁體驗的 Looker 資訊主頁中的交叉篩選器,允許的屬性包括 crossfilterEnabled 和 crossfilters。

    print 屬性可與 done 函式搭配使用,改善自訂圖表的 PDF 算繪效果,尤其是包含動畫的圖表。例如:

    if (details.print) {
            done();
    }
    
  • done 函式

    回呼,表示圖表已完全算繪。如果圖表需要執行非同步呼叫或轉譯為 PDF,則呼叫這個函式特別重要。

算繪資料

Looker 在 LookML 中提供豐富的資料格式設定工具,可用來自訂資料點的外觀和行為。這些工具包括欄位層級的 LookML 設定,例如自訂值格式、HTML、向下鑽取連結和資料動作。

儲存格具有 value 屬性,這是所有情況下唯一存在的屬性。這個屬性是 JavaScript 型別,與儲存格所屬欄位的型別相符。不過,直接將 value 屬性插入 HTML 或 SVG 並不安全,因為系統未執行任何 HTML 逸出作業,且部分欄位值是複雜的 JavaScript 物件或陣列,會以不適當或令人困惑的方式轉譯。

為確保所有視覺化效果都能一致且安全地算繪這些項目,您可以使用多種公用函式,將傳遞至圖表的 data 中的儲存格中繼資料,轉換為不同用途的不同表示法。在某些情況下,儲存格中繼資料可能會壓縮或省略特定欄位,而這些輔助函式可讓您提供一致的體驗。

這些輔助函式都可在全域 LookerCharts.Utils 物件上使用。

  • LookerCharts.Utils.textForCell(cell)

    這個函式會接受儲存格,並傳回適合顯示的字串表示法。這項函式一律會傳回字串,不會傳回 null 或任何其他類型。

  • LookerCharts.Utils.htmlForCell(cell)

    這個函式會接受儲存格,並傳回含有 HTML 的字串。這個函式一律會傳回字串,不會傳回 null 或任何其他類型。

    這個函式的輸出內容會經過適當逸出處理,可直接插入元素的 HTML 中。如果資料適合,輸出 HTML 也會在點選時正確顯示細查選單。

  • LookerCharts.Utils.filterableValueForCell(cell)

    這個函式會接受儲存格,並傳回與該儲存格值相符的 Looker 進階篩選器語法字串。

  • LookerCharts.Utils.toggleCrossfilter({row, pivot, event})

    這個函式接受資料列、資料透視或事件,用於檢查圖表是否啟用交叉篩選功能。以下範例說明如何為元素新增事件監聽器,在事件發生時檢查是否已啟用交叉篩選:

    d3.select("#myElement")
    .on("click", function (d) {
        if (details.crossfilterEnabled) {
                LookerCharts.Utils.toggleCrossfilter({
                    row: d.row,
                    event: d3.event,
                });
        } else {
          // ... handle click when cross-filtering is not enabled
        }
    });
    
  • LookerCharts.Utils.getCrossfilterSelection(row, pivot?)

    這個函式接受資料列或資料透視,用於檢查自訂圖表是否選取該資料列或資料透視。如果 NONE,函式會傳回 CrossfilterSelection {NONE, SELECTED, UNSELECTED} 的列舉 0;如果 SELECTED,則傳回 1;如果 UNSELECTED,則傳回 2。

    以下範例會根據條件,為交叉篩選的資料列套用填滿顏色,並在未啟用交叉篩選時套用預設顏色:

    d3.select("#myElement")
    .attr("fill", function (d) {
        const crossfilter = LookerCharts.Utils.getCrossfilterSelection(d.row)
        if (details.crossfilterEnabled && crossfilter === 1) {
                return d.color
        } else {
                return "#DEE1E5" //Hex used for unselected elements in native visualizations
    ...
    
  • LookerCharts.Utils.openDrillMenu(options)

    htmlForCell 的輸出內容會視需要自動顯示細查選單,但這可能不適用於某些類型的轉譯。(例如,SVG 無法轉譯 HTML,但您可能想擷取點擊事件來開始細查)。

    options 物件包含下列參數:

    • links 必要 陣列

      從儲存格的 links 屬性傳回的物件陣列。如要一次顯示多個儲存格的連結,可以先將這些陣列串連在一起。如果是自訂連結,請提供物件陣列,格式如下:

      { label: string, type: 'drill', type_label: string, url: url }

    • event HTML DOM 事件

      導致深入鑽研事件的點擊 (或其他) 事件。Looker 會根據這項資訊決定細查選單的位置。如果沒有,請嘗試傳遞含有 pageX 和 pageY 座標的物件。

    範例:

    for (var row of data) {
        var cell = row[queryResponse.fields.dimensions[0].name];
        var cellElement = myBuildElementFunction(cell);
        cellElement.onclick = function(event) {
            LookerCharts.Utils.openDrillMenu({
                links: cell.links,
                event: event
            });
        };
        // ... more visualization stuff...
    }
    

呈現設定 UI

options 參數是物件,其中鍵是選項名稱的任意 ID,值則是說明選項資訊的物件。

範例如下:

options: {
    color_range: {
      type: "array",
      label: "Color Range",
      display: "colors"
    },
   top_label: {
      type: "string",
      label: "Label (for top)",
      placeholder: "My Great Chart"
    },
    transport_mode: {
      type: "string",
      label: "Mode of Transport",
      display: "select",
      values: [
         {"Airplane": "airplane"},
         {"Car": "car"},
         {"Unicycle": "unicycle"}
      ],
      default: "unicycle"
    }
}

選項物件參數

option 物件具有下列基本參數、顯示專用屬性和分類選項。

基本參數

  • type 字串

    選項的資料類型。

    允許的值: string (預設)、number、boolean、array

  • label 字串

    向使用者顯示的選項標籤,人類可讀。

  • default

    選項的預設值。如未指定,選項的值為 null。這個值應與 type 的類型相同。

  • display 字串

    某些 type 值可以透過不同方式呈現在 UI 中。

    • type 為 string 時:

      允許的值: text (預設)、select、radio

    • type 為 number 時:

      允許值: number (預設)、range

    • type為 array 時:

      允許的值: text (預設)、color、colors

  • placeholder 字串

    如果 display 值支援,則提供範例值或說明,提示使用者應輸入的內容。

多媒體廣告專屬屬性

  • values 物件陣列

    當 display 為 radio 或 select 時,陣列會包含要在介面中列出的標籤和值。

    陣列中的每個項目都應是具有單一鍵/值組合的物件,代表選項的標籤和值。標籤只會顯示在 UI 中,轉譯時只會收到值。

    範例:

    values: [
        {"Center": "c"},
        {"Left": "l"},
        {"Right": "r"}
    ]
    

    如果 display 為 radio,則每個選項都可以額外指定 description:

    values: [
        {"Cool": "c"},
        {"Uncool": {
                value: "unc",
                description: "Only choose this if the data is very uncool."
            }
        }
    ]
    
  • max number

    當 display 為 range 時,範圍滑桿可選取的最大值。

  • min number

    當 display 為 range 時,範圍滑桿可選取的最小值。

  • step number

    當 display 為 range 時,範圍滑桿上每個刻度代表的金額。

整理選項

  • section 字串

    如果圖表有很多選項,請為選項應顯示的區段加上標籤。使用者介面會依 section 值將選項分組。如果只有一個區段,系統就不會顯示區段 UI。

    如果您使用 section,則應為每個選項設定這個屬性。

  • order number

    代表使用者介面中選項顯示順序的數字。如果指定此選項,系統會依據這個順序排序選項。

  • display_size 字串

    代表 UI 中選項寬度的尺寸類別。舉例來說,如要並排顯示「最小值」和「最大值」選項,可以將這兩個選項的顯示大小設為 half。

    允許的值: normal (預設)、half、third

活動

圖表可觸發事件 (通常是為了回應使用者互動),進而更新圖表或查詢的屬性。

只要對圖表物件呼叫 trigger 函式,即可觸發這些事件。第一個參數一律是事件名稱,第二個參數則是引數陣列。

this.trigger("limit", [20]);

可用的事件

  • updateConfig

    更新圖表目前的設定。

    引數:包含要更新的設定鍵的物件。未指定的鍵不會變更。

    範例:

    var vis = this;
    $(element).find(".axis").click(function(){
        vis.trigger("updateConfig", [{axis_hidden: true}]);
    });
    
  • limit

    更新基礎查詢的限制:

    引數:代表查詢新限制的整數。

    var vis = this;
    $(element).find(".show-all").click(function(){
        vis.trigger("limit", [500]);
    });
    
  • filter

    更新基礎查詢的篩選器值:

    var vis = this;
    $(element).find(".show-all-tommys").click(function(){
        vis.trigger("filter", [{
            field: "users.name", // the name of the field to filter
            value: "%tommy%", // the "advanced syntax" for the filter
            run: true, // whether to re-run the query with the new filter
        }]);
    });
    
  • loadingStart

    將圖表標示為載入中。大多數情況下,您不需要這麼做,但如果圖表從遠端位置載入物件或執行長時間的計算,您可以使用這個方法繼續顯示載入指標。

    在 loadingEnd 觸發前,系統會顯示載入中。

  • loadingEnd

    將視覺化效果標示為不再載入。

  • printSize (Looker 26.0 以上版本)

    在將資訊主頁匯出為 PDF 時,允許視覺化圖表使用「展開資料表即可顯示所有資料列」選項。應用程式可透過這個事件得知轉譯內容的高度,並適當展開資訊主頁圖塊,以便顯示所有資訊供列印。

      this.trigger('printSize', {
        heightExpanded: FULL_HEIGHT_IN_PIXELS
      });
    
  • registerOptions (Looker 5.24 以上版本)

    允許圖表在註冊後註冊其他選項:

      update: function(data, element, config, queryResponse, details){
        options = {}
        // Create an option for each measure in your query
        queryResponse.fields.measure_like.forEach(function(field) {
          id = "color_" + field.name
          options[id] =
          {
        label: field.label_short + " Color",
        default: "#8B7DA8",
        section: "Style",
        type: "string",
        display: "color"
          }
        })
        this.trigger('registerOptions', options) // register options with parent page to update visConfig
        ...
      }
    });