🎉

Svelte、Plotlyでグラフ4つ➕1つのグラフを作成してみた

2025/01/19に公開

Svelte、Plotlyでグラフ4つ➕1つのグラフを作成してみました。
その備忘録です。

<script>
  import { onMount } from 'svelte';
  import Plotly from 'plotly.js-dist';

  // グラフデータとレイアウト
  const graphs = [
    {
      id: 'graph1',
      data: [
        {
          x: [1, 2, 3, 4],
          y: [10, 15, 13, 17],
          type: 'scatter',
          mode: 'lines+markers',
          marker: { color: 'red' }
        }
      ],
      layout: { title: 'Graph 1' }
    },
    {
      id: 'graph2',
      data: [
        {
          x: [1, 2, 3, 4],
          y: [10, 20, 15, 25],
          type: 'bar'
        }
      ],
      layout: { title: 'Graph 2' }
    },
    {
      id: 'graph3',
      data: [
        {
          labels: ['A', 'B', 'C'],
          values: [30, 20, 50],
          type: 'pie'
        }
      ],
      layout: { title: 'Graph 3' }
    },
    {
      id: 'graph4',
      data: [
        {
          z: [[1, 20, 30], [20, 1, 60], [30, 60, 1]],
          type: 'heatmap'
        }
      ],
      layout: { title: 'Graph 4' }
    }
  ];

  // 追加の動的グラフ
  const dynamicGraphId = 'dynamicGraph';
  let dynamicData = [
    {
      x: [1, 2, 3, 4],
      y: [10, 20, 30, 40],
      type: 'scatter',
      mode: 'lines',
      marker: { color: 'blue' }
    }
  ];
  let dynamicLayout = { title: 'Dynamic Graph' };
  let inputValue = 0;

  // グラフの初期化
  onMount(() => {
    graphs.forEach(({ id, data, layout }) => {
      Plotly.newPlot(id, data, layout);
    });
    Plotly.newPlot(dynamicGraphId, dynamicData, dynamicLayout);
  });

  // ボタンのクリックでグラフを更新
  function updateGraph() {
    const newY = dynamicData[0].y.map(y => y + parseFloat(inputValue));
    dynamicData[0].y = newY;
    Plotly.react(dynamicGraphId, dynamicData, dynamicLayout);
  }
</script>

<style>
  .container {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr 1fr;
    gap: 20px;
  }
  .graph {
    width: 100%;
    height: 100%;
    min-height: 300px;
  }
  .dynamic-container {
    display: flex;
    align-items: center;
    margin-top: 20px;
  }
  .dynamic-graph {
    flex: 3;
    min-height: 300px;
  }
  .control-panel {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-left: 20px;
  }
  input[type="number"] {
    padding: 5px;
    font-size: 1rem;
  }
  button {
    padding: 10px;
    font-size: 1rem;
    background-color: #007bff;
    color: white;
    border: none;
    cursor: pointer;
  }
  button:hover {
    background-color: #0056b3;
  }
</style>

<div class="container">
  {#each graphs as graph}
    <div id={graph.id} class="graph"></div>
  {/each}
</div>

<div class="dynamic-container">
  <div id={dynamicGraphId} class="dynamic-graph"></div>
  <div class="control-panel">
    <label for="inputValue">数値を入力:</label>
    <input
      type="number"
      id="inputValue"
      bind:value={inputValue}
      placeholder="数値を入力してください"
    />
    <button on:click={updateGraph}>グラフを更新</button>
  </div>
</div>

Discussion