こんにちは。Visual M2M Data Visualizer の開発を担当している白金です。
この度、Visual M2M Data Visualizer Ver3.0.0 のアップデートとあわせて 可視化用パーツ「ビジュアルパーツ」を開発するための開発キット(以下「Visual Parts SDK」) をリリースしました。
Visual Parts SDKを使用して可視化用パーツをカスタマイズ開発することで、Visual M2M Data Visualizerに、ユーザー様自身やパートナー企業様の手で新しい可視化方法を追加することが可能になります。
早速、Visual Parts SDKを使ってフリートマップのビジュアルパーツを作ってみたので Visual Parts SDK とあわせて紹介したいと思います。
Visual Parts SDK の紹介
Visual Parts SDK とは
Visual M2M Data Visualizer (以下「Data Visualizer」) に表示する可視化パーツをカスタマイズ開発するためのSDKです。
Visual Parts SDK により、ユーザー様自身やパートナー企業様のご要望に対して Data Visualizer に含まれている標準ビジュアルパーツで表現が難しかった可視化方法が、カスタマイズ開発することで解決することが可能になります。
Visual Parts SDKの構成
Visual Parts SDK は JavaScript の言語をサポートしている 以下2つのnpmパッケージで構成しています。
@aptpod/data-viz-visual-parts-sdk
(APIライブラリー)
Visual Parts SDKの本体です。Data VisualizerのAPIを提供するライブラリーです。
@aptpod/data-viz-create-visual-parts-react
(ワークスペース作成ツール)
ビジュアルパーツの開発に使用するワークスペース(開発用のディレクトリ)を作成するためのパッケージスクリプトです。ビジュアルパーツを開発する際に、このスクリプトを使用することは必須ではありませんが、使用するとTypeScript, React, Styled Components などのフレームワークも活用して効率的に開発を進めることができます。
詳細についてはビジュアルパーツの作成ガイド「Visual Parts SDKによるData Visualizer用ビジュアルパーツの作成」を参照してください。
ローカル開発環境でサンプルのビジュアルパーツを表示する
@aptpod/data-viz-create-visual-parts-react のパッケージスクリプトを実行して開発用のワークスペースを作成します。
$ npx @aptpod/data-viz-create-visual-parts-react -o <workspace-directory>
作成したワークスペースにはサンプルとしていくつかのビジュアルパーツが付属しています。
以下の動画では、弊社のモバイル計測アプリ intdash Motion の加速度センサの値を、ワークスペースに含まれるサンプルビジュアルパーツを使って可視化しています。
動画で確認できる情報は下記のとおりです。
- ワークスペースを作る
- 依存パッケージをインストールする
- ローカル開発サーバーを起動する
- Data Visualizer にローカル開発サーバーのURLを設定する
- Sensor Value のサンプルビジュアルパーツを表示する
- Motion の計測を開始して、Sensor Value のビジュアルパーツでセンサーの値を可視化する
- Horizontal Barsのビジュアルパーツで複数のセンサーの値を可視化する
- ビジュアルパーツのLine Graph も同時に表示する
- ストアした計測したデータを表示する
Visual Parts SDK で利用可能なデータ
Visual Parts SDK を使用して下記データの連携が可能になります。
Data Visualizer から ビジュアルパーツへは 可視化に必要な情報、ビジュアルパーツから Data Visualizer には、変更されたビジュアルパーツの設定情報を連携することが可能です。
Visual Parts SDK を使用した標準ビジュアルパーツ
Data Visualizer に含まれている標準ビジュアルパーツも Visual Parts SDK を使用して作成されています。 Visual Parts SDKを使用してどんなパーツが作成できるのかを知っていただくために、標準ビジュアルパーツの中でもよく使われているものをいくつか紹介します。
単一データ
数値・テキストの表示、またはメーターで表現します。 まずは数値で可視化したい、または最大値に対してどれぐらい近づいたかなどを確認するときに使用します。
時系列データ
時系列のデータを折れ線グラフで表示したり2つのデータから散布図を可視化します。表示している時間範囲で計測データの前後関係(傾向)や、特徴点、または突出したデータが含まれていないか確認するときに使用します。
メディアデータ
H.264形式で計測した動画の可視化、またはPCMで計測した音声を再生することができます。 *1
Audio Player には、スペクトログラムを表示する機能も含まれています。
複数のビジュアルパーツを組み合わせる
ユーザー様自身やパートナー企業様の手で標準ビジュアルパーツを組み合わせてダッシュボードを作成することが可能です。
Visual Parts SDK を使用して作成したパーツは、その他の標準パーツと一緒にダッシュボード上に表示することができます。(下図赤枠)
ローカル開発環境でフリートマップを作る
ここから本題の作成したフリートマップについて紹介します。
作成したビジュアルパーツの紹介
まずは作成したパーツの紹介をします。 複数の車両の位置と走行速度、SOC (バッテリーの充電率)をリアルタイムで監視し、必要に応じて特定の車両(ドライバー)にアクションを指示するユースケースをイメージして作成しました。
また、マップ表示は、OpenStreetMap を使用してライセンスの範囲内でお手軽に実装できました。
LIVE計測中の動画はこちらです。
後から走行データ、SOCの残量を確認することも可能です。
Panel Option から OpenStreetMap の表示スタイルも変更できるように実装しました。
ビジュアルパーツを実装する
では、実際にビジュアルパーツの実装の内容を紹介したいと思います。
Visual Parts SDK のワークスペース作成ツール @aptpod/data-viz-create-visual-parts-react を使用します。
ビジュアルパーツの作成ガイド「Visual Parts SDKによるData Visualizer用ビジュアルパーツの作成」の手順のとおり、事前にサーバーの設定を完了しておきます。
ワークスペースを準備する
ビジュアルパーツを開発するためのワークスペースを作成します。
# ワークスペースのディレクトリを作成します $ npx @aptpod/data-viz-create-visual-parts-react -o visual-parts-fleet-map # ワークスペースに移動します $ cd visual-parts-fleet-map # 依存パッケージをインストールします $ npm ci
開発用のディレクトリを作成する
フリートマップの開発で使用するディレクトリ、ファイルを追加します。
追加作成したファイル構成は以下のとおりです。
ソースコードは GitHub を参照してください。
src - assets - images - fleet-map - th-fleet-map@3x.png ....... サムネイル画像です - entrypoint - fleet-map - parts ....................... View のReactサブコンポーネントを実装します - bar-sub-division-meter - car-maker - edge-card - edges-panel-title - map-zoom-controller - scrollbar - selector - props-selector.ts ........ Visual Parts SDK のデータから View の Component Props に変換します - component.tsx .............. View のReactコンポネントを実装します - container.tsx .............. Visual Parts SDK と Fleet Map Component を連結します - index.ts ................... ビジュアルパーツ Fleet Map を定義します - extension.tsx .............. ビジュアルパーツの設定、及びPanel Option を定義します - utils.ts ................... ヘルパーを実装します - index.ts ..................... エントリポイントの定義します (複数のビジュアルパーツを実装する場合はここにimportの行を追加します)
View を実装する
フリートマップ で表現したいComponent の Props を src/entrypoint/fleet-map/component.tsx
に定義します。
この定義に沿って React の Component を実装します。
type Props = { size: { /** unit: px */ width: number /** unit: px */ height: number } openStreetMap: { url: string attribution: string } datasets: { edgeUUID: string edgeName: string /** unit:degree */ lat: number /** unit:degree */ lng: number /** unit:degree */ heading: number /** unit: ratio */ soc: number /** unit: Km/h */ speed: number }[] }
Map の表示は OpenStreetMap を使用しています。
Leaflet 、及び React Leaflet *2 を使用してお手軽に実現しています。
import React, { memo, useMemo, useState, useCallback, useEffect } from 'react' import { renderToString } from 'react-dom/server' import { TileLayer, Marker, Map } from 'react-leaflet' import { Icon, Point } from 'leaflet' import { MapZoomController } from './parts/map-zoom-controller' import { CarMarker } from './parts/car-maker' import { Scrollbar } from './parts/scrollbar' import { EdgesPanelTitle } from './parts/edges-panel-title' import { EdgeCard } from './parts/edge-card' import * as C from './constant' import * as S from './style' import * as utils from './utils' type Props = { ... } export const FleetMap: React.VFC<Props> = memo((props) => { const { size, openStreetMap, datasets } = props const { width, height } = size const [centerCoord, setCenterCoord] = useState( C.OPEN_STREET_MAP_LAT_LNG_DEFAULT, ) const [zoom, setZoom] = useState(C.OPEN_STREET_MAP_ZOOM_DEFAULT) const [selectedEdgeUUID, setSelectedEdgeUUID] = useState(C.EDGE_UNSELECTED) // Zoom In / Outイベントハンドラ const onZoomIn = useCallback(() => { setZoom((prev) => Math.min(prev + 1, C.OPEN_STREET_MAP_ZOOM_IN_LIMIT)) }, []) const onZoomOut = useCallback(() => { setZoom((prev) => Math.max(prev - 1, C.OPEN_STREET_MAP_ZOOM_OUT_LIMIT)) }, []) // Mapを表示するサイズ、または OpenSteetMapのURLが変更になったら // Mapを再描画するようにKeyも変更する const mapKey = `${width}-${height}-${openStreetMap.url}` // マップのコンテナスタイル const mapContainerStyle = useMemo( () => ({ width, height: height - C.LAYOUT_HEADER_HEIGHT, }), [width, height], ) // マップの Center 座標を更新する // Edgeが未選択、または Lat, Lng が無効値なら更新しない useEffect(() => { datasets.forEach(({ edgeUUID, lat, lng }) => { if (edgeUUID === selectedEdgeUUID && utils.isFiniteLatLng(lat, lng)) { setCenterCoord([lat, lng]) } }) }, [datasets, selectedEdgeUUID]) // Edgeを選択するイベントハンドラを作成する // すでに同一のEdgeが選択済みの場合は選択を解除する const makeOnSelectEdgeUUID = useCallback((edgeUUID: string) => { return () => { setSelectedEdgeUUID((prev) => { return prev === edgeUUID ? C.EDGE_UNSELECTED : edgeUUID }) } }, []) //Car Marker の Icon を作成する const makeCarMarkerIcon = useCallback( (selected: boolean, heading: number) => { return new Icon({ iconUrl: utils.toDataURISchemaSvg( renderToString( <CarMarker size={C.CAR_MARKER_SIZE} selected={selected} rotationAngle={ isFinite(heading) ? heading : C.CAR_MARKER_HEADING_DEFAULT } />, ), ), iconAnchor: [C.CAR_MARKER_SIZE / 2, C.CAR_MARKER_SIZE / 2], iconSize: new Point(C.CAR_MARKER_SIZE, C.CAR_MARKER_SIZE), }) }, [], ) // Edgeの数を判定する const numOfEdge = datasets.length const numOfActiveEdge = useMemo( () => datasets.filter(({ lat, lng }) => utils.isFiniteLatLng(lat, lng)).length, [datasets], ) // Action ボタンを押したらDriverに指示を送ろう!! // eslint-disable-next-line no-alert const doAction = useCallback(() => alert(C.DO_ACTION_MESSAGE), []) return ( <S.Section marginTop={C.LAYOUT_HEADER_HEIGHT}> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA=='crossorigin='" /> <S.EdgesPanelArea> <Scrollbar> <S.EdgesPanelBg> <S.EdgesPanelHeaderArea> <EdgesPanelTitle numOfActiveEdge={numOfActiveEdge} numOfTotalEdge={numOfEdge} /> </S.EdgesPanelHeaderArea> <S.EdgeCardsArea> {useMemo(() => { return datasets.map((dataset, idx) => ( <EdgeCard key={idx} selected={selectedEdgeUUID === dataset.edgeUUID} name={utils.formatEdgeName(dataset.edgeName, C.NO_NAME)} soc={utils.formatSocString(dataset.soc, C.INVALID_STRING)} socRatio={utils.formatSocRatio( dataset.soc, C.SOC_RATIO_DEFAULT, )} speed={utils.formatSppedString( dataset.speed, C.INVALID_STRING, )} driver={C.DRIVER_NAME} onCardClick={makeOnSelectEdgeUUID(dataset.edgeUUID)} onActionClick={doAction} /> )) }, [datasets, doAction, makeOnSelectEdgeUUID, selectedEdgeUUID])} </S.EdgeCardsArea> </S.EdgesPanelBg> </Scrollbar> </S.EdgesPanelArea> <S.MapArea> <Map key={mapKey} center={centerCoord} zoom={zoom} zoomControl={C.OPEN_STREET_MAP_ZOOM_CONTROLS_DEFAULT} style={mapContainerStyle} > <TileLayer url={openStreetMap.url} attribution={openStreetMap.attribution} /> {useMemo(() => { return datasets.map((dataset, idx) => ( <React.Fragment key={idx}> {utils.isFiniteLatLng(dataset.lat, dataset.lng) && ( <Marker position={[dataset.lat, dataset.lng]} icon={makeCarMarkerIcon( selectedEdgeUUID === dataset.edgeUUID, dataset.heading, )} onClick={makeOnSelectEdgeUUID(dataset.edgeUUID)} /> )} </React.Fragment> )) }, [ datasets, makeCarMarkerIcon, makeOnSelectEdgeUUID, selectedEdgeUUID, ])} <S.MapZoomControllerArea> <MapZoomController onZoomInClick={onZoomIn} onZoomOutClick={onZoomOut} /> </S.MapZoomControllerArea> </Map> </S.MapArea> </S.Section> ) })
Container を実装する
Visual Parts SDK から取得したデータを FleetMap Component に連携する処理を実装します。
src/entrypoint/fleet-map/container.tsx
import React, { memo, useEffect, useState } from 'react' import { ExposerEvent, ViewBox, DataSpecification, Value, } from '@aptpod/data-viz-visual-parts-sdk' import { FleetMap } from './component' import { useSelectSize, useSelectOpenstreetMap, useSelectDatasets, } from './selector/props-selector' import { OPEN_STREET_MAP_URL_DEFAULT, OPEN_STREET_MAP_ATTRIBUTION_DEFAULT, } from './constant' import { parse as parseExtension, defaultExtension } from './extension' type Props = { comm: ExposerEvent } const VIEW_BOX_DEFAULT: ViewBox = { width: 100, height: 100 } const DATA_SPECS_DEFAULT: DataSpecification[] = [] const VALUES_DEFAULT: Value[] = [] /** * data-viz-visual-parts-sdk から取得したデータを FleetMap Component に必要なPropsに連携します。 */ export const FleetMapContainer: React.FC<Props> = memo((props) => { const [viewBox, setViewBox] = useState(VIEW_BOX_DEFAULT) const [extension, setExtension] = useState(defaultExtension) const [dataSpecifications, setDataSpecifications] = useState(DATA_SPECS_DEFAULT) const [values, setValues] = useState(VALUES_DEFAULT) useEffect(() => { // ビジュアルパーツの表示サイズを取得します。 props.comm.viewBox.on(setViewBox) // ビジュアルパーツの設定情報を取得します。 props.comm.extension.on((anyExtension: any) => { setExtension(parseExtension(anyExtension)) }) // Data Visualizer にバインドしているデータの定義リストを取得します。 props.comm.dataSpecifications.on(setDataSpecifications) // Data Visualizer にバインドしているデータに紐づく計測データを取得します。 props.comm.values.on(setValues) // Data Visualizer に、ビジュアルパーツのイベント取得初期設定が完了したことを通知します。 props.comm.loaded.emit() }, [props.comm]) // Fleet Map Component に指定する Props に変換します。 const size = useSelectSize({ viewBox }) const openSteetMap = useSelectOpenstreetMap({ dataset: { url: extension.openStreetMapURL, attribution: extension.openStreetMapAttribution, }, default: { url: OPEN_STREET_MAP_URL_DEFAULT, attribution: OPEN_STREET_MAP_ATTRIBUTION_DEFAULT, }, }) const datasets = useSelectDatasets({ dataSpecifications, values }) // View を表示します。 return ( <FleetMap size={size} openStreetMap={openSteetMap} datasets={datasets} /> ) })
src/entrypoint/fleetmap/props-selector.tsx
import { ComponentProps, useMemo } from 'react' import { ViewBox, DataSpecification, Value, } from '@aptpod/data-viz-visual-parts-sdk' import { FleetMap } from '../component' type FleetMapProps = ComponentProps<typeof FleetMap> /** * FleetMap Component Size Props に変換します。 */ export const useSelectSize = (params: { viewBox: ViewBox }): FleetMapProps['size'] => { const { width, height } = params.viewBox const size = useMemo(() => { return { width, height } }, [width, height]) return size } /** * FleetMap Component の OpenStreetMap Props に変換します。 */ export const useSelectOpenstreetMap = (params: { dataset: { url: string attribution: string } default: { url: string attribution: string } }): FleetMapProps['openStreetMap'] => { const p = params const trimedURL = p.dataset.url.trim() const trimedAttribution = p.dataset.attribution.trim() const url = trimedURL !== '' ? trimedURL : p.default.url const attribution = trimedAttribution !== '' ? trimedAttribution : p.default.attribution const openStreetMap = useMemo(() => { return { url, attribution, } }, [url, attribution]) return openStreetMap } /** * FleetMap Component の Datasets Props に変換します。 */ export const useSelectDatasets = (params: { dataSpecifications: DataSpecification[] values: Value[] }): FleetMapProps['datasets'] => { const { dataSpecifications, values } = params const edgeMap: Map< string, { edgeUUID: string edgeName: string values: number[] } > = new Map() for (const [i, { edgeUUID, edgeName }] of dataSpecifications.entries()) { const has = edgeMap.has(edgeUUID) if (!has) { edgeMap.set(edgeUUID, { edgeUUID, edgeName, values: [], }) } const value = values[i] if (!value) { continue } const numValue = Number((value.data[value.baseIdx] ?? { v: NaN }).v) const edge = edgeMap.get(edgeUUID) edge?.values.push(numValue) } const datasets = [...edgeMap.values()].map((edge) => { return { edgeUUID: edge.edgeUUID, edgeName: edge.edgeName, lat: edge.values[0] ?? NaN, lng: edge.values[1] ?? NaN, heading: edge.values[2] ?? NaN, soc: edge.values[3] ?? NaN, speed: edge.values[4] ?? NaN, } }) return datasets }
ビジュアルパーツの設定情報を定義する
OpenStreetMap の URL、Attribution を定義します。
src/entrypoint/fleet-map/extension.ts
で定義した EXTENSION_CONFIGS
は
実装次第では、 Panel Settings の Panel Option からビジュアルパーツの設定を変更することも可能です。
今回は例として、 OpenStreetMap の表示スタイルを変更する設定を実装してみました。
src/entrypoint/fleet-map/extension.ts
import * as Z from 'zod' import { Metadata } from '@aptpod/data-viz-visual-parts-sdk' import { estimate, estimatePartialObject } from 'src/utils/zod' /** * Extension の型を定義 */ export type Extension = { openStreetMapURL: string openStreetMapAttribution: string } /** * Extension のDefault値を設定します。 */ export const defaultExtension: Extension = { openStreetMapURL: '', openStreetMapAttribution: '', } /** * Extension のスキーマ定義します。 */ export const schema = { openStreetMapURL: Z.string(), openSteetMapAttribution: Z.string(), } /** * Extension の各フィールドをチェックします。 */ export const parse = (anyExtension: any): Extension => { const def = defaultExtension const ext = estimatePartialObject<Extension>(anyExtension) // eslint-disable-next-line prettier/prettier const openStreetMapURL = estimate(schema.openStreetMapURL, ext.openStreetMapURL, def.openStreetMapURL) // eslint-disable-next-line prettier/prettier const openStreetMapAttribution = estimate(schema.openStreetMapURL, ext.openStreetMapAttribution, def.openStreetMapAttribution) return { openStreetMapURL, openStreetMapAttribution, } } /** * Data VisualizerのPanel Optionに表示する入力項目を定義します。 */ export const EXTENSION_CONFIGS: Metadata['panelOptionConfig']['extensionConfigs'] = [ { id: 'InputText', key: 'openStreetMapURL', label: 'OpenStreetMap URL', option: { placeholder: 'URL' }, }, { id: 'InputText', key: 'openStreetMapAttribution', label: 'OpenStreetMap Attribution', option: { placeholder: 'HTML Source Code' }, }, ]
サムネイル画像の準備をする
こちらの手順に沿ってビジュアルパーツにはSVGまたはpng形式のサムネイルを準備します。
フリートマップのサムネイルは、png形式のため Retina 対応の画像も考慮して 幅150x横100 の3倍のpng形式のファイルを使用しました。
index.tsx を作成します。
Data Visualizer がフリートマップを表示するための処理を実装します。
src/entrypoint/fleet-map/index.tsx
import { expose, Renderer, Metadata, ExposerEvent, } from '@aptpod/data-viz-visual-parts-sdk' import React from 'react' import { render, unmountComponentAtNode } from 'react-dom' // Shadow DOM に適用するStyle import { StyledShadowStyle } from '../../styles/shadow' // Styled Components を Shadow DOM 以下で適用するための Utility import { StyleSheetManagerWrapper } from '../../utils/components/style/stylesheet-manager-wrapper' import { FleetMapContainer } from './container' import { EXTENSION_CONFIGS, defaultExtension } from './extension' import thumbnailSrc from 'src/assets/images/fleet-map/th-fleet-map@3x.png' /** * Metadata 作成 */ const metadata: Metadata = { partsType: '@demo/fleet-map', partsName: 'Fleet Map', groupName: 'Demo', panelTagName: 'x-demo-fleet-map', getThumbnailURL: (baseURL: string) => `${baseURL}${thumbnailSrc}`, panelViewConfig: { displayTimestamp: true, }, panelOptionConfig: { rangeAtMost: 0, canEditColor: false, bindDataCountMax: 250, extensionConfigs: EXTENSION_CONFIGS, }, defaultExtension, } /** * Renderer クラスを継承したPluginRendererを定義します。 */ class PluginRenderer extends Renderer { /** * 描画を実行します。 1回だけコールします。 * 状態を変更する場合は、 ExposerEvent のイベントを利用し、 element のDOMを再描画します。 */ // eslint-disable-next-line class-methods-use-this render(el: HTMLElement, comm: ExposerEvent) { // Reactを使用した描画 render( <StyleSheetManagerWrapper> <> <StyledShadowStyle /> <FleetMapContainer comm={comm} /> </> </StyleSheetManagerWrapper>, el, ) } /** * element に紐づく子要素のDOMや子要素のイベントハンドラを解放します。 * HTMLElement は、 render メソッドに引数として渡された HTMLElement (コンテナ)と同じです。 */ // eslint-disable-next-line class-methods-use-this dispose(el: HTMLElement) { unmountComponentAtNode(el) } } /** * 作成した metadata, renderer を公開します。 */ expose({ metadata, renderer: PluginRenderer, })
フリートマップ の src/entrypoint/fleet-map/index.ts
を src/entrypoint/index.ts
に追加します。
src/entrypoint/index.ts
import './fleet-map'
サンプルパーツを削除する
付属のサンプルパーツは不要のため削除します。
- src/entrypoint/index.ts から、
import './sample/...'
の行を削除 - 付属サンプルのディレクトリを削除
- src/assets/images/samples
- src/entrypoint/samples
npm uninstall chart.js react-chartjs-2 d3 @types/chart.js @types/d3 binary-search-bound
を実行して、サンプルビジュアルパーツが使用していたパッケージをアンインストール
Data Visualizer で表示を確認する
ビジュアルパーツをローカル開発サーバーでホストする
実装したビジュアルパーツをホストするローカル開発サーバーを起動します。
ビジュアルパーツをローカル開発サーバーでホストすることで、ビジュアルパーツの動作確認、または調整など効率的に開発を進めることができます。
$ npm run start ... -------------------------------- Set the Plugin URL under development to Visual M2M Data Visualizer. Please set the following URL in Local Plugin URL Settings of Function Menu. - http://localhost:8080/app.js --------------------------------
ローカル開発サーバーのURLを入力する
ローカル開発サーバー起動時に表示されたURL (http://localhost:8080/app.js
) を Data Visualizer の Visual Parts Plugin Settings Plg
の設定画面で保存します。
Plg
のメニューを表示するためには、ビジュアルパーツの作成ガイド「Visual Parts SDKによるData Visualizer用ビジュアルパーツの作成」 を参照してください。
ビジュアルパーツを選択する
Data Visualizer で開発した Fleet Map のビジュアルパーツの選択が可能になっていることを確認します。 今回作成したパーツは Demo
グループに表示されます。( index.tsx の groupName
で変更することができます)
デモ用計測データの定義を準備する
デモ用の計測データを表示するための定義ファイル を Data Settings にインポートします。(Data Visualizer の使用方法については、マニュアルをご覧ください)
データをバインドする
作成した Fleet Map の ビジュアルパーツにデータを一つずつ追加します。
計測データを確認する
最後にデモの計測を開始し、Data Visualizer を LIVE再生すると表示ができました。
まとめ
Visual Parts SDK を使用することで、ユーザー様ご自身で Data Visualizer をカスタマイズできることを実感いただけましたでしょうか?少しでも実際に近い開発や運用のイメージを掴んで頂くため、今回はフリートマップをサンプルとして選んでみました。
読者の皆様に本製品を活用いただくことで、DX表現のパートナーとしてお手伝いできることを楽しみにしております。 また、Data Visualizer ビジュアルパーツをカスタマイズ開発するための一助になれば幸いです。
以上です。ありがとうございました!