Looker Visualization API は、 サンドボックス化された iframe で実行され、Looker アプリケーション内でホストされる JavaScript API です。
同じビジュアリゼーション コードを使用して、Looker の任意の場所(Explore、Look、ダッシュボード、埋め込み、PDF、レンダリングされた画像)にビジュアリゼーションを表示できます。
各ビジュアリゼーションは、単一の Looker クエリのビューを表します。 Looker はクエリを実行し、結果をビジュアリゼーション コードに渡します。また、Looker は、ビジュアリゼーション コードが描画できる DOM 要素も渡します。
要件
始める前に、次の要件を満たしていることを確認してください。
- JavaScript とウェブ開発に関するある程度の知識が必要です。
- LookML プロジェクト マニフェスト ファイルを作成して更新するには、Looker 管理者権限が必要です。
Hello World ビジュアリゼーションを作成する
このセクションでは、指定されたクエリの最初のディメンションを表示するカスタム ビジュアリゼーション スクリプトを作成する方法について説明します。
最終的な結果は、次の画像のようになります。

設定
Looker でビジュアリゼーションを開発してテストするには、次の 2 つの方法があります。
これらのオプションのいずれかを構成したら、このセクションの例に沿って hello_world.js を作成できます。
基本的なコード構造
この例の最終的なソースコードを表示するには、 GitHub リポジトリをご覧ください。
ホストしているフォルダに、新しい空の JavaScript ファイルを作成し、hello_world.js という名前を付けます。
新しいカスタム ビジュアリゼーションを Looker に登録するには、looker.plugins.visualizations.add 関数を呼び出して、ビジュアリゼーション オブジェクトを渡します。
このオブジェクトには、ビジュアリゼーションの定義とその構成 UI が含まれています。
次の例は、必要なプロパティがすべて入力されたビジュアリゼーションのスケルトンを示しています。これには、ビジュアリゼーション コードを記述できる create 関数と updateAsync 関数が含まれています。
looker.plugins.visualizations.add({
create: function(element, config) {
},
updateAsync: function(data, element, config, queryResponse, details, done) {
}
})
このコードは有効な Looker ビジュアリゼーションですが、まだ視覚化されておらず、空白のボックスとして表示されます。
準備
create 関数には、element と config の 2 つの引数があります。
Looker は element を提供します。これは、ビジュアリゼーションを配置するために Looker が必要とする
DOM 要素
です。
Looker はこの要素を構築し、適切なサイズにします。コンテンツを配置する必要があります。
create 関数を使用すると、要素の初期設定を行うことができます。この例では、次の HTML 構造のようなグラフを作成します。
<style>
/* custom styles for your chart */
</style>
<div class="hello-world-vis">
<div>Data Goes Here</div>
</div>
JavaScript を使用して、この構造に合わせて要素を DOM 要素に挿入できます。
次の例は、詳細を追加したこの関数を示しています。
create: function(element, config) {
// Insert a <style> tag with some styles to use later.
var css = element.innerHTML = `
<style>
.hello-world-vis {
/* Vertical centering */
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
}
</style>
`;
// Create a container element to center the text.
var container = element.appendChild(document.createElement("div"));
container.className = "hello-world-vis";
// Create an element to contain the text.
this._textElement = container.appendChild(document.createElement("div"));
},
このコードは CSS を追加し、hello-world-vis コンテナを作成して、その中に div を追加します。
また、このコードは、レンダリングするコンテナに this._textElement を割り当てます。これにより、グラフのレンダリングが開始されたときに、後で再度検索する必要がなくなります。
create 関数は、1 回だけ実行する必要がある設定タスクを行うのに便利な場所です。
レンダリング
このセクションでは、updateAsync メソッドを拡張してデータを可視化する方法について説明します。このメソッドは、グラフで変更を可視化する必要がある場合や、グラフのレンダリング方法に影響する可能性のある他のイベント(グラフのサイズ変更や構成オプションの変更など)が発生した場合に呼び出されます。
この例では、最初のセルの最初のディメンションのみを見つける必要があります。
これを行うには、データセットのすべての行の配列である data と、フィールド名やタイプなどのクエリに関するメタデータを含む queryResponse を使用します。
LookerCharts.Utils.htmlForCell というヘルパー メソッドを使用して、そのセルのデータポイントの適切な HTML 表現を提供することもできます。このメソッドは、ドリルリンク、書式設定、データアクションなどの要素を自動的に処理します。
updateAsync: function(data, element, config, queryResponse, details, done) {
// Grab the first cell of the data.
var firstRow = data[0];
var firstCell = firstRow[queryResponse.fields.dimensions[0].name];
// Insert the data into the page.
this._textElement.innerHTML = LookerCharts.Utils.htmlForCell(firstCell);
// Always call done to indicate a visualization has finished rendering.
done()
}
これで、カスタム ビジュアリゼーションを機能させるために必要な手順は完了です。ただし、エラー処理用のメソッドを含めることが重要です。
エラー処理
updateAsync コードはデータの最初の行を取得しますが、クエリが結果を返さない場合や、ディメンションが含まれていない場合はエラーが発生する可能性があります。
エラー処理を行わないと、ブラウザのコンソールに JavaScript エラーが表示され、グラフがレンダリングされない場合にユーザーが混乱する可能性があります。
グラフは、レンダリング中に問題が発生した場合に、カスタム エラー メッセージを表示できます。Looker は、ビジュアリゼーション オブジェクトに addError 関数と clearErrors 関数の 2 つの関数を追加します。これらの関数を使用して、すべてのユーザーにわかりやすいエラー メッセージを表示できます。
これらの関数はビジュアリゼーション オブジェクトに追加されるため、this オブジェクトを介して updateAsync 関数のコンテキストから使用できます。
updateAsync メソッドの先頭を変更して、エラー状態を検出し、ユーザーに問題を通知して、レンダリングを試行する代わりに終了できます。
updateAsync: function(data, element, config, queryResponse, details, done) {
// Clear any errors from previous updates.
this.clearErrors();
// Throw some errors and exit if the shape of the data isn't what this chart needs.
if (queryResponse.fields.dimensions.length == 0) {
this.addError({title: "No Dimensions", message: "This chart requires dimensions."});
// Always call done() before exiting early to avoid dashboard exports hanging
done();
return;
}
if (!data || data.length === 0) {
this.addError({title: "No Data", message: "The query returned no results."});
done();
return;
}
// ... the rest of the update code here ...
ユーザーが指標のみを含むクエリを作成すると、次のようなエラー メッセージが表示されます。

非同期レンダリングと PDF エクスポート
前の「Hello World」の例では、DOM が更新された直後に done() 関数が呼び出されます。innerHTML の設定は同期であるため、このアプローチは適切です。
ただし、D3.js、Chart.js、React などのグラフ作成ライブラリを使用する場合、レンダリングは非同期になる可能性があります。スクリプトの末尾で done() を呼び出すと、Looker がグラフの描画が完了する前に PDF または PNG エクスポートのスクリーンショットをキャプチャし、空白のタイルになる可能性があります。
Looker がダッシュボードをエクスポートする場合、ヘッドレス ブラウザを使用し、done() コールバックを使用してスクリーンショットを安全に取得できるタイミングを把握します。
グラフが正しくエクスポートされるようにするには、done() コールバックをライブラリの完了イベントに関連付け、details.print フラグを使用してエクスポート中のアニメーションを無効にする必要があります。
次の例は、D3.js を使用して非同期レンダリングを処理する方法を示しています。
updateAsync: function(data, element, config, queryResponse, details, done) {
this.clearErrors();
// Check if Looker is exporting the chart to a PDF/PNG
const isExport = details && details.print === true;
// Clear previous elements
this.svg.selectAll("*").remove();
const circle = this.svg.append("circle")
.attr("cx", 50)
.attr("cy", 50);
if (isExport) {
// Instant render for exports. Draw the final state immediately with no transitions
circle.attr("r", 40);
// Tell Looker to take the screenshot right now
done();
} else {
// If it's for the browser, start small and animate
circle.attr("r", 0)
.transition()
.duration(1000)
.attr("r", 40)
.on("end", () => {
// Tell Looker the animation is fully complete
done();
});
}
}
React を使用する場合は、done コールバックをレンダリング関数の 3 番目の引数として渡して、Looker が React のコンポーネントのマウントを待機するようにします。
this.chart = ReactDOM.render(
<MyCustomChart data={data} />,
element,
done // Looker waits for React to finish
);
構成
ユーザーがビジュアリゼーションの側面をカスタマイズできるようにすることができます。
ビジュアリゼーション オブジェクトの他のプロパティに加えて、options という名前のプロパティを使用できます。
このプロパティを使用して、グラフに必要なオプションの種類を指定できます。
looker.plugins.visualizations.add({
options: {
font_size: {
type: "string",
label: "Font Size",
values: [
{"Large": "large"},
{"Small": "small"}
],
display: "radio",
default: "large"
}
},
// ... rest of visualization object ...
この例では、ラジオボタンとして表示される font_size オプションを作成し、ユーザーが「小」と「大」のフォントサイズを選択できるようにします。
ビジュアリゼーション ピッカーにオプションを追加するには、options プロパティを指定する必要があります。
このオプションをコードで使用するには、updateAsync メソッドに config パラメータがあることを思い出してください。このパラメータには、次の選択したオプションが含まれています。
updateAsync: function(data, element, config, queryResponse, details, done) {
config オブジェクトは次のようになります。
{font_size: "large"}
グラフを更新するときに、このオブジェクトを確認して適切に対応できます。 フォントサイズの変更を実装するには、更新メソッドの末尾に次のチェックを追加します。
if (config.font_size == "small") {
this._textElement.className = "hello-world-text-small";
} else {
this._textElement.className = "hello-world-text-large";
}
`create` メソッドで追加した `<style>` タグを更新して、`
hello-world-text-small` CSS クラスと `hello-world-text-large` CSS クラスを定義する必要があります。
.hello-world-text-large {
font-size: 72px;
}
.hello-world-text-small {
font-size: 18px;
}
updateAsync 関数は構成が変更されるたびに呼び出され、Looker は構成を自動的に保存するため、構成設定に対応するために必要な作業はこれだけです。
次のステップ
この「Hello World」ビジュアリゼーションの完全なソースコードは、Looker オープンソース GitHub リポジトリで確認できます。
その他の機能の詳細については、 Visualization API リファレンスをご覧ください。