Этот призыв к статьям можно назвать судьбой, потому что в последние два месяца я работал над echarts, antvg6, cesium и другими визуальными широкоэкранными и блок-схемами, а также сделал некоторые резюме в блоге. Часть g6 уже была обобщена, это было в период исследования проекта на тот момент, а затем углубленное использование после перевода исследования в стадию разработки не было обобщено, а было только дальнейшее использование функции, и вещи, которые нужно использовать, все еще это. Во время своих исследований я написал демо, которое на тот момент находилось в стадии исследования, хотя было много проблем, я мог сослаться на структуру и использование.
Резюме личного блога:Энкаи просмотрел .top/blog/6.htm…
небольшая демонстрация g6:GitHub.com/encaike/G6-com…
представлять
G6 — это простой, удобный в использовании и полноценный движок для визуализации графов, который предоставляет серию элегантных и простых в использовании решений для визуализации графов, основанных на широких возможностях настройки. Это может помочь разработчикам создавать свои собственные приложения для визуализации графиков, анализа графиков или редактора графиков.
Установить
-
Введение CDN
// version <= 3.2 <script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g6-{$version}/build/g6.js"></script> // version >= 3.3 <script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g6-{$version}/dist/g6.min.js"></script>
Введите номер версии в поле {$version}, например 3.4.7;
Последняя версия может просматривать последнюю версию и номер версии в NPM;
За подробностями обращайтесь к ветке Github:GitHub.com/ant-vis/ant-6/he…
- установка нпм
-
Установить зависимости с помощью npm
npm install --save @antv/g6
-
Импортируйте, где необходимо
import G6 from '@antv/g6';
-
Используется во Вью
- Импорт в файлы, которые должны использовать G6/глобально в Vue
- Способ создания схемы инициализации в методах, подробную настройку смотрите в документации
- Вызовите метод init в смонтированном или созданном и используйте nextTick, чтобы немедленно изменить DOM.
- Если есть Behavior, прослушивание привязки и т. д. интерактивные события, вам необходимо объявить их перед инициализацией.
Пример кода:
//此处为引入G6,以及引入我自己定义的行为和节点
import G6, { Graph } from "@antv/g6";
import { initBehavors } from "./behavior";
import { initItems } from "./Item";
//此处调用初始化方法
export default {
created() {
this.$nextTick(() => {
this.init();
});
},
methods:{
init() {
/* 图初始化 */
this.graph = new G6.Graph({
container: "mountNode", //这里写绑定标签的id,G6画布会插入到这个位置
width: this.width, //图宽度
height: this.height, //图高度
...
});
}
}
}
Если вы хотите изменить адаптивное окно, вам нужно одновременно изменить конфигурацию ширины и высоты холста и g6.
концепция
холст/макет
Канвас в G6 — это канвас, который нужно вставить в див, включая плагин канваса. Потому что вам нужно объявить класс и размер вставленного div во время инициализации. Макет — это правила распределения элементов холста, после настройки элементы будут фиксировать свое положение в соответствии с правилами распределения.
элемент
В G6 узлы, ребра и группы являются элементами, и структура является общей. Такие объекты определяются в данных графика и визуализируются на холсте методом рендеринга. Без событий взаимодействия, которые нужно координировать, элемент будет просто генерировать графику на холсте по определению.
условие
Состояние стиля элемента можно изменить с помощью интерактивного поведения и привязки событий, после чего отображаются эффекты стиля различных состояний, настроенных во время инициализации.
взаимодействовать
Интерактивные объекты в G6 в основном включают холст и элементы, которые могут реагировать на все обычные интерактивные события. Его необходимо определить и зарегистрировать в соответствии с поведением документа. Регистрация до инициализации может быть прописана в initialization, а регистрация после инициализации добавляется через метод. События также можно использовать отдельно, с привязкой слушателей.
анимация
Анимации можно добавлять в G6.После определения анимации и ее регистрации в компоненте анимации ее можно отобразить на холсте. В основном делится на глобальную анимацию, анимацию узлов и краевую анимацию.
использовать
Реализовать добавление узла/ребра/комбо (то же самое удаление и изменение)
-
С помощью API G6 через метод addItem указывается тип элемента и создается конфигурация узла. Узлы, созданные таким образом, могут получать данные только через API.
this.graph.addItem("node", { id: this.newNode.id, type: this.newNode.type, label: this.newNode.label, size: nodeSize, x: parseInt(this.newNode.x), y: parseInt(this.newNode.y), comboId: null });
-
Определите данные графика в данных, затем добавьте их в массив узлов с помощью метода push и прочитайте данные через API для повторного рендеринга и добавления узлов. Узлы, созданные этим методом, могут получать операции непосредственно в данных.
this.ghdata.nodes.push({ id: this.newNode.id, type: this.newNode.type, label: this.newNode.label, size: nodeSize, x: parseInt(this.newNode.x), y: parseInt(this.newNode.y), comboId: null }); this.graph.read(this.ghdata); this.graph.render();
Реализовать привязку поведения/мониторинг событий
-
Зарегистрируйте поведение с помощью метода registerBehavior, параметрами которого являются имя поведения и конфигурация поведения, а метод getEvents предназначен для описания соответствующей связи между событиями и методами. После регистрации нужно настроить режим участия поведения в диаграмме, иначе он не подействует.
G6.registerBehavior("before-edge", { getEvents() { return { "node:mousedown": "onMouseDown" }; }, onMouseDown(e) { const graph = this.graph; if ("index" in e.shape.attrs) { if (e.shape.attrs.index == "node") { console.log("节点:拖动关键图形"); } else { console.log("节点:拖动锚点"); if (e.item) { const point = e.item.getContainer().get("children")[ parseInt(e.shape.attrs.index) + 1 ]; point.attr("fill", "#fff"); point.attr("stroke", "#000"); point.attr("r", 2.5); } const uid = Math.round(Math.random() * 100 + 100); graph.setMode("addedge"); newEdge = graph.addItem("edge", { id: uid, type: "cubic", source: e.item.getModel().id, sourceAnchor: e.shape.attrs.index, target: { x: e.x, y: e.y } }); newEdge.toBack(); } } else { console.log("节点:拖动原生图形"); } } }); this.graph = new G6.Graph({ modes: { default: [ "before-edge" ] }, })
-
Добавляйте или удаляйте прослушиватели событий с помощью метода включения/выключения.Параметры — это события прослушивателя и методы обработки. Прослушиватели событий позволяют прослушивателям запускать только одно событие, но поведения могут прослушивать несколько событий одновременно.
this.graph.on("node:click", e => { this.select = { ...e.item.getModel() }; });
Реализовать переходы между состояниями
-
Сначала объявите стиль состояния в конфигурации стиля, есть два метода:
- Инициализировать глобальную конфигурацию по умолчанию
this.graph = new G6.Graph({ defaultEdge: { style: { stroke: "#000", endArrow: true } }, edgeStateStyles: { hover: { stroke: "#66C4FF" } }, })
- Добавьте узлы для индивидуальной настройки
this.graph.addItem("node", { ..., style: { stroke: "#000", endArrow: true } });
-
Затем состояние элемента преобразуется через метод setItemState в коде.Многозначное преобразование поддерживается в старшей версии G6, то есть один тип состояния имеет несколько стилей состояния.
const graph = this.graph; const item = e.item; graph.setItemState(item, "hover", true);
Реализовать пользовательские узлы/ребра
-
Зарегистрируйте узел/ребро с помощью метода registerNode/registerEdge, параметрами которого являются имя узла/ребра и настраиваемый объект жизненного цикла.
G6.registerNode( 'nodeName', { options: { style: {}, stateStyles: { hover: {}, selected: {}, }, }, /** * 绘制节点,包含文本 * @param {Object} cfg 节点的配置项 * @param {G.Group} group 节点的容器 * @return {G.Shape} 返回一个绘制的图形作为 keyShape,通过 node.get('keyShape') 可以获取。 * 关于 keyShape 可参考文档 核心概念-节点/边/Combo-图形 Shape 与 keyShape */ draw(cfg, group) {}, /** * 绘制后的附加操作,默认没有任何操作 * @param {Object} cfg 节点的配置项 * @param {G.Group} group 节点的容器 */ afterDraw(cfg, group) {}, /** * 更新节点,包含文本 * @override * @param {Object} cfg 节点的配置项 * @param {Node} node 节点 */ update(cfg, node) {}, /** * 更新节点后的操作,一般同 afterDraw 配合使用 * @override * @param {Object} cfg 节点的配置项 * @param {Node} node 节点 */ afterUpdate(cfg, node) {}, /** * 响应节点的状态变化。 * 在需要使用动画来响应状态变化时需要被复写,其他样式的响应参见下文提及的 [配置状态样式] 文档 * @param {String} name 状态名称 * @param {Object} value 状态值 * @param {Node} node 节点 */ setState(name, value, node) {}, /** * 获取锚点(相关边的连入点) * @param {Object} cfg 节点的配置项 * @return {Array|null} 锚点(相关边的连入点)的数组,如果为 null,则没有控制点 */ getAnchorPoints(cfg) {}, }, // 继承内置节点类型的名字,例如基类 'single-node',或 'circle', 'rect' 等 // 当不指定该参数则代表不继承任何内置节点类型 extendedNodeName, );
- Метод draw требуется, если новый узел не расширяется из любого существующего узла или из «одного узла»;
- Вся графика внутри узла использует систему координат относительно самого узла, т. е. (0, 0) — это центр узла. Координаты узла относятся к холсту и контролируются матрицей на группе узлов.В пользовательском узле восприятие пользователя не требуется. Если вы добавляете прямоугольную форму в пользовательский узел, обратите внимание на его x и y минус половина его длины и ширины. См. пример определения узлов с нуля;
- Метод обновления можно оставить неопределенным:
- Когда обновление не определено: если указан третий параметр extendedNodeName для registerNode (то есть он представляет собой наследование указанного встроенного типа узла), логика обновления унаследованного встроенного типа узла будет выполняться при обновлении узла; если в третьем параметре registerNode не указан параметр, то при обновлении узла будет выполнен метод отрисовки, и вся графика будет очищена и перерисована;
- Когда метод обновления определен, независимо от того, указан ли третий параметр registerNode, переопределенная логика функции обновления будет выполняться при обновлении узла.
- методы afterDraw и afterUpdate обычно используются для расширения существующих узлов, таких как: прикрепление изображений к прямоугольным узлам, добавление анимации к круглым узлам и т. д.;
- setState нужно перезаписывать только тогда, когда вам нужно использовать анимацию для ответа на изменения состояния.Общий стиль реакции на изменения состояния может быть достигнут путем настройки стилей состояния;
- Метод getAnchorPoints нужно переопределять только в том случае, если вам нужно ограничить точки подключения краем, или его можно указать непосредственно в данных.
-
В дополнение к draw, который является обязательным методом рисования графики, по мере необходимости добавляются другие методы (методы, которые не переопределены, будут наследовать базовый класс). Параметр cfg Draw — это конфигурация создания, а группа — комбинация графики, этот метод возвращает комбинацию графики, которая является окончательным стилем.
G6.registerNode("ownrect", { draw(cfg, group) { group.addShape("rect", { attrs: { width: cfg.size[0], height: cfg.size[1], stroke: "block", fill: "white", index: "node" }, draggable: true }); const points = cfg.anchorPoints; for (let index = 0; index < points.length; index++) { group.addShape("circle", { attrs: { x: cfg.size[0] * points[index][0], y: cfg.size[1] * points[index][1], r: 2.5, stroke: "block", fill: "white", index } }); } if (cfg.label) { group.addShape("text", { attrs: { x: cfg.size[0] / 2, y: cfg.size[1] / 2, textAlign: "center", textBaseline: "middle", text: cfg.label, fill: "#666", index: "node" }, draggable: true }); } return group; } });
Реализовать перетаскивание для создания узлов
-
Установите тег HTML для перетаскивания, а затем добавьте метод перетаскивания после завершения перетаскивания.
<span draggable @dragend="handleDragEnd"> 拖动节点 </span>
-
Задайте сгенерированные координаты x, y и конфигурацию узлов в dragend, а затем добавьте узлы на холст через addItem.
handleDragEnd(e) { let str = Math.round(Math.random() * 100).toString(); let point = this.graph.getPointByClient(e.clientX, e.clientY); this.graph.addItem("node", { id: str, type: "ownrect", label: str, size: [80, 80], x: parseInt(point.x - 40), y: parseInt(point.y - 40), comboId: null }); },
Реализовать перетаскивание для создания краев
-
Сначала разберитесь с логикой перетаскивания и добавления ребер и перетаскивания и перемещения узлов.Поведение перетаскивания узла помещается в режим по умолчанию, а поведение добавления ребра помещается в пользовательский режим. Через событие node:mousedown (мышь вниз на узле) вы можете отслеживать, нажата ли мышь на точку привязки или на узел.Если это точка привязки, переключитесь в пользовательский режим и создайте ребро в том же время.Если это узел, все равно.
G6.registerBehavior("before-edge", { getEvents() { return { "node:mousedown": "onMouseDown" }; }, onMouseDown(e) { const graph = this.graph; if ("index" in e.shape.attrs) { if (e.shape.attrs.index == "node") { console.log("节点:拖动关键图形"); } else { console.log("节点:拖动锚点"); if (e.item) { const point = e.item.getContainer().get("children")[ parseInt(e.shape.attrs.index) + 1 ]; point.attr("fill", "#fff"); point.attr("stroke", "#000"); point.attr("r", 2.5); } const uid = Math.round(Math.random() * 100 + 100); graph.setMode("addedge"); newEdge = graph.addItem("edge", { id: uid, type: "cubic", source: e.item.getModel().id, sourceAnchor: e.shape.attrs.index, target: { x: e.x, y: e.y } }); newEdge.toBack(); } } else { console.log("节点:拖动原生图形"); } } });
-
После переключения в пользовательский режим прослушивайте событие mousemove (перемещение мыши по всему холсту) и постоянно обновляйте целевую конфигурацию стороны, получая положение мыши, чтобы заставить мышь перетаскивать и перемещать ее во время движения. Затем, когда инициируется событие mouseup (полное поднятие мыши на холсте), получается информация об узле и точке привязки, на которую указывалось при освобождении, и создается ребро обновления. Если вы не находитесь на узле, когда отпускаете мышь, край сразу уничтожается.
G6.registerBehavior("add-edge", { getEvents() { return { mousemove: "onMouseMove", mouseup: "onMouseUp" }; }, onMouseMove(e) { const graph = this.graph; console.log("画布:鼠标移动"); if (newEdge) { graph.updateItem(newEdge, { target: { x: e.x, y: e.y } }); } }, onMouseUp(e) { const graph = this.graph; if (!e.item.getModel()) { console.log("节点:松开在画布"); graph.removeItem(newEdge); graph.setMode("default"); newEdge = {}; return; } if ("index" in e.shape.attrs) { if (e.shape.attrs.index == "node") { console.log("节点:松开在关键图形"); } else { console.log("节点:松开在锚点"); graph.updateItem(newEdge, { target: e.item.getModel().id, targetAnchor: e.shape.attrs.index }); graph.setMode("default"); newEdge = {}; } } else { console.log("节点:松开在原生图形"); } } });
наконец
Это мой первый раз, когда писать статью, так что есть много недостатков, я надеюсь, что все могут критиковать и исправить меня, спасибо ~