Создание простейшего графика

В данном статье используется сборщик Vite.

Создание проекта

$ npm create vite@latest my-app --template vanilla my-app
$ cd my-app

$ npm install
$ npm run dev
$ npm create vite@latest my-app --template react my-app
$ cd my-app

$ npm install
$ npm run dev
$ npm create vite@latest my-app --template vue my-app
$ cd my-app

$ npm install
$ npm run dev

Установка библиотеки

Для установки библиотеки необходимо выполнить шаги из пункта УСТАНОВКА.

Offline-график

Конфигурация графика

Для настройки отображения графика необходимо создать файл конфигурации.

Примечание

Подробнее о файле конфигурации в разделе Файл конфигурации

В директории с исходным кодом проекта необходимо создать файл VisualSettings.json. Далее, необходимо скопировать конфигурацию графика в файл VisualSettings.json.

Инициализация графика

В директории с исходным кодом проекта необходимо создать main.js и импортировать необходимые элементы.

import { JagmRootProvider } from "@incartdev/jagm-core";
import { JagmRawLineSignalData, JagmRawSignalsChartProvider } from "@incartdev/jagm-chart";
import { RawOfflineVisualizatorConfigJsUnpacker } from "@incartdev/jagm-visualizator";

import VisualConfig from "./VisualConfig.json";

Для инициализации графика и генератора сигнала в файле main.js создается функция init.

export const init = async () => {
  // Получение ссылок на DOM элементы контейнера
  const canvasRef = document.querySelector(".canvas-wrap");

  // Создать экземпляр класса для рисования графиков
  const visProvider = new JagmRootProvider(new RawOfflineVisualizatorConfigJsUnpacker());

  // Создание тестовых данных для отображения на графическом полотне
  // Происходит генерация графика синуса с частотой 500Гц и амплитудоай 1000
  const plotData = Array.from({ length: 5000 }, (_, index) => Math.sin((index * Math.PI) / 250) * 1000);
  const signalData = new JagmRawLineSignalData(plotData);

  // Инициализация создания графических элементов
  await visProvider.create({
    settings: VisualConfig,
    rootHtml: canvasRef
  });

  // Создание контроллера графических элементов библиотеки
  const chartProvider = new JagmRawSignalsChartProvider(visProvider.builder);
  
  // Добавление сгенерированных данных на графическое полотно
  chartProvider.signalObjectGroups.forEach(async (signalGroup) => {
    await signalGroup.addSignalData(0, 0, 0, signalData);
  });

  // Обновление графика
  visProvider.refreshGraphics();
};

В файл index.html необходимо добавить следущие элементы.

Важно

Важно отметить, что контейнер НЕ должен быть нулевой высоты. В противном случае, график не будет отображен, из-за отсутствия места.

<div class="vis-wrap" id="wrapRef">
    <div class="canvas-wrap" id="canvasWrap"/>
</div>

<script type="module">
  import { init } from './main.js'
  document.addEventListener("DOMContentLoaded", () => {
    init();
  });
</script>

<style>
  .canvas-wrap {
  height: 100%;
  width: 100%;
  position: absolute;
  }
  .vis-wrap {
    position: relative;
    height: 500px;
    width: 500px;
  }
</style>

Важно

Важно отметить, что у script должен быть прописан type=module

В директории src необходимо создать поддиректорию graph. Внутри graph необходимо создать файл graph.jsx.
В graph.jsx требуется импортировать необходимые элементы.

import React, { useRef, useEffect } from "react";
import { JagmRootProvider } from "@incartdev/jagm-core";
import { JagmRawLineSignalData, JagmRawSignalsChartProvider } from "@incartdev/jagm-chart";
import { RawOfflineVisualizatorConfigJsUnpacker } from "@incartdev/jagm-visualizator";

import VisualConfig from "./VisualConfig.json";

В файл graph.jsx необходимо создать элемент Graph.

// Стилизация графика
const canvasWrapStyle = {
  height: "400px",
  width: "400px",
  position: "relative"
};

export const Graph = () => {
  const canvasRef = useRef(null);
  useEffect(() => {
    const init = () => {
      // Создать экземпляр класса для рисования графиков
      const visProvider = new JagmRootProvider(new RawOfflineVisualizatorConfigJsUnpacker());

      // Создание тестовых данных для отображения на графическом полотне
      // Происходит генерация графика синуса с частотой 500Гц и амплитудоай 1000
      const plotData = Array.from({ length: 5000 }, (_, index) => Math.sin((index * Math.PI) / 250) * 1000);
      const signalData = new JagmRawLineSignalData(plotData);

      // Инициализация создания графических элементов
      await visProvider.create({
        settings: VisualConfig,
        rootHtml: canvasRef.current
      });

      // Создание контроллера графических элементов библиотеки
      const chartProvider = new JagmRawSignalsChartProvider(visProvider.builder);

      // Добавление сгенерированных данных на графическое полотно
      chartProvider.signalObjectGroups.forEach(async (signalGroup) => {
        await signalGroup.addSignalData(0, 0, 0, signalData);
      });

      // Обновление графика
      visProvider.refreshGraphics();
    };

    install();
  }, []);

  return (
    <div className="canvas-wrap" style={canvasWrapStyle} ref={canvasRef} />
  );
};

Созданный элемент необходимо импортировать в graph.jsx и добавить в рендер.

import React from 'react'
import ReactDOM from 'react-dom/client'
import { Graph } from './src/graph/graph.jsx'

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <Graph />
  </React.StrictMode>,
);

В директории src необходимо создать поддиректорию graph. Внутри graph необходимо создать файл graph.vue.

<template>
  <div class="canvasWrap" ref="canvasWrap"></div>
</template>

<script setup>
  import { onMounted, ref, nextTick } from 'vue';
  import { JagmRootProvider } from "@incartdev/jagm-core";
  import { JagmRawLineSignalData, JagmRawSignalsChartProvider } from "@incartdev/jagm-chart";
  import { RawOfflineVisualizatorConfigJsUnpacker } from "@incartdev/jagm-visualizator";

  import VisualConfig from "./VisualConfig.json";

  const canvasWrap = ref(null);

  onMounted(() => {
    const init = async () => {
      await nextTick();
      // Создать экземпляр класса для рисования графиков
      const visProvider = new JagmRootProvider(new RawOfflineVisualizatorConfigJsUnpacker());

      // Создание тестовых данных для отображения на графическом полотне
      // Происходит генерация графика синуса с частотой 500Гц и амплитудоай 1000
      const plotData = Array.from({ length: 5000 }, (_, index) => Math.sin((index * Math.PI) / 250) * 1000);
      const signalData = new JagmRawLineSignalData(plotData);

      // Инициализация создания графических элементов
      await visProvider.create({
        settings: VisualConfig,
        rootHtml: canvasWrap.value
      });

      // Создание контроллера графических элементов библиотеки
      const chartProvider = new JagmRawSignalsChartProvider(visProvider.builder);

      // Добавление сгенерированных данных на графическое полотно
      chartProvider.signalObjectGroups.forEach(async (signalGroup) => {
        await signalGroup.addSignalData(0, 0, 0, signalData);
      });

      // Обновление графика
      visProvider.refreshGraphics();
    };

    init();
  });
</script>

<style scoped>
  .canvasWrap {
    height: 400px;
    width: 400px;
    position: relative;
  }
</style>

В файле main.js требуется произвести импорт созданного элемента графического полотна.

import { createApp } from 'vue';
import Graph from './graph/graph.vue';

createApp(Graph).mount('#app');

Online-график

Конфигурация графика

Для настройки отображения графика необходимо создать файл конфигурации.

Примечание

Подробнее о файле конфигурации в разделе Файл конфигурации

В директории с исходным кодом проекта необходимо создать файл VisualSettings.json. Далее, необходимо скопировать конфигурацию графика в файл VisualSettings.json.

Настройка генератора сигналов

Online-график — график, отображающий сигнал, изменяющийся в реальном времени. Для отображения будет использован демонстрационный сигнал, генерирующийся в реальном времени
с помощью генератора сигнала. Генератор сигнала также требуется сконфигурировать в отдельном файле конфигурации. В данном примере не рассматривается вариант создания конфигурации с нуля.

Для настройки генератора сигналов в директории с исходным кодом проекта необходимо создать файл generator.json. Далее, необходимо скопировать конфигурацию генератора сигналов в файл generator.josn.

Инициализация графика

В директории с исходным кодом проекта необходимо создать main.js и импортировать необходимые элементы.

import { JagmRootProvider } from "@incartdev/jagm-core";
import { JagmRawSignalsChartProvider, JagmRawVisScreenDataParser } from "@incartdev/jagm-chart";
import { RawOnlineVisualizatorConfigJsUnpacker } from "@incartdev/jagm-visualizator";
import { RawSignalGenerator, GeneratorSettingsParser } from "@incartdev/signal-generator-js-core";

import generatorConfig from "./generatorConfig.json";
import VisualConfig from "./VisualConfig.json";

Для инициализации графика и генератора сигнала в файле main.js создается функция init.

export const init = async () => {
  // Получение ссылок на DOM элементы контейнера
  const canvasWrap = document.querySelector(".canvas-wrap");

  // Создание экземпляров класса конструктора графического полотна и генератора сигналов
  const visProvider = new JagmRootProvider(new RawOnlineVisualizatorConfigJsUnpacker());

  const generator = new RawSignalGenerator();

  // Загрузка конфигурации генератора сигналов
  const generatorSettings = GeneratorSettingsParser.parse(generatorConfig);
  if (generatorSettings === undefined) {
    return;
  }

  // Инициализация генератора сигналов
  generator.init(generatorSettings);

  // Инициализация создания графических элементов
  await visProvider.create({
    settings: VisualConfig,
    rootHtml: canvasWrap
  });

  // Создание контроллера графических элементов библиотеки
  const chartProvider = new JagmRawSignalsChartProvider(visProvider.builder);

  // Установка калибровки для сигнала ЭКГ
  chartProvider.setCalibration(undefined, "ecg", [0], [1000], [0]);

  // Установка коллбэка, передающего занчения с генератора сигналов на графическое полотно
  generator.onFrameIsReady = async message =>{
    const typedMessage = JagmRawVisScreenDataParser.parse(message);
    if (typedMessage === undefined) {
      return;
    }
    await chartProvider.pushVisMessage(typedMessage);
  };

  // Запуск генератора сигнала
  generator.start();
};

В файл index.html необходимо добавить следущие элементы.

Важно

Важно отметить, что контейнер НЕ должен быть нулевой высоты. В противном случае, график не будет отображен, из-за отсутствия места

<div class="vis-wrap" id="wrapRef">
    <div class="canvas-wrap" id="canvasWrap"/>
</div>

<script type="module">
  import { init } from './main.js'
  document.addEventListener("DOMContentLoaded", () => {
    init();
  });
</script>

<style>
  .canvas-wrap {
  height: 100%;
  width: 100%;
  position: absolute;
  }
  .vis-wrap {
    position: relative;
    height: 500px;
    width: 500px;
  }
</style>

Важно

Важно отметить, что у script должен быть прописан type=module

В директории src необходимо создать поддиректорию graph. Внутри graph необходимо создать файл graph.jsx.
В graph.jsx требуется импортировать необходимые элементы.

import React, { useRef, useEffect } from "react";
import { JagmRootProvider } from "@incartdev/jagm-core";
import { JagmRawSignalsChartProvider, JagmRawVisScreenDataParser } from "@incartdev/jagm-chart";
import { RawOnlineVisualizatorConfigJsUnpacker } from "@incartdev/jagm-visualizator";
import { RawSignalGenerator, GeneratorSettingsParser } from "@incartdev/signal-generator-js-core";

import VisualConfig from "./VisualConfig.json";
import generatorConfig from "./generatorConfig.json";

В файл graph.jsx необходимо создать элемент Graph.

// Стилизация графика
const canvasWrapStyle = {
  height: "400px",
  width: "400px",
  position: "relative"
};

export const Graph = () => {
  const canvasWrap = useRef(null);

  useEffect(() => {
    const init = async () => {

      // Создание экземпляров класса конструктора графического полотна и генератора сигналов
      const visProvider = new JagmRootProvider(new RawOnlineVisualizatorConfigJsUnpacker());

      const generator = new RawSignalGenerator();

      // Загрузка конфигурации генератора сигналов
      const generatorSettings = GeneratorSettingsParser.parse(generatorConfig);
      if (generatorSettings === undefined) {
        return;
      }

      // Инициализация генератора сигналов
      generator.init(generatorSettings);

      // Инициализация создания графических элементов
      await visProvider.create({
        settings: VisualConfig,
        rootHtml: canvasWrap
      });

      // Создание контроллера графических элементов библиотеки
      const chartProvider = new JagmRawSignalsChartProvider(visProvider.builder);

      // Установка калибровки для сигнала ЭКГ
      chartProvider.setCalibration(undefined, "ecg", [0], [1000], [0]);

      // Установка коллбэка, передающего занчения с генератора сигналов на графическое полотно
      generator.onFrameIsReady = async message =>{
        const typedMessage = JagmRawVisScreenDataParser.parse(message);
        if (typedMessage === undefined) {
          return;
        }
        await chartProvider.pushVisMessage(typedMessage);
      };

      // Запуск генератора сигнала
      generator.start();
    };

    init();
  }, []);

  return (
    <div className="canvas-wrap" ref={canvasWrap} style={canvasWrapStyle} />
  );
};

Созданный элемент необходимо импортировать в main.jsx и добавить в рендер.

import React from 'react'
import ReactDOM from 'react-dom/client'
import { Graph } from './src/graph/graph.jsx'

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <Graph />
  </React.StrictMode>,
);

В директории src необходимо создать поддиректорию graph. Внутри graph необходимо создать файл graph.vue.

<template>
  <div class="canvas-wrap" ref="canvasWrap"></div>
</template>

<script setup>
  import { ref, onMounted } from "vue";
  import { JagmRootProvider } from "@incartdev/jagm-core";
  import { JagmRawSignalsChartProvider, JagmRawVisScreenDataParser } from "@incartdev/jagm-chart";
  import { RawOnlineVisualizatorConfigJsUnpacker } from "@incartdev/jagm-visualizator";
  import { RawSignalGenerator, GeneratorSettingsParser } from "@incartdev/signal-generator-js-core";
  
  import VisualConfig from "./VisualConfig.json";
  import generatorConfig from "./generatorConfig.json";
  
  const canvasWrap = ref(null);

  onMounted(() => {
    const init = async () => {
      // Создание экземпляров класса конструктора графического полотна и генератора сигналов
      const visProvider = new JagmRootProvider(new RawOnlineVisualizatorConfigJsUnpacker());

      const generator = new RawSignalGenerator();

      // Загрузка конфигурации генератора сигналов
      const generatorSettings = GeneratorSettingsParser.parse(generatorConfig);
      if (generatorSettings === undefined) {
        return;
      }

      // Инициализация генератора сигналов
      generator.init(generatorSettings);

      // Инициализация создания графических элементов
      await visProvider.create({
        settings: VisualConfig,
        rootHtml: canvasWrap.value
      });

      // Создание контроллера графических элементов библиотеки
      const chartProvider = new JagmRawSignalsChartProvider(visProvider.builder);

      // Установка калибровки для сигнала ЭКГ
      chartProvider.setCalibration(undefined, "ecg", [0], [1000], [0]);

      // Установка коллбэка, передающего занчения с генератора сигналов на графическое полотно
      generator.onFrameIsReady = async message =>{
        const typedMessage = JagmRawVisScreenDataParser.parse(message);
        if (typedMessage === undefined) {
          return;
        }
        await chartProvider.pushVisMessage(typedMessage);
      };

      // Запуск генератора сигнала
      generator.start();
    };

    init();
  });
</script>

<style>
  .canvas-wrap {
    height: 400px;
    width: 400px;
    position: relative;
  }
</style>

В файле main.js требуется произвести импорт созданного элемента графического полотна.

import { createApp } from 'vue';
import Graph from './graph/graph.vue';

createApp(Graph).mount('#app');

Pauseable-график

Статья в разработке

Доступ к содержимому по ссылке возможен только для авторизованных пользователей GitHub, являющихся участниками организации IncartDev
Ссылка на ресурс

Доступ к содержимому по ссылке возможен только для авторизованных пользователей GitHub, являющихся участниками организации IncartDev
Ссылка на ресурс

Доступ к содержимому по ссылке возможен только для авторизованных пользователей GitHub, являющихся участниками организации IncartDev
Ссылка на ресурс

Предыдущая