Как на JS реализовать интерактивный график изменения цены (Stock Chart) без использования тяжелых библиотек?

Реализовать интерактивный Stock Chart на чистом JavaScript вполне реально без подключения тяжёлых библиотек вроде Highcharts или Chart.js. Для этого используются встроенные браузерные API — Canvas 2D или SVG.

## Подход 1: Canvas 2D API

Canvas — наиболее производительный вариант для динамических графиков с большим количеством точек.

html

javascript
const canvas = document.getElementById(‘chart’);
const ctx = canvas.getContext(‘2d’);

const data = [120, 132, 125, 148, 139, 160, 155, 170, 165, 180];

function drawChart(data) {
const W = canvas.width, H = canvas.height;
const padding = 40;
const max = Math.max(…data);
const min = Math.min(…data);
const xStep = (W — padding * 2) / (data.length — 1);
const yScale = (H — padding * 2) / (max — min);

ctx.clearRect(0, 0, W, H);

// Сетка
ctx.strokeStyle = ‘#e0e0e0’;
for (let i = 0; i {
const x = padding + i * xStep;
const y = H — padding — (val — min) * yScale;
i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
});
ctx.stroke();

// Заливка под графиком
ctx.lineTo(padding + (data.length — 1) * xStep, H — padding);
ctx.lineTo(padding, H — padding);
ctx.closePath();
ctx.fillStyle = ‘rgba(33, 150, 243, 0.1)’;
ctx.fill();
}

drawChart(data);

## Интерактивность: тултип при наведении

javascript
canvas.addEventListener(‘mousemove’, (e) => {
const rect = canvas.getBoundingClientRect();
const mouseX = e.clientX — rect.left;
const padding = 40;
const xStep = (canvas.width — padding * 2) / (data.length — 1);
const index = Math.round((mouseX — padding) / xStep);

if (index >= 0 && index < data.length) {
drawChart(data);
const x = padding + index * xStep;
const max = Math.max(…data), min = Math.min(…data);
const yScale = (canvas.height — padding * 2) / (max — min);
const y = canvas.height — padding — (data[index] — min) * yScale;

// Вертикальная линия
ctx.beginPath();
ctx.strokeStyle = '#FF5722';
ctx.setLineDash([4, 4]);
ctx.moveTo(x, padding);
ctx.lineTo(x, canvas.height — padding);
ctx.stroke();
ctx.setLineDash([]);

// Точка
ctx.beginPath();
ctx.arc(x, y, 5, 0, Math.PI * 2);
ctx.fillStyle = '#FF5722';
ctx.fill();

// Тултип
ctx.fillStyle = '#333';
ctx.font = '14px Arial';
ctx.fillText(`Цена: ${data[index]}`, x + 10, y — 10);
}
});

## Подход 2: SVG

SVG удобен, если нужна доступность и простая интеграция с DOM. Генерируйте элемент « динамически через `document.createElementNS`. Каждая точка может иметь обработчик `mouseenter` для тултипа.

## Дополнительные улучшения

— **Масштабирование (zoom)**: обрабатывайте события `wheel` и перерисовывайте видимый диапазон данных.
— **Перетаскивание (pan)**: отслеживайте `mousedown`, `mousemove`, `mouseup` для сдвига диапазона.
— **Анимация**: используйте `requestAnimationFrame` для плавного появления линии.
— **Адаптивность**: слушайте `resize` и пересчитывайте размеры canvas через `canvas.width = container.offsetWidth`.

Такой подход даёт полный контроль над рендерингом, минимальный размер бандла и высокую производительность даже при тысячах точек данных.


Задайте вопрос нейросети

Не нашли ответ? Спросите ИИ — он подготовит развёрнутую статью.