Библиотека Paper.js предоставляет мощный векторный движок, который
позволяет строить интерактивные и динамические визуализации
непосредственно в браузере. В отличие от традиционных
DOM-ориентированных решений, здесь используется собственная сцена
(Project) и иерархия объектов (Item), что
делает работу с графикой более гибкой и производительной.
Ключевые элементы:
Path — основной примитив для построения линий и
фигурPoint — координатная единицаGroup — объединение элементовLayer — уровень сценыView — отображение и управление холстомВизуализация данных в Paper.js сводится к преобразованию числовых значений в геометрические формы.
Любая визуализация начинается с масштабирования данных. Например, массив значений:
const data = [10, 25, 40, 15, 30];
Необходимо перевести в координаты на холсте:
const max = Math.max(...data);
const width = view.size.width;
const height = view.size.height;
const stepX = width / data.length;
const points = data.map((value, index) => {
return new Point(
index * stepX,
height - (value / max) * height
);
});
Ключевой момент — инверсия оси Y, так как в Canvas начало координат находится в верхнем левом углу.
Линейный график — базовый тип визуализации. В Paper.js он реализуется
через Path:
const path = new Path({
strokeColor: 'blue',
strokeWidth: 2
});
points.forEach(point => path.add(point));
Для улучшения визуального восприятия используется сглаживание:
path.smooth({
type: 'catmull-rom',
factor: 0.5
});
Это особенно важно при работе с шумными данными.
Каждое значение представляется прямоугольником:
const barWidth = stepX * 0.6;
data.forEach((value, index) => {
const barHeight = (value / max) * height;
new Path.Rectangle({
point: [index * stepX, height - barHeight],
size: [barWidth, barHeight],
fillColor: 'green'
});
});
Для центрирования столбцов:
const offset = (stepX - barWidth) / 2;
Paper.js позволяет работать с дугами и секторами:
const total = data.reduce((a, b) => a + b, 0);
let startAngle = 0;
data.forEach(value => {
const angle = (value / total) * 360;
const from = new Point(200, 200);
const through = from.add(new Point({
length: 100,
angle: startAngle + angle / 2
}));
const to = from.add(new Point({
length: 100,
angle: startAngle + angle
}));
const path = new Path.Arc(from, through, to);
path.add(from);
path.closed = true;
path.fillColor = new Color(Math.random(), Math.random(), Math.random());
startAngle += angle;
});
Paper.js поддерживает встроенный цикл отрисовки через
onFrame:
view.onFr ame = function(event) {
path.segments.forEach((segment, index) => {
segment.point.y += Math.sin(event.time + index) * 0.5;
});
path.smooth();
};
Каждый элемент сцены может реагировать на события:
path.onMouseEn ter = function() {
this.strokeColor = 'red';
};
path.onMouseLe ave = function() {
this.strokeColor = 'blue';
};
bar.onCl ick = function() {
this.fillColor = 'orange';
};
Интерактивность позволяет превращать статические графики в аналитические инструменты.
Для сложных визуализаций:
const group = new Group();
data.forEach((value, index) => {
const circle = new Path.Circle({
center: [index * 50, value * 5],
radius: 5,
fillColor: 'black'
});
group.addChild(circle);
});
Текст создаётся через PointText:
new PointText({
point: [10, 20],
content: 'График данных',
fillColor: 'black',
fontSize: 14
});
new Path.Line({
from: [0, height],
to: [width, height],
strokeColor: 'black'
});
new Path.Line({
from: [0, 0],
to: [0, height],
strokeColor: 'black'
});
Paper.js автоматически адаптируется под размер холста:
view.onRes ize = function() {
project.clear();
drawChart();
};
Это позволяет создавать отзывчивые визуализации.
При работе с большими объёмами данных важно учитывать:
PathCompoundPath для объединенияПример объединения:
const compound = new CompoundPath({
children: paths,
fillColor: 'blue'
});
Paper.js поддерживает сложные цветовые модели:
path.fillColor = new Color({
gradient: {
stops: ['red', 'blue']
},
origin: [0, 0],
destination: [100, 0]
});
path.opacity = 0.5;
Обновление графика без полной перерисовки:
function updateData(newData) {
newData.forEach((value, index) => {
path.segments[index].point.y =
height - (value / max) * height;
});
path.smooth();
}
Можно объединять несколько типов графиков:
const line = new Path(points);
const dots = points.map(p => new Path.Circle(p, 3));
const group = new Group([line, ...dots]);
Для временных рядов:
const now = Date.now();
const data = timestamps.map(t => ({
x: (t - now) / 1000,
y: value
}));
Полезны для анимаций и масштабирования:
group.scale(1.2);
group.rotate(15);
group.translate([10, 0]);
Стратегии:
Типичная структура:
data → нормализация → координаты → объекты Paper.js → рендер → интерактивность
Разделение логики:
Данные могут поступать из:
fetch('/data')
.then(res => res.json())
.then(updateData);
Paper.js хорошо сочетается с:
Глубокая интеграция геометрии, анимации и интерактивности делает Paper.js эффективным инструментом для создания сложных визуализаций данных, где важны точность, гибкость и контроль над графикой на низком уровне.