Elixir Phoenix.LiveView + Chart.js를 사용한 실시간 차트 작성
목표
LiveView 상태 없음
LiveView은 타이머와 가짜 데이터
LiveView은
phx-hook
를 통해 데이터를 차트로 보냅니다.前提
erlang 24.1.7
elixir 1.13.0-otp-24
phoenix 1.6.2
phoenix_live_view 0.17.1
https://nagix.github.io/chartjs-plugin-streaming/2.0.0/guide/getting-started.html#integration
依存関係をinstorl
npm install --save --prefix assets \
chart.js luxon chartjs-adapter-luxon chartjs-plugin-streaming
// package.json
{
"dependencies": {
"chart.js": "^3.6.1",
"chartjs-adapter-luxon": "^1.1.0",
"chartjs-plugin-streaming": "^2.0.0",
"luxon": "^2.1.1",
}
}
그라후を操作する JavaScript を定義
assets/js/line_chart.js
Chart.js의
Chart
노랍파// assets/js/line_chart.js
// https://www.chartjs.org/docs/3.6.1/getting-started/integration.html#bundlers-webpack-rollup-etc
import Chart from 'chart.js/auto'
import 'chartjs-adapter-luxon'
import ChartStreaming from 'chartjs-plugin-streaming'
Chart.register(ChartStreaming)
// A wrapper of Chart.js that configures the realtime line chart.
export default class {
constructor(ctx) {
this.colors = [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
]
const config = {
type: 'line',
data: { datasets: [] },
options: {
datasets: {
// https://www.chartjs.org/docs/3.6.0/charts/line.html#dataset-properties
line: {
// 線グラフに丸みを帯びさせる。
tension: 0.3
}
},
plugins: {
// https://nagix.github.io/chartjs-plugin-streaming/2.0.0/guide/options.html
streaming: {
// 表示するX軸の幅をミリ秒で指定。
duration: 60 * 1000,
// Chart.jsに点をプロットする猶予を与える。
delay: 1500
}
},
scales: {
x: {
// chartjs-plugin-streamingプラグインの機能をつかうための型。
type: 'realtime'
},
y: {
// あらかじめY軸の範囲をChart.jsに教えてあげると、グラフの更新がスムーズです。
suggestedMin: 50,
suggestedMax: 200
}
}
}
}
this.chart = new Chart(ctx, config)
}
addPoint(label, value) {
const dataset = this._findDataset(label) || this._createDataset(label)
dataset.data.push({x: Date.now(), y: value})
this.chart.update()
}
destroy() {
this.chart.destroy()
}
_findDataset(label) {
return this.chart.data.datasets.find((dataset) => dataset.label === label)
}
_createDataset(label) {
const newDataset = {label, data: [], borderColor: colors.pop()}
this.chart.data.datasets.push(newDataset)
return newDataset
}
}
LiveView 와 JavaScript 와 の間で通信するための福を定義
LiveView がマウントされたときに実行する処理を書きます.
// assets/js/live_view_hooks/line_chart_hook.js
// 前項で定義したJSファイルをインポートする。
import RealtimeLineChart from '../line_chart'
export default {
mounted() {
// グラフを初期化する。
this.chart = new RealtimeLineChart(this.el)
// LiveViewから'new-point'イベントを受信時、座標を追加する。
this.handleEvent('new-point', ({ label, value }) => {
this.chart.addPoint(label, value)
})
},
destroyed() {
// 使用後はちゃんと破壊する。
this.chart.destroy()
}
}
個人的に
index.js
ファイルで整理するスタイルが気に入ってます.// assets/js/live_view_hooks/index.js
import LineChart from './line_chart_hook'
export default {
LineChart
}
assets/js/app.js
파이르로 LiveSocket
に福クを登録します.// assets/js/app.js
import 'phoenix_html'
import { Socket } from 'phoenix'
import { LiveSocket } from 'phoenix_live_view'
import topbar from '../vendor/topbar'
import LiveViewHooks from './live_view_hooks'
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute('content')
let liveSocket = new LiveSocket('/live', Socket, {
hooks: LiveViewHooks,
params: {
_csrf_token: csrfToken
}
})
// ...
그라후を表示する LiveView を定義
# lib/mnishiguchi_web/live/chart_live.ex
defmodule MnishiguchiWeb.ChartLive do
use MnishiguchiWeb, :live_view
@impl Phoenix.LiveView
def mount(_params, _session, socket) do
if connected?(socket) do
# 本来はPubSubでデータを受信するところだが、今回そこはタイマーで再現する。
:timer.send_interval(1000, self(), :update_chart)
end
{:ok, socket}
end
@impl Phoenix.LiveView
def render(assigns) do
~H"""
<div>
<!--
フックをセットする。
本LiveViewにおいてグラフ更新はJavascriptの責任範囲なので、あらかじめ`phx-update="ignore"`により
LiveViewにグラフ更新されないようにしておく。
-->
<canvas
id="chart-canvas"
phx-update="ignore"
phx-hook="LineChart"></canvas>
</div>
"""
end
@impl Phoenix.LiveView
def handle_info(:update_chart, socket) do
# ダミーデータを生成し、"new-point"イベントを発信する。
{:noreply,
Enum.reduce(1..5, socket, fn i, acc ->
push_event(
acc,
"new-point",
%{label: "User #{i}", value: Enum.random(50..150) + i * 10}
)
end)}
end
end
LiveView의 루트를 취소할 수 있습니다.
# lib/mnishiguchi_web/router.ex
defmodule MnishiguchiWeb.Router do
use MnishiguchiWeb, :router
# ...
scope "/", MnishiguchiWeb do
pipe_through :browser
# ...
live "/chart", ChartLive
end
# ...
比較的少ないコード記述量でリアルタイムグラフうねうねの実装ができました.
🎉🎉🎉
자원
Reference
이 문제에 관하여(Elixir Phoenix.LiveView + Chart.js를 사용한 실시간 차트 작성), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/mnishiguchi/real-time-charting-with-elixir-phoenixliveview-chartjs-b4c텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)