added endless camera movement
This commit is contained in:
parent
90ac56df1e
commit
7322ba5ead
131
graph.js
131
graph.js
|
@ -97,7 +97,7 @@ class graph {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Реестр запрещённых к изменению параметров
|
// Реестр запрещённых к изменению параметров
|
||||||
#block = new Set(["events"]);
|
#block = new Set(['events']);
|
||||||
get block() {
|
get block() {
|
||||||
return this.#block;
|
return this.#block;
|
||||||
}
|
}
|
||||||
|
@ -158,11 +158,11 @@ class graph {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Инициализация HTML-элемента узла
|
// Инициализация HTML-элемента узла
|
||||||
const article = document.createElement("article");
|
const article = document.createElement('article');
|
||||||
article.id = this.#operator.id + '_node_' + this.#operator.nodes.size;
|
article.id = this.#operator.id + '_node_' + this.#operator.nodes.size;
|
||||||
if (typeof data.color === 'string') article.classList.add(data.color);
|
if (typeof data.color === 'string') article.classList.add(data.color);
|
||||||
article.classList.add(..._this.operator.classes.node.element);
|
article.classList.add(..._this.operator.classes.node.element);
|
||||||
if (typeof data.href === "string") {
|
if (typeof data.href === 'string') {
|
||||||
article.href = data.href;
|
article.href = data.href;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ class graph {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Инициализация заголовка
|
// Инициализация заголовка
|
||||||
const title = document.createElement("h4");
|
const title = document.createElement('h4');
|
||||||
title.classList.add(..._this.#operator.classes.node.title);
|
title.classList.add(..._this.#operator.classes.node.title);
|
||||||
title.innerText = data.title ?? '';
|
title.innerText = data.title ?? '';
|
||||||
|
|
||||||
|
@ -181,7 +181,7 @@ class graph {
|
||||||
article.appendChild(title);
|
article.appendChild(title);
|
||||||
|
|
||||||
// Инициализация описания
|
// Инициализация описания
|
||||||
const description = document.createElement("div");
|
const description = document.createElement('div');
|
||||||
description.classList.add(..._this.#operator.classes.node.description);
|
description.classList.add(..._this.#operator.classes.node.description);
|
||||||
if (typeof data.popup === 'string') description.title = data.popup;
|
if (typeof data.popup === 'string') description.title = data.popup;
|
||||||
|
|
||||||
|
@ -261,21 +261,21 @@ class graph {
|
||||||
article.appendChild(description);
|
article.appendChild(description);
|
||||||
|
|
||||||
// Инициализация левой фигуры для обёртки текста
|
// Инициализация левой фигуры для обёртки текста
|
||||||
const left = document.createElement("span");
|
const left = document.createElement('span');
|
||||||
left.classList.add(..._this.#operator.classes.node.wrappers.both, ..._this.#operator.classes.node.wrappers.left);
|
left.classList.add(..._this.#operator.classes.node.wrappers.both, ..._this.#operator.classes.node.wrappers.left);
|
||||||
|
|
||||||
// Запись в описание
|
// Запись в описание
|
||||||
description.appendChild(left);
|
description.appendChild(left);
|
||||||
|
|
||||||
// Инициализация правой фигуры для обёртки текста
|
// Инициализация правой фигуры для обёртки текста
|
||||||
const right = document.createElement("span");
|
const right = document.createElement('span');
|
||||||
right.classList.add(..._this.#operator.classes.node.wrappers.both, ..._this.#operator.classes.node.wrappers.right);
|
right.classList.add(..._this.#operator.classes.node.wrappers.both, ..._this.#operator.classes.node.wrappers.right);
|
||||||
|
|
||||||
// Запись в описание
|
// Запись в описание
|
||||||
description.appendChild(right);
|
description.appendChild(right);
|
||||||
|
|
||||||
// Инициализация ссылки на источник
|
// Инициализация ссылки на источник
|
||||||
const a = document.createElement("a");
|
const a = document.createElement('a');
|
||||||
if (typeof data.link === 'object' && typeof data.link.name === 'string') a.innerText = data.link.name;
|
if (typeof data.link === 'object' && typeof data.link.name === 'string') a.innerText = data.link.name;
|
||||||
if (typeof data.link === 'object' && typeof data.link.href === 'string') a.href = data.link.href;
|
if (typeof data.link === 'object' && typeof data.link.href === 'string') a.href = data.link.href;
|
||||||
if (typeof data.link === 'object' && typeof data.link.class === 'object') a.classList.add(...data.link.class);
|
if (typeof data.link === 'object' && typeof data.link.class === 'object') a.classList.add(...data.link.class);
|
||||||
|
@ -348,19 +348,19 @@ class graph {
|
||||||
description.appendChild(a);
|
description.appendChild(a);
|
||||||
|
|
||||||
// Запись текста в описание
|
// Запись текста в описание
|
||||||
const text = document.createElement("p");
|
const text = document.createElement('p');
|
||||||
if (typeof data.description === 'string') text.innerText = data.description;
|
if (typeof data.description === 'string') text.innerText = data.description;
|
||||||
|
|
||||||
// Запись в оболочку
|
// Запись в оболочку
|
||||||
description.appendChild(text);
|
description.appendChild(text);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
typeof data.cover === "string"
|
typeof data.cover === 'string'
|
||||||
) {
|
) {
|
||||||
// Получено изображение-обложка
|
// Получено изображение-обложка
|
||||||
|
|
||||||
// Инициализация изображения-обложки
|
// Инициализация изображения-обложки
|
||||||
const cover = document.createElement("img");
|
const cover = document.createElement('img');
|
||||||
if (typeof cover.src === 'string') cover.src = data.cover;
|
if (typeof cover.src === 'string') cover.src = data.cover;
|
||||||
if (typeof cover.alt === 'string') cover.alt = data.title;
|
if (typeof cover.alt === 'string') cover.alt = data.title;
|
||||||
cover.classList.add(..._this.#operator.classes.node.cover);
|
cover.classList.add(..._this.#operator.classes.node.cover);
|
||||||
|
@ -370,8 +370,8 @@ class graph {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
typeof data.append === "HTMLCollection" ||
|
typeof data.append === 'HTMLCollection' ||
|
||||||
typeof data.append === "HTMLElement"
|
typeof data.append === 'HTMLElement'
|
||||||
) {
|
) {
|
||||||
// Получены другие HTML-элементы
|
// Получены другие HTML-элементы
|
||||||
|
|
||||||
|
@ -463,7 +463,7 @@ class graph {
|
||||||
a.style.left = description.offsetWidth / 2 - a.offsetWidth / 2 + 'px';
|
a.style.left = description.offsetWidth / 2 - a.offsetWidth / 2 + 'px';
|
||||||
|
|
||||||
// Сокрытие описания (выполняется после расчёта размера потому, что иначе размер будет недоступен)
|
// Сокрытие описания (выполняется после расчёта размера потому, что иначе размер будет недоступен)
|
||||||
description.style.display = "none";
|
description.style.display = 'none';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Показать описание
|
* Показать описание
|
||||||
|
@ -526,7 +526,7 @@ class graph {
|
||||||
|
|
||||||
// Инициализация размера HTML-элемента
|
// Инициализация размера HTML-элемента
|
||||||
this.element.style.width = this.element.style.height =
|
this.element.style.width = this.element.style.height =
|
||||||
this.#diameter + "px";
|
this.#diameter + 'px';
|
||||||
|
|
||||||
// Инициализация описания
|
// Инициализация описания
|
||||||
const description = this.element.getElementsByClassName('description')[0];
|
const description = this.element.getElementsByClassName('description')[0];
|
||||||
|
@ -542,7 +542,7 @@ class graph {
|
||||||
// Инициализация наблюдателя
|
// Инициализация наблюдателя
|
||||||
this.#observer = new MutationObserver(function (mutations) {
|
this.#observer = new MutationObserver(function (mutations) {
|
||||||
for (const mutation of mutations) {
|
for (const mutation of mutations) {
|
||||||
if (mutation.type === "attributes") {
|
if (mutation.type === 'attributes') {
|
||||||
// Перехвачено изменение аттрибута
|
// Перехвачено изменение аттрибута
|
||||||
|
|
||||||
// Запись параметра в инстанцию бегущей строки
|
// Запись параметра в инстанцию бегущей строки
|
||||||
|
@ -560,12 +560,12 @@ class graph {
|
||||||
|
|
||||||
move(x, y, collision = false, pushing = false, pulling = false) {
|
move(x, y, collision = false, pushing = false, pulling = false) {
|
||||||
// Запись отступов
|
// Запись отступов
|
||||||
this.element.style.left = x + "px";
|
this.element.style.left = x + 'px';
|
||||||
this.element.style.top = y + "px";
|
this.element.style.top = y + 'px';
|
||||||
|
|
||||||
// Запись аттрибутов с координатами
|
// Запись аттрибутов с координатами
|
||||||
this.element.setAttribute("data-graph-x", x);
|
this.element.setAttribute('data-x', x);
|
||||||
this.element.setAttribute("data-graph-y", y);
|
this.element.setAttribute('data-y', y);
|
||||||
|
|
||||||
// Инициализация реестров узлов
|
// Инициализация реестров узлов
|
||||||
if (collision === true) collision = new Set();
|
if (collision === true) collision = new Set();
|
||||||
|
@ -866,7 +866,7 @@ class graph {
|
||||||
(node.diameter + _this.diameter) / 2 +
|
(node.diameter + _this.diameter) / 2 +
|
||||||
distance +
|
distance +
|
||||||
increase +
|
increase +
|
||||||
(typeof add === "number" ? add : 0) ||
|
(typeof add === 'number' ? add : 0) ||
|
||||||
--iterations <= 0
|
--iterations <= 0
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
@ -904,7 +904,7 @@ class graph {
|
||||||
(node.diameter + _this.diameter) / 2 +
|
(node.diameter + _this.diameter) / 2 +
|
||||||
distance +
|
distance +
|
||||||
increase +
|
increase +
|
||||||
(typeof add === "number" ? add : 0)
|
(typeof add === 'number' ? add : 0)
|
||||||
)
|
)
|
||||||
setTimeout(move, between.length() / 100);
|
setTimeout(move, between.length() / 100);
|
||||||
}
|
}
|
||||||
|
@ -997,7 +997,7 @@ class graph {
|
||||||
(node.diameter + _this.diameter) / 2 +
|
(node.diameter + _this.diameter) / 2 +
|
||||||
distance +
|
distance +
|
||||||
increase +
|
increase +
|
||||||
(typeof add === "number" ? add : 0) ||
|
(typeof add === 'number' ? add : 0) ||
|
||||||
--iterations <= 0
|
--iterations <= 0
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
@ -1034,7 +1034,7 @@ class graph {
|
||||||
(node.diameter + _this.diameter) / 2 +
|
(node.diameter + _this.diameter) / 2 +
|
||||||
distance +
|
distance +
|
||||||
increase +
|
increase +
|
||||||
(typeof add === "number" ? add : 0)
|
(typeof add === 'number' ? add : 0)
|
||||||
)
|
)
|
||||||
return setTimeout(
|
return setTimeout(
|
||||||
move,
|
move,
|
||||||
|
@ -1049,9 +1049,9 @@ class graph {
|
||||||
|
|
||||||
configure(attribute) {
|
configure(attribute) {
|
||||||
// Инициализация названия параметра
|
// Инициализация названия параметра
|
||||||
const parameter = (/^data-graph-(\w+)$/.exec(attribute) ?? [, null])[1];
|
const parameter = (/^data-(\w+)$/.exec(attribute) ?? [, null])[1];
|
||||||
|
|
||||||
if (typeof parameter === "string") {
|
if (typeof parameter === 'string') {
|
||||||
// Параметр найден
|
// Параметр найден
|
||||||
|
|
||||||
// Проверка на разрешение изменения
|
// Проверка на разрешение изменения
|
||||||
|
@ -1064,19 +1064,19 @@ class graph {
|
||||||
// Найдено значение
|
// Найдено значение
|
||||||
|
|
||||||
// Запрошено изменение координаты: x
|
// Запрошено изменение координаты: x
|
||||||
if (parameter === "x") this.element.style.left = value + "px";
|
if (parameter === 'x') this.element.style.left = value + 'px';
|
||||||
|
|
||||||
// Запрошено изменение координаты: y
|
// Запрошено изменение координаты: y
|
||||||
if (parameter === "y") this.element.style.top = value + "px";
|
if (parameter === 'y') this.element.style.top = value + 'px';
|
||||||
|
|
||||||
// Инициализация буфера для временных данных
|
// Инициализация буфера для временных данных
|
||||||
let buffer;
|
let buffer;
|
||||||
|
|
||||||
// Запись параметра
|
// Запись параметра
|
||||||
this[parameter] = isNaN((buffer = parseFloat(value)))
|
this[parameter] = isNaN((buffer = parseFloat(value)))
|
||||||
? value === "true"
|
? value === 'true'
|
||||||
? true
|
? true
|
||||||
: value === "false"
|
: value === 'false'
|
||||||
? false
|
? false
|
||||||
: value
|
: value
|
||||||
: buffer;
|
: buffer;
|
||||||
|
@ -1148,7 +1148,7 @@ class graph {
|
||||||
// Не найден HTML-элемент-оболочки соединений
|
// Не найден HTML-элемент-оболочки соединений
|
||||||
|
|
||||||
// Инициализация HTML-элемента-оболочки соединений
|
// Инициализация HTML-элемента-оболочки соединений
|
||||||
const shell = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
const shell = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
||||||
shell.id = this.#operator.id + '_connections';
|
shell.id = this.#operator.id + '_connections';
|
||||||
shell.classList.add(...this.#operator.classes.connection.shell);
|
shell.classList.add(...this.#operator.classes.connection.shell);
|
||||||
|
|
||||||
|
@ -1164,35 +1164,35 @@ class graph {
|
||||||
|
|
||||||
// Инициализация оболочки
|
// Инициализация оболочки
|
||||||
const line = document.createElementNS(
|
const line = document.createElementNS(
|
||||||
"http://www.w3.org/2000/svg",
|
'http://www.w3.org/2000/svg',
|
||||||
"line"
|
'line'
|
||||||
);
|
);
|
||||||
line.setAttribute(
|
line.setAttribute(
|
||||||
"x1",
|
'x1',
|
||||||
(isNaN((buffer = parseInt(from.element.style.left))) ? 0 : buffer) +
|
(isNaN((buffer = parseInt(from.element.style.left))) ? 0 : buffer) +
|
||||||
from.element.offsetWidth / 2
|
from.element.offsetWidth / 2
|
||||||
);
|
);
|
||||||
line.setAttribute(
|
line.setAttribute(
|
||||||
"y1",
|
'y1',
|
||||||
(isNaN((buffer = parseInt(from.element.style.top))) ? 0 : buffer) +
|
(isNaN((buffer = parseInt(from.element.style.top))) ? 0 : buffer) +
|
||||||
from.element.offsetHeight / 2
|
from.element.offsetHeight / 2
|
||||||
);
|
);
|
||||||
line.setAttribute(
|
line.setAttribute(
|
||||||
"x2",
|
'x2',
|
||||||
(isNaN((buffer = parseInt(to.element.style.left))) ? 0 : buffer) +
|
(isNaN((buffer = parseInt(to.element.style.left))) ? 0 : buffer) +
|
||||||
to.element.offsetWidth / 2
|
to.element.offsetWidth / 2
|
||||||
);
|
);
|
||||||
line.setAttribute(
|
line.setAttribute(
|
||||||
"y2",
|
'y2',
|
||||||
(isNaN((buffer = parseInt(to.element.style.top))) ? 0 : buffer) +
|
(isNaN((buffer = parseInt(to.element.style.top))) ? 0 : buffer) +
|
||||||
to.element.offsetHeight / 2
|
to.element.offsetHeight / 2
|
||||||
);
|
);
|
||||||
line.setAttribute("stroke", "grey");
|
line.setAttribute('stroke', 'grey');
|
||||||
line.setAttribute("stroke-width", "8px");
|
line.setAttribute('stroke-width', '8px');
|
||||||
line.id = this.#operator.id + '_connection_' + operator.connections.size;
|
line.id = this.#operator.id + '_connection_' + operator.connections.size;
|
||||||
line.classList.add(...this.operator.classes.connection.element);
|
line.classList.add(...this.operator.classes.connection.element);
|
||||||
line.setAttribute("data-from", from.element.id);
|
line.setAttribute('data-from', from.element.id);
|
||||||
line.setAttribute("data-to", to.element.id);
|
line.setAttribute('data-to', to.element.id);
|
||||||
|
|
||||||
// Запись в оболочку
|
// Запись в оболочку
|
||||||
this.shell.append(line);
|
this.shell.append(line);
|
||||||
|
@ -1208,8 +1208,8 @@ class graph {
|
||||||
*/
|
*/
|
||||||
synchronize(node) {
|
synchronize(node) {
|
||||||
// Инициализация названий аттрибутов
|
// Инициализация названий аттрибутов
|
||||||
let x = "x",
|
let x = 'x',
|
||||||
y = "y";
|
y = 'y';
|
||||||
|
|
||||||
if (node === this.from) {
|
if (node === this.from) {
|
||||||
// Исходящее соединение
|
// Исходящее соединение
|
||||||
|
@ -1231,6 +1231,7 @@ class graph {
|
||||||
// Запись отступа (координаты по горизонтали)
|
// Запись отступа (координаты по горизонтали)
|
||||||
this.element.setAttribute(
|
this.element.setAttribute(
|
||||||
x,
|
x,
|
||||||
|
-this.#shell.getAttribute('data-x') +
|
||||||
(isNaN((buffer = parseInt(node.element.style.left))) ? 0 : buffer) +
|
(isNaN((buffer = parseInt(node.element.style.left))) ? 0 : buffer) +
|
||||||
node.element.offsetWidth / 2
|
node.element.offsetWidth / 2
|
||||||
);
|
);
|
||||||
|
@ -1238,6 +1239,7 @@ class graph {
|
||||||
// Запись отступа (координаты по вертикали)
|
// Запись отступа (координаты по вертикали)
|
||||||
this.element.setAttribute(
|
this.element.setAttribute(
|
||||||
y,
|
y,
|
||||||
|
-this.#shell.getAttribute('data-y') +
|
||||||
(isNaN((buffer = parseInt(node.element.style.top))) ? 0 : buffer) +
|
(isNaN((buffer = parseInt(node.element.style.top))) ? 0 : buffer) +
|
||||||
node.element.offsetHeight / 2
|
node.element.offsetHeight / 2
|
||||||
);
|
);
|
||||||
|
@ -1288,26 +1290,39 @@ class graph {
|
||||||
const x = onmousedown.pageX - coords.left + scrollX;
|
const x = onmousedown.pageX - coords.left + scrollX;
|
||||||
const y = onmousedown.pageY - coords.top + scrollY;
|
const y = onmousedown.pageY - coords.top + scrollY;
|
||||||
|
|
||||||
// Инициализация буфера высчитанных отступов полотна
|
// Инициализация HTML-элемента-оболочки соединений
|
||||||
let _x, _y;
|
const connections = document.getElementById(_this.#id + '_connections');
|
||||||
|
|
||||||
// Инициализация функции переноса полотна
|
// Инициализация функции переноса полотна
|
||||||
function move(onmousemove) {
|
function move(onmousemove) {
|
||||||
// Запись нового отступа от лева
|
// Инициализация буфера
|
||||||
_this.shell.style.left = (_x = onmousemove.pageX - x) + "px";
|
let buffer;
|
||||||
|
|
||||||
// Запись нового отступа от верха
|
// Запись нового отступа от лева для HTML-элемента оболочки графика
|
||||||
_this.shell.style.top = (_y = onmousemove.pageY - y) + "px";
|
_this.shell.style.left = (buffer = onmousemove.pageX - x) + 'px';
|
||||||
|
|
||||||
// for (const connection of _this.#connections) {
|
// Запись нового отступа от лева для HTML-элемента оболочки соединений
|
||||||
// // Перебор всех HTML-элементов-соединений
|
connections.style.left = -buffer + 'px';
|
||||||
|
|
||||||
// // Запись нового отступа от лева
|
// Запись аттрибута с координатами для HTML-элемента оболочки соединений
|
||||||
// connection.element.style.left = -_x + "px";
|
connections.setAttribute('data-x', -buffer);
|
||||||
|
|
||||||
// // Запись нового отступа от верха
|
// Запись нового отступа от верха для HTML-элемента оболочки графика
|
||||||
// connection.element.style.top = -_y + "px";
|
_this.shell.style.top = (buffer = onmousemove.pageY - y) + 'px';
|
||||||
// }
|
|
||||||
|
// Запись нового отступа от верха для HTML-элемента оболочки соединений
|
||||||
|
connections.style.top = -buffer + 'px';
|
||||||
|
|
||||||
|
// Запись аттрибута с координатами для HTML-элемента оболочки соединений
|
||||||
|
connections.setAttribute('data-y', -buffer);
|
||||||
|
|
||||||
|
for (const connection of _this.connections) {
|
||||||
|
// Перебор соединений
|
||||||
|
|
||||||
|
// Синхронизация
|
||||||
|
connection.synchronize(connection.from);
|
||||||
|
connection.synchronize(connection.to);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Запись слушателя события: "перенос полотна"
|
// Запись слушателя события: "перенос полотна"
|
||||||
|
@ -1330,7 +1345,7 @@ class graph {
|
||||||
}
|
}
|
||||||
|
|
||||||
write = function (data = {}) {
|
write = function (data = {}) {
|
||||||
if (typeof data === "object") {
|
if (typeof data === 'object') {
|
||||||
// Получен обязательный входной параметр в правильном типе
|
// Получен обязательный входной параметр в правильном типе
|
||||||
|
|
||||||
// Инициализация узла
|
// Инициализация узла
|
||||||
|
@ -1437,7 +1452,7 @@ class graph {
|
||||||
}
|
}
|
||||||
|
|
||||||
document.dispatchEvent(
|
document.dispatchEvent(
|
||||||
new CustomEvent("graph.loaded", {
|
new CustomEvent('graph.loaded', {
|
||||||
detail: { graph }
|
detail: { graph }
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue