feat: v5 selfloop (#4857)

* feat: v5 selfloop

* fix: update loop

---------

Co-authored-by: yvonneyx <banxuan.zyx@antgroup.com>
Co-authored-by: Yanyan Wang <yanyanwang93@gmail.com>
This commit is contained in:
yvonneyx 2023-08-29 15:24:58 +08:00 committed by GitHub
parent db369d1b09
commit 2bb251f80f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 804 additions and 17 deletions

View File

@ -45,7 +45,7 @@
"fix": "eslint ./src ./tests --fix && prettier ./src ./tests --write ", "fix": "eslint ./src ./tests --fix && prettier ./src ./tests --write ",
"test": "jest", "test": "jest",
"test:integration": "node --expose-gc --max-old-space-size=4096 --unhandled-rejections=strict node_modules/jest/bin/jest tests/integration/ --config jest.node.config.js --coverage -i --logHeapUsage --detectOpenHandles", "test:integration": "node --expose-gc --max-old-space-size=4096 --unhandled-rejections=strict node_modules/jest/bin/jest tests/integration/ --config jest.node.config.js --coverage -i --logHeapUsage --detectOpenHandles",
"test:integration_one": "node --expose-gc --max-old-space-size=4096 --unhandled-rejections=strict node_modules/jest/bin/jest tests/integration/combo-render.spec.ts --config jest.node.config.js --coverage -i --logHeapUsage --detectOpenHandles", "test:integration_one": "node --expose-gc --max-old-space-size=4096 --unhandled-rejections=strict node_modules/jest/bin/jest tests/integration/items-edge-loop.spec.ts --config jest.node.config.js --coverage -i --logHeapUsage --detectOpenHandles",
"size": "limit-size", "size": "limit-size",
"test-live": "DEBUG_MODE=1 jest --watch ./tests/unit/item-animate-spec.ts", "test-live": "DEBUG_MODE=1 jest --watch ./tests/unit/item-animate-spec.ts",
"test-behavior": "DEBUG_MODE=1 jest --watch ./tests/unit/item-3d-spec.ts" "test-behavior": "DEBUG_MODE=1 jest --watch ./tests/unit/item-3d-spec.ts"

View File

@ -9,7 +9,7 @@ import DragCombo from './behavior/drag-combo';
import DragNode from './behavior/drag-node'; import DragNode from './behavior/drag-node';
import LassoSelect from './behavior/lasso-select'; import LassoSelect from './behavior/lasso-select';
import { validateData } from './data/validateData'; import { validateData } from './data/validateData';
import { LineEdge } from './item/edge'; import { LineEdge, LoopEdge } from './item/edge';
import { import {
CircleNode, CircleNode,
EllipseNode, EllipseNode,
@ -116,6 +116,7 @@ const stdLib = {
'cubic-vertical-edge': CubicVerticalEdge, 'cubic-vertical-edge': CubicVerticalEdge,
'quadratic-edge': Quadratic, 'quadratic-edge': Quadratic,
'polyline-edge': Polyline, 'polyline-edge': Polyline,
'loop-edge': LoopEdge,
}, },
combos: { combos: {
'circle-combo': CircleCombo, 'circle-combo': CircleCombo,

View File

@ -32,6 +32,7 @@ import { getWordWrapWidthByEnds } from '../../../util/text';
import { AnimateCfg } from '../../../types/animate'; import { AnimateCfg } from '../../../types/animate';
import { getZoomLevel } from '../../../util/zoom'; import { getZoomLevel } from '../../../util/zoom';
import { DEFAULT_ARROW_CONFIG, getArrowPath } from '../../../util/arrow'; import { DEFAULT_ARROW_CONFIG, getArrowPath } from '../../../util/arrow';
import Node from '../../../item/node';
export abstract class BaseEdge { export abstract class BaseEdge {
type: string; type: string;

View File

@ -1,3 +1,4 @@
export * from './line'; export * from './line';
export * from './quadratic'; export * from './quadratic';
export * from './polyline'; export * from './polyline';
export * from './loop';

View File

@ -0,0 +1,162 @@
import { vec2 } from '@antv/matrix-util';
import { getBBoxHeight, getBBoxWidth } from '../../../util/bbox';
import { distanceVec } from '../../../util/point';
import {
calculatePointForEllipse,
calculatePointForOtherShapes,
} from '../../../util/loop';
import { Point } from '../../../types/common';
import {
EdgeDisplayModel,
EdgeModelData,
EdgeShapeMap,
} from '../../../types/edge';
import { State } from '../../../types/item';
import { LOOP_POSITION, LoopCfg, LoopPosition } from '../../../types/loop';
import { CubicEdge } from './cubic';
export class LoopEdge extends CubicEdge {
public type = 'loop-edge';
public defaultStyles = {
keyShape: {
x1: 0,
y1: 0,
z1: 0,
x2: 0,
y2: 0,
z2: 0,
isBillboard: true,
loopCfg: {
position: LOOP_POSITION.top,
clockwise: true,
},
},
};
constructor(props) {
super(props);
// suggest to merge default styles like this to avoid style value missing
// this.defaultStyles = mergeStyles([this.baseDefaultStyles, this.defaultStyles]);
}
public drawKeyShape(
model: EdgeDisplayModel,
sourcePoint: Point,
targetPoint: Point,
shapeMap: EdgeShapeMap,
diffData?: { previous: EdgeModelData; current: EdgeModelData },
diffState?: { previous: State[]; current: State[] },
) {
const { keyShape: keyShapeStyle } = this.mergedStyles as any;
const { startPoint, endPoint, controlPoints } = this.getPathPoints(
model,
sourcePoint,
targetPoint,
keyShapeStyle.loopCfg,
);
const { startArrow, endArrow, ...others } = keyShapeStyle;
const lineStyle = {
...keyShapeStyle,
path: [
['M', startPoint.x, startPoint.y],
[
'C',
controlPoints[0].x,
controlPoints[0].y,
controlPoints[1].x,
controlPoints[1].y,
endPoint.x,
endPoint.y,
],
],
};
this.upsertArrow('start', startArrow, others, model, lineStyle);
this.upsertArrow('end', endArrow, others, model, lineStyle);
return this.upsertShape('path', 'keyShape', lineStyle, shapeMap, model);
}
private getPathPoints(
model: EdgeDisplayModel,
sourcePoint: Point,
targetPoint: Point,
loopCfg: LoopCfg,
): {
startPoint: Point;
endPoint: Point;
controlPoints: [Point, Point];
} {
const { source: sourceNodeId, target: targetNodeId } = model;
if (sourceNodeId !== targetNodeId) {
throw new Error();
}
const item = this.nodeMap.get(sourceNodeId);
const shapeType = item.shapeMap.keyShape.nodeName;
const bbox = item.getKeyBBox();
const width = getBBoxWidth(bbox);
const height = getBBoxHeight(bbox);
const halfOfHeight = height / 2;
const halfOfWidth = width / 2;
const center = bbox.center;
let startPoint: vec2 = [sourcePoint.x, sourcePoint.y];
let endPoint: vec2 = [targetPoint.x, targetPoint.y];
// The relative position relationship between self-loop edge and keyShape.
const position: LoopPosition = loopCfg.position || LOOP_POSITION.top;
if (startPoint[0] === endPoint[0] && startPoint[1] === endPoint[1]) {
if (shapeType === 'circle' || shapeType === 'ellipse') {
[startPoint, endPoint] = calculatePointForEllipse(
position,
center,
halfOfWidth,
halfOfHeight,
);
} else {
[startPoint, endPoint] = calculatePointForOtherShapes(
position,
center,
halfOfWidth,
halfOfHeight,
loopCfg.pointPadding,
);
}
// If drawing counterclockwise, swap start and end points。
if (loopCfg.clockwise === false) {
const swap = startPoint;
startPoint = endPoint;
endPoint = swap;
}
}
// The distance from the edge of the keyShape
const dist: number = loopCfg.dist || Math.max(width, height) * 2;
const startVec: vec2 = [
startPoint[0] - center[0],
startPoint[1] - center[1],
];
const endVec: vec2 = [endPoint[0] - center[0], endPoint[1] - center[1]];
const rstart = distanceVec([0, 0], startVec);
const rend = distanceVec([0, 0], endVec);
const scaleRateStart = (rstart + dist) / rstart;
const scaleRateEnd = (rend + dist) / rend;
const startExtendVec = vec2.scale([0, 0], startVec, scaleRateStart);
const endExtendVec = vec2.scale([0, 0], endVec, scaleRateEnd);
const controlPoints = [
{ x: center[0] + startExtendVec[0], y: center[1] + startExtendVec[1] },
{ x: center[0] + endExtendVec[0], y: center[1] + endExtendVec[1] },
] as [Point, Point];
return {
startPoint: { x: startPoint[0], y: startPoint[1] },
endPoint: { x: endPoint[0], y: endPoint[1] },
controlPoints,
};
}
}

View File

@ -0,0 +1,23 @@
export enum LOOP_POSITION {
'top' = 'top',
'top-right' = 'top-right',
'right' = 'right',
'bottom-right' = 'bottom-right',
'bottom' = 'bottom',
'bottom-left' = 'bottom-left',
'left' = 'left',
'top-left' = 'top-left',
}
export type LoopPosition = `${LOOP_POSITION}`;
export type LoopCfg = {
/** Specifies the relative position of the self-loop to the node. Default: top. */
position?: LoopPosition;
/** Determine the position from the edge of the node keyShape to the top of the self-loop, used to specify the curvature of the self-loop, the default is the height. */
dist?: number;
/** Specify whether to draw the ring clockwise. Default: true */
clockwise?: boolean;
/** For non-circular nodes, the offset between the connection point and the center coordinates of the node (top-right, bottom-right, top-left, bottom-left are special, which are four corner coordinates) in the x-axis or y-axis direction, The default is 1/4 of the minimum value of node width and high. */
pointPadding?: number;
};

View File

@ -0,0 +1,145 @@
import { Tuple3Number } from '@antv/g';
import { vec2 } from '@antv/matrix-util';
import { LOOP_POSITION, LoopPosition } from '../types/loop';
const PI_OVER_8 = Math.PI / 8;
const radiansMap = {
[LOOP_POSITION.top]: [-5 * PI_OVER_8, -3 * PI_OVER_8],
[LOOP_POSITION['top-right']]: [-3 * PI_OVER_8, -PI_OVER_8],
[LOOP_POSITION.right]: [-PI_OVER_8, PI_OVER_8],
[LOOP_POSITION['bottom-right']]: [PI_OVER_8, 3 * PI_OVER_8],
[LOOP_POSITION.bottom]: [3 * PI_OVER_8, 5 * PI_OVER_8],
[LOOP_POSITION['bottom-left']]: [5 * PI_OVER_8, 7 * PI_OVER_8],
[LOOP_POSITION.left]: [7 * PI_OVER_8, 9 * PI_OVER_8],
[LOOP_POSITION['top-left']]: [-7 * PI_OVER_8, -5 * PI_OVER_8],
};
/**
* Calculates the start and end points of an ellipse based on the given position.
* @param {LoopPosition} position - The position of the ellipse (top, top-right, right, bottom-right, bottom, bottom-left, left, top-left).
* @param {Tuple3Number} center - The center coordinates.
* @param {number} halfOfWidth - Half of the width.
* @param {number} halfOfHeight - Half of the height.
* @returns {[vec2, vec2]} - An array containing the start and end points of the ellipse.
*/
export const calculatePointForEllipse = (
position: LoopPosition,
center: Tuple3Number,
halfOfWidth: number,
halfOfHeight: number,
): [vec2, vec2] => {
const [rstartX, rstartY, rendX, rendY] = getPointsOnEllipseAtAngles(
halfOfWidth,
halfOfHeight,
radiansMap[position]?.[0] || -PI_OVER_8,
radiansMap[position]?.[1] || PI_OVER_8,
);
return [
[center[0] + rstartX, center[1] + rstartY],
[center[0] + rendX, center[1] + rendY],
];
};
/**
* Calculates the start and end points of a shape other than an ellipse based on the given position.
* @param {LoopPosition} position
* @param {Tuple3Number} center - The center coordinates.
* @param {number} halfOfWidth - Half of the width of keyShape.
* @param {number} halfOfHeight - Half of the height of keyShape.
* @param {number} customPointPadding - Optional custom padding for the point calculation.
*/
export const calculatePointForOtherShapes = (
position: LoopPosition,
center: Tuple3Number,
halfOfWidth: number,
halfOfHeight: number,
customPointPadding?: number,
): [vec2, vec2] => {
// For aesthetic considerations, pointPadding defaults to 1/4 of the minimum width and high school.
const defaultPointPadding = Math.min(halfOfHeight / 2, halfOfWidth / 2);
const maxPointPadding = Math.min(halfOfHeight, halfOfWidth);
const pointPadding = customPointPadding
? Math.min(maxPointPadding, customPointPadding)
: defaultPointPadding;
const pointsPositionMap: Record<LoopPosition, [vec2, vec2]> = {
[LOOP_POSITION.top]: [
[center[0] - pointPadding, center[1] - halfOfHeight],
[center[0] + pointPadding, center[1] - halfOfHeight],
],
[LOOP_POSITION['top-right']]: [
[center[0] + halfOfWidth - pointPadding, center[1] - halfOfHeight],
[center[0] + halfOfWidth, center[1] - halfOfHeight + pointPadding],
],
[LOOP_POSITION.right]: [
[center[0] + halfOfWidth, center[1] - pointPadding],
[center[0] + halfOfWidth, center[1] + pointPadding],
],
[LOOP_POSITION['bottom-right']]: [
[center[0] + halfOfWidth, center[1] + halfOfHeight - pointPadding],
[center[0] + halfOfWidth - pointPadding, center[1] + halfOfHeight],
],
[LOOP_POSITION.bottom]: [
[center[0] + pointPadding, center[1] + halfOfHeight],
[center[0] - pointPadding, center[1] + halfOfHeight],
],
[LOOP_POSITION['bottom-left']]: [
[center[0] - halfOfWidth + pointPadding, center[1] + halfOfHeight],
[center[0] - halfOfWidth, center[1] + halfOfHeight - pointPadding],
],
[LOOP_POSITION.left]: [
[center[0] - halfOfWidth, center[1] + pointPadding],
[center[0] - halfOfWidth, center[1] - pointPadding],
],
[LOOP_POSITION['top-left']]: [
[center[0] - halfOfWidth, center[1] - halfOfHeight + pointPadding],
[center[0] - halfOfWidth + pointPadding, center[1] - halfOfHeight],
],
};
return pointsPositionMap[position] || pointsPositionMap[LOOP_POSITION.top];
};
/**
* Calculate the point on the ellipse at the given angle.
* @param {number} halfOfWidth - Half of the width of the ellipse.
* @param {number} halfOfHeight - Half of the height of the ellipse.
* @param {number} angleInRadians - The angle in radians.
* @returns {vec2} - The point on the ellipse at the given angle.
*/
export const getPointOnEllipseAtAngle = (
halfOfWidth: number,
halfOfHeight: number,
angleInRadians: number,
): vec2 => {
const x = halfOfWidth * Math.cos(angleInRadians);
const y = halfOfHeight * Math.sin(angleInRadians);
return [x, y];
};
/**
* Calculates an array of points on an ellipse at the given angles.
* @param {number} halfOfWidth - Half of the width of the ellipse.
* @param {number} halfOfHeight - Half of the height of the ellipse.
* @param {number} startAngle - The starting angle in radians.
* @param {number} endAngle - The ending angle in radians.
*/
export const getPointsOnEllipseAtAngles = (
halfOfWidth: number,
halfOfHeight: number,
startAngle: number,
endAngle: number,
) => {
const [rstartX, rstartY] = getPointOnEllipseAtAngle(
halfOfWidth,
halfOfHeight,
startAngle,
);
const [rendX, rendY] = getPointOnEllipseAtAngle(
halfOfWidth,
halfOfHeight,
endAngle,
);
return [rstartX, rstartY, rendX, rendY];
};

View File

@ -1,3 +1,4 @@
import { vec2 } from '@antv/matrix-util';
import { Point } from '../types/common'; import { Point } from '../types/common';
import { isBetween } from './math'; import { isBetween } from './math';
@ -34,8 +35,19 @@ export const getNearestPoint = (
/** /**
* Get distance by two points. * Get distance by two points.
* @param p1 first point * @param {vec2} p1 first point
* @param p2 second point * @param {vec2} p2 second point
*/
export const distanceVec = (p1: vec2, p2: vec2): number => {
const vx = p1[0] - p2[0];
const vy = p1[1] - p2[1];
return Math.sqrt(vx * vx + vy * vy);
};
/**
* Get distance by two points.
* @param {Point} p1 first point
* @param {Point} p2 second point
*/ */
export const distance = (p1: Point, p2: Point): number => { export const distance = (p1: Point, p2: Point): number => {
const vx = p1.x - p2.x; const vx = p1.x - p2.x;

View File

@ -1,16 +1,22 @@
// import demoFor4 from './demo/demoFor4';
import anchor from './item/anchor';
import animations_node_build_in from './animations/node-build-in'; import animations_node_build_in from './animations/node-build-in';
import arrow from './item/edge/arrow';
import behaviors_activateRelations from './behaviors/activate-relations'; import behaviors_activateRelations from './behaviors/activate-relations';
import behaviors_brush_select from './behaviors/brush-select'; import behaviors_brush_select from './behaviors/brush-select';
import behaviors_click_select from './behaviors/click-select'; import behaviors_click_select from './behaviors/click-select';
import behaviors_collapse_expand_tree from './behaviors/collapse-expand-tree'; import behaviors_collapse_expand_tree from './behaviors/collapse-expand-tree';
import bugReproduce from './demo/bugReproduce'; import bugReproduce from './demo/bugReproduce';
import circularUpdate from './layouts/circular-update';
import comboBasic from './combo/combo-basic'; import comboBasic from './combo/combo-basic';
import comboRect from './combo/combo-rect'; import comboRect from './combo/combo-rect';
import cubic_edge from './item/edge/cubic-edge'; import cubic_edge from './item/edge/cubic-edge';
import cubic_horizon_edge from './item/edge/cubic-horizon-edge'; import cubic_horizon_edge from './item/edge/cubic-horizon-edge';
import cubic_vertical_edge from './item/edge/cubic-vertical-edge'; import cubic_vertical_edge from './item/edge/cubic-vertical-edge';
import dataValidate from './data/data-validate';
import demo from './demo/demo'; import demo from './demo/demo';
import demoForPolyline from './demo/demoForPolyline'; import demoForPolyline from './demo/demoForPolyline';
import diamond from './demo/diamond';
import donut_node from './item/node/donut-node'; import donut_node from './item/node/donut-node';
import ellipse from './demo/ellipse'; import ellipse from './demo/ellipse';
import fisheye from './plugins/fisheye'; import fisheye from './plugins/fisheye';
@ -30,6 +36,7 @@ import layouts_fruchterman_gpu from './layouts/fruchterman-gpu';
import layouts_fruchterman_wasm from './layouts/fruchterman-wasm'; import layouts_fruchterman_wasm from './layouts/fruchterman-wasm';
import layouts_grid from './layouts/grid'; import layouts_grid from './layouts/grid';
import line_edge from './item/edge/line-edge'; import line_edge from './item/edge/line-edge';
import loop_edge from './item/edge/loop-edge';
import menu from './demo/menu'; import menu from './demo/menu';
import performance from './performance/performance'; import performance from './performance/performance';
import performance_layout from './performance/layout'; import performance_layout from './performance/layout';
@ -38,32 +45,34 @@ import star from './demo/star';
import polyline from './item/edge/polyline-edge'; import polyline from './item/edge/polyline-edge';
import quadratic from './demo/quadratic'; import quadratic from './demo/quadratic';
import rect from './demo/rect'; import rect from './demo/rect';
import star from './demo/star';
import toolbar from './plugins/toolbar'; import toolbar from './plugins/toolbar';
import tooltip from './demo/tooltip'; import tooltip from './demo/tooltip';
import treeGraph from './tree/treeGraph'; import treeGraph from './tree/treeGraph';
import triangle from './demo/triangle'; import triangle from './demo/triangle';
import user_defined_canvas from './user-defined-canvas/circular'; import user_defined_canvas from './user-defined-canvas/circular';
import visual from './visual/visual'; import visual from './visual/visual';
import diamond from './demo/diamond';
import dataValidate from './data/data-validate';
import anchor from './item/anchor';
import arrow from './item/edge/arrow';
import circularUpdate from './layouts/circular-update';
import modelRect from './demo/modelRect'; import modelRect from './demo/modelRect';
export { export {
anchor,
animations_node_build_in,
arrow,
behaviors_activateRelations, behaviors_activateRelations,
behaviors_brush_select, behaviors_brush_select,
behaviors_click_select, behaviors_click_select,
behaviors_collapse_expand_tree, behaviors_collapse_expand_tree,
bugReproduce, bugReproduce,
circularUpdate,
comboBasic, comboBasic,
comboRect, comboRect,
cubic_edge, cubic_edge,
cubic_horizon_edge, cubic_horizon_edge,
cubic_vertical_edge, cubic_vertical_edge,
dataValidate,
demo, demo,
demoForPolyline, demoForPolyline,
diamond,
donut_node, donut_node,
ellipse, ellipse,
fisheye, fisheye,
@ -83,6 +92,7 @@ export {
layouts_fruchterman_wasm, layouts_fruchterman_wasm,
layouts_grid, layouts_grid,
line_edge, line_edge,
loop_edge,
menu, menu,
performance_layout_3d, performance_layout_3d,
performance_layout, performance_layout,
@ -90,18 +100,12 @@ export {
polyline, polyline,
quadratic, quadratic,
rect, rect,
star,
toolbar, toolbar,
tooltip, tooltip,
animations_node_build_in,
star,
treeGraph, treeGraph,
triangle, triangle,
user_defined_canvas, user_defined_canvas,
visual, visual,
diamond,
dataValidate,
anchor,
arrow,
circularUpdate,
modelRect, modelRect,
}; };

View File

@ -0,0 +1,254 @@
import { deepMix } from '@antv/util';
import { EdgeUserModel, Graph, IGraph } from '../../../../src/index';
import { TestCaseContext } from '../../interface';
// @ts-nocheck
let graph: IGraph;
let container: HTMLElement;
const loopPosition = [
'top',
'top-right',
'right',
'bottom-right',
'bottom',
'bottom-left',
'left',
'top-left',
];
const defaultData = {
nodes: [
{
id: 'node1',
data: {
x: 100,
y: 100,
},
},
{
id: 'node2',
data: { x: 200, y: 100, type: 'rect-node' },
},
{
id: 'node3',
data: {
x: 350,
y: 100,
type: 'ellipse-node',
},
},
],
edges: [
{
id: 'edge1',
source: 'node1',
target: 'node1',
data: {
type: 'loop-edge',
keyShape: {
endArrow: {},
},
},
},
{
id: 'edge2',
source: 'node2',
target: 'node2',
data: {
type: 'loop-edge',
keyShape: {
endArrow: {},
},
},
},
{
id: 'edge3',
source: 'node3',
target: 'node3',
data: {
type: 'loop-edge',
keyShape: {
endArrow: {},
},
},
},
],
};
// create container for controllers
const createCtrlContainer = (container: HTMLElement) => {
const ctrlContainer = document.createElement('div');
ctrlContainer.id = 'ctrl-container';
ctrlContainer.style.width = '100%';
ctrlContainer.style.height = '150px';
ctrlContainer.style.backgroundColor = '#eee';
container.appendChild(ctrlContainer);
};
let outerTop = 64;
const createLabelCheckbox = (
container: HTMLElement,
labelText: string,
checkedCallback: () => void,
uncheckedCallback: () => void,
isChecked = false,
top?: number,
) => {
if (!container) return;
let innerTop = top;
if (!top) {
innerTop = outerTop;
outerTop += 30;
}
const label = document.createElement('span');
label.textContent = labelText;
label.style.position = 'absolute';
label.style.top = `${innerTop}px`;
label.style.left = '16px';
label.style.zIndex = '100';
const cb = document.createElement('input');
cb.type = 'checkbox';
cb.value = 'highlight';
cb.style.position = 'absolute';
cb.style.width = '20px';
cb.style.height = '20px';
cb.style.top = `${innerTop}px`;
cb.style.left = '400px';
cb.style.zIndex = '100';
cb.checked = Boolean(isChecked);
cb.addEventListener('click', (e) => {
cb.checked ? checkedCallback() : uncheckedCallback();
});
container.appendChild(label);
container.appendChild(cb);
};
// Create options and control buttons (for selecting different features to test)
const createControls = () => {
const parentEle = document.getElementById('ctrl-container')!;
// clockwise
createLabelCheckbox(
parentEle,
'clockwise',
() => {
graph.getAllEdgesData().forEach((edgeData) => {
const newData = deepMix({}, edgeData, {
data: {
keyShape: {
loopCfg: {
clockwise: true,
},
},
},
}) as Partial<EdgeUserModel>;
graph.updateData('edge', newData);
});
},
() => {
graph.getAllEdgesData().forEach((edgeData) => {
const newData = deepMix({}, edgeData, {
data: {
keyShape: {
loopCfg: {
clockwise: false,
},
},
},
}) as Partial<EdgeUserModel>;
graph.updateData('edge', newData);
});
},
true,
);
// custom dist
createLabelCheckbox(
parentEle,
'custom dist',
() => {
graph.getAllEdgesData().forEach((edgeData) => {
const newData = deepMix({}, edgeData, {
data: {
keyShape: {
loopCfg: {
dist: 100,
},
},
},
}) as Partial<EdgeUserModel>;
graph.updateData('edge', newData);
});
},
() => {
graph.getAllEdgesData().forEach((edgeData) => {
const newData = deepMix({}, edgeData, {
data: {
keyShape: {
loopCfg: {
dist: 0,
},
},
},
}) as Partial<EdgeUserModel>;
graph.updateData('edge', newData);
});
},
);
// change loop position
const changeLoopPositionBtn = document.createElement('button');
changeLoopPositionBtn.innerText = 'Change loop position';
changeLoopPositionBtn.style.position = 'absolute';
changeLoopPositionBtn.style.top = '124px';
changeLoopPositionBtn.style.left = '16px';
let i = 1;
changeLoopPositionBtn.addEventListener('click', () => {
graph.getAllEdgesData().forEach((edgeData) => {
const newData = deepMix({}, edgeData, {
data: {
keyShape: {
loopCfg: {
position: loopPosition[i % loopPosition.length],
},
},
},
}) as Partial<EdgeUserModel>;
graph.updateData('edge', newData);
});
i++;
});
parentEle.appendChild(changeLoopPositionBtn);
};
export default (context: TestCaseContext) => {
const { container } = context;
// 1.create control container (for control buttons, etc.)
createCtrlContainer(container!);
createControls();
graph = new Graph({
...context,
data: defaultData,
modes: {
// supported behavior
default: ['activate-relations'],
},
edge: (edgeInnerModel: any) => {
const { id, data } = edgeInnerModel;
return { id, data };
},
});
// 3.return graph
return graph;
};

View File

@ -0,0 +1,174 @@
import { resetEntityCounter } from '@antv/g';
import loopEdge from '../demo/item/edge/loop-edge';
import { createContext } from './utils';
import './utils/useSnapshotMatchers';
describe('Items edge line', () => {
beforeEach(() => {
/**
* SVG Snapshot testing will generate a unique id for each element.
* Reset to 0 to keep snapshot consistent.
*/
resetEntityCounter();
});
it('should be rendered correctly with Canvas2D', (done) => {
const dir = `${__dirname}/snapshots/canvas/items/edge/loop`;
const { backgroundCanvas, canvas, transientCanvas, container } =
createContext('canvas', 500, 500);
const graph = loopEdge({
container,
backgroundCanvas,
canvas,
transientCanvas,
width: 500,
height: 500,
});
graph.on('afterlayout', async () => {
await expect(canvas).toMatchCanvasSnapshot(dir, 'items-edge-loop');
/**
* Click the checkbox to switch clockwise.
*/
const $switchClockwise = document.querySelectorAll(
'input',
)[0] as HTMLInputElement;
$switchClockwise.click();
await expect(canvas).toMatchCanvasSnapshot(
dir,
'items-edge-loop-clockwise',
);
$switchClockwise.click();
/**
* Click the checkbox to set custom distance.
*/
const $dist = document.querySelectorAll('input')[1] as HTMLInputElement;
$dist.click();
await expect(canvas).toMatchCanvasSnapshot(
dir,
'items-edge-loop-distance',
);
$dist.click();
/**
* Click the button to change loop position.
*/
const $loopPositionBtn = document.querySelectorAll(
'button',
)[0] as HTMLButtonElement;
$loopPositionBtn.click();
await expect(canvas).toMatchCanvasSnapshot(
dir,
'items-edge-loop-top-right',
);
$loopPositionBtn.click();
await expect(canvas).toMatchCanvasSnapshot(dir, 'items-edge-loop-right');
$loopPositionBtn.click();
await expect(canvas).toMatchCanvasSnapshot(
dir,
'items-edge-loop-bottom-right',
);
$loopPositionBtn.click();
await expect(canvas).toMatchCanvasSnapshot(dir, 'items-edge-loop-bottom');
$loopPositionBtn.click();
await expect(canvas).toMatchCanvasSnapshot(
dir,
'items-edge-loop-bottom-left',
);
$loopPositionBtn.click();
await expect(canvas).toMatchCanvasSnapshot(dir, 'items-edge-loop-left');
$loopPositionBtn.click();
await expect(canvas).toMatchCanvasSnapshot(
dir,
'items-edge-loop-top-left',
);
$loopPositionBtn.click();
graph.destroy();
done();
});
});
it('should be rendered correctly with SVG', (done) => {
const dir = `${__dirname}/snapshots/svg/items/edge/loop`;
const { backgroundCanvas, canvas, transientCanvas, container } =
createContext('svg', 500, 500);
const graph = loopEdge({
container,
backgroundCanvas,
canvas,
transientCanvas,
width: 500,
height: 500,
});
graph.on('afterlayout', async () => {
await expect(canvas).toMatchSVGSnapshot(dir, 'items-edge-loop');
/**
* Click the checkbox to switch clockwise.
*/
const $switchClockwise = document.querySelectorAll(
'input',
)[0] as HTMLInputElement;
$switchClockwise.click();
await expect(canvas).toMatchSVGSnapshot(
dir,
'items-edge-loop-clockwise',
);
$switchClockwise.click();
/**
* Click the checkbox to set custom distance.
*/
const $dist = document.querySelectorAll('input')[1] as HTMLInputElement;
$dist.click();
await expect(canvas).toMatchSVGSnapshot(
dir,
'items-edge-loop-distance',
);
$dist.click();
/**
* Click the button to change loop position.
*/
const $loopPositionBtn = document.querySelectorAll(
'button',
)[0] as HTMLButtonElement;
$loopPositionBtn.click();
await expect(canvas).toMatchSVGSnapshot(
dir,
'items-edge-loop-top-right',
);
$loopPositionBtn.click();
await expect(canvas).toMatchSVGSnapshot(dir, 'items-edge-loop-right');
$loopPositionBtn.click();
await expect(canvas).toMatchSVGSnapshot(
dir,
'items-edge-loop-bottom-right',
);
$loopPositionBtn.click();
await expect(canvas).toMatchSVGSnapshot(dir, 'items-edge-loop-bottom');
$loopPositionBtn.click();
await expect(canvas).toMatchSVGSnapshot(
dir,
'items-edge-loop-bottom-left',
);
$loopPositionBtn.click();
await expect(canvas).toMatchSVGSnapshot(dir, 'items-edge-loop-left');
$loopPositionBtn.click();
await expect(canvas).toMatchSVGSnapshot(
dir,
'items-edge-loop-top-left',
);
$loopPositionBtn.click();
graph.destroy();
done();
});
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" style="background: transparent; position: fixed; outline: none;" color-interpolation-filters="sRGB" tabindex="1"><defs/><g transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" stroke="transparent" stroke-width="01"/><g fill="none" transform="matrix(1,0,0,1,0,0)"/><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,55.510433,106.122932)"><path fill="none" d="M 38.36663257727206,8.659137602339158 C 13.874892905906322 67.78742768306151,-29.420795105789466 24.491739671365735,29.7074949749329 0 L 25.088097312376465,1.9134171618254472" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 5.902270540571408,44.346217560541774 C -18.589469130794328 -14.782072520180591,42.63988004762001 -14.782072520180591,18.148140376254275 44.346217560541774 L 20.061557538079725,39.72681989798534" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(-0.923880,0.382683,-0.382683,-0.923880,25.088097,1.913417)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,153.810211,108)"><path fill="none" d="M 38.18978704486787,8 C 9.568116932870566 65.24334022399461,-27.053553179126737 28.621670111997304,30.18978704486787 0 L 25.71765108986829,2.2360679774997907" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 6.766454082410348,42.932505167995956 C -21.855216029586956 -14.310835055998652,51.38812419440765 -14.310835055998652,22.76645408241035 42.932505167995956 L 25.002522059910138,38.460369212996376" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(-0.894427,0.447214,-0.447214,-0.894427,25.717651,2.236068)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,259.776184,107.653671)"><path fill="none" d="M 78.74332207412647,10.823922002923936 C 15.413378757018165 112.75192737657898,-53.16335938395346 31.941608993363275,62.50743906974054 0 L 57.687822467503295,1.3309003747234696" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 15.984408254141556,76.44600403024128 C -47.345535062966746 -25.48200134341376,102.2753575131552 -25.48200134341376,38.9454141960469 76.44600403024128 L 41.584161834259746,72.199003806339" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(-0.963923,0.266180,-0.266180,-0.963923,57.687824,1.330900)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,100,100)"><g transform="matrix(1,0,0,1,0,0)"><circle fill="rgba(34,126,255,1)" transform="translate(-16,-16)" cx="16" cy="16" r="16" stroke-width="0"/></g></g><g fill="none" transform="matrix(1,0,0,1,200,100)"><g transform="matrix(1,0,0,1,-16,-16)"><path fill="rgba(34,126,255,1)" d="M 0,0 l 32,0 l 0,32 l-32 0 z" r="16" stroke-width="0" width="32" height="32"/></g></g><g fill="none" transform="matrix(1,0,0,1,350,100)"><g transform="matrix(1,0,0,1,0,0)"><ellipse fill="rgba(34,126,255,1)" transform="translate(-30,-20)" cx="30" cy="20" r="16" stroke-width="0" rx="30" ry="20"/></g></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" style="background: transparent; position: fixed; outline: none;" color-interpolation-filters="sRGB" tabindex="1"><defs/><g transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" stroke="transparent" stroke-width="01"/><g fill="none" transform="matrix(1,0,0,1,0,0)"/><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,106.122932,106.122932)"><path fill="none" d="M 8.659137602339158,0 C 67.78742768306151 24.491739671365735,24.491739671365735 67.78742768306151,0 8.659137602339158 L 1.913417161825448,13.278535264895591" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 5.902270540571408,44.346217560541774 C -18.589469130794328 -14.782072520180591,42.63988004762001 -14.782072520180591,18.148140376254275 44.346217560541774 L 20.061557538079725,39.72681989798534" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(0.382683,0.923880,-0.923880,0.382683,1.913417,13.278535)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,208,108)"><path fill="none" d="M 8,0 C 65.24334022399461 28.621670111997304,28.621670111997304 65.24334022399461,0 8 L 2.2360679774997902,12.47213595499958" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 6.766454082410348,42.932505167995956 C -21.855216029586956 -14.310835055998652,51.38812419440765 -14.310835055998652,22.76645408241035 42.932505167995956 L 25.002522059910138,38.460369212996376" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(0.447214,0.894427,-0.894427,0.447214,2.236068,12.472136)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,361.480499,107.653671)"><path fill="none" d="M 16.235883004385926,0 C 131.9066814580799 31.941608993363275,63.3299433171083 112.75192737657898,0 10.823922002923936 L 2.6387476382128456,15.07092222682623" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 15.984408254141556,76.44600403024128 C -47.345535062966746 -25.48200134341376,102.2753575131552 -25.48200134341376,38.9454141960469 76.44600403024128 L 41.584161834259746,72.199003806339" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(0.527750,0.849400,-0.849400,0.527750,2.638748,15.070922)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,100,100)"><g transform="matrix(1,0,0,1,0,0)"><circle fill="rgba(34,126,255,1)" transform="translate(-16,-16)" cx="16" cy="16" r="16" stroke-width="0"/></g></g><g fill="none" transform="matrix(1,0,0,1,200,100)"><g transform="matrix(1,0,0,1,-16,-16)"><path fill="rgba(34,126,255,1)" d="M 0,0 l 32,0 l 0,32 l-32 0 z" r="16" stroke-width="0" width="32" height="32"/></g></g><g fill="none" transform="matrix(1,0,0,1,350,100)"><g transform="matrix(1,0,0,1,0,0)"><ellipse fill="rgba(34,126,255,1)" transform="translate(-30,-20)" cx="30" cy="20" r="16" stroke-width="0" rx="30" ry="20"/></g></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" style="background: transparent; position: fixed; outline: none;" color-interpolation-filters="sRGB" tabindex="1"><defs/><g transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" stroke="transparent" stroke-width="01"/><g fill="none" transform="matrix(1,0,0,1,0,0)"/><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,87.974792,114.782074)"><path fill="none" d="M 18.14814037625426,0 C 42.63988004762 59.12829008072235,-18.589469130794342 59.12829008072235,5.9022705405713936 0 L 3.988853378745945,4.619397662556434" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 5.902270540571408,44.346217560541774 C -18.589469130794328 -14.782072520180591,42.63988004762001 -14.782072520180591,18.148140376254275 44.346217560541774 L 20.061557538079725,39.72681989798534" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(-0.382683,0.923880,-0.923880,-0.382683,3.988853,4.619398)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,185.233551,116)"><path fill="none" d="M 22.76645408241032,0 C 51.388124194407624 57.24334022399461,-21.855216029586984 57.24334022399461,6.76645408241032 0 L 4.53038610491053,4.47213595499958" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 6.766454082410348,42.932505167995956 C -21.855216029586956 -14.310835055998652,51.38812419440765 -14.310835055998652,22.76645408241035 42.932505167995956 L 25.002522059910138,38.460369212996376" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(-0.447214,0.894427,-0.894427,-0.447214,4.530386,4.472136)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,322.535095,118.477592)"><path fill="none" d="M 38.94541419604684,0 C 102.27535751315514 101.92800537365504,-47.3455350629668 101.92800537365504,15.9844082541415 0 L 13.34566061592865,4.247000223902292" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 15.984408254141556,76.44600403024128 C -47.345535062966746 -25.48200134341376,102.2753575131552 -25.48200134341376,38.9454141960469 76.44600403024128 L 41.584161834259746,72.199003806339" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(-0.527749,0.849400,-0.849400,-0.527749,13.345660,4.247000)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,100,100)"><g transform="matrix(1,0,0,1,0,0)"><circle fill="rgba(34,126,255,1)" transform="translate(-16,-16)" cx="16" cy="16" r="16" stroke-width="0"/></g></g><g fill="none" transform="matrix(1,0,0,1,200,100)"><g transform="matrix(1,0,0,1,-16,-16)"><path fill="rgba(34,126,255,1)" d="M 0,0 l 32,0 l 0,32 l-32 0 z" r="16" stroke-width="0" width="32" height="32"/></g></g><g fill="none" transform="matrix(1,0,0,1,350,100)"><g transform="matrix(1,0,0,1,0,0)"><ellipse fill="rgba(34,126,255,1)" transform="translate(-30,-20)" cx="30" cy="20" r="16" stroke-width="0" rx="30" ry="20"/></g></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" style="background: transparent; position: fixed; outline: none;" color-interpolation-filters="sRGB" tabindex="1"><defs/><g transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" stroke="transparent" stroke-width="01"/><g fill="none" transform="matrix(1,0,0,1,0,0)"/><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,87.974792,40.871712)"><path fill="none" d="M 18.14814037625426,44.346217560541774 C 42.63988004762 -14.782072520180591,-18.589469130794342 -14.782072520180591,5.9022705405713936 44.346217560541774 L 3.988853378745945,39.72681989798534" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 5.902270540571408,44.346217560541774 C -18.589469130794328 -14.782072520180591,42.63988004762001 -14.782072520180591,18.148140376254275 44.346217560541774 L 20.061557538079725,39.72681989798534" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(-0.382683,-0.923880,0.923880,-0.382683,3.988853,39.726818)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,185.233551,41.067493)"><path fill="none" d="M 22.76645408241032,42.932505167995956 C 51.388124194407624 -14.310835055998652,-21.855216029586984 -14.310835055998652,6.76645408241032 42.932505167995956 L 4.53038610491053,38.460369212996376" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 6.766454082410348,42.932505167995956 C -21.855216029586956 -14.310835055998652,51.38812419440765 -14.310835055998652,22.76645408241035 42.932505167995956 L 25.002522059910138,38.460369212996376" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(-0.447214,-0.894427,0.894427,-0.447214,4.530386,38.460369)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,322.535095,5.076406)"><path fill="none" d="M 38.94541419604684,76.44600403024128 C 102.27535751315514 -25.48200134341376,-47.3455350629668 -25.48200134341376,15.9844082541415 76.44600403024128 L 13.34566061592865,72.199003806339" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 15.984408254141556,76.44600403024128 C -47.345535062966746 -25.48200134341376,102.2753575131552 -25.48200134341376,38.9454141960469 76.44600403024128 L 41.584161834259746,72.199003806339" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(-0.527749,-0.849400,0.849400,-0.527749,13.345660,72.199005)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,100,100)"><g transform="matrix(1,0,0,1,0,0)"><circle fill="rgba(34,126,255,1)" transform="translate(-16,-16)" cx="16" cy="16" r="16" stroke-width="0"/></g></g><g fill="none" transform="matrix(1,0,0,1,200,100)"><g transform="matrix(1,0,0,1,-16,-16)"><path fill="rgba(34,126,255,1)" d="M 0,0 l 32,0 l 0,32 l-32 0 z" r="16" stroke-width="0" width="32" height="32"/></g></g><g fill="none" transform="matrix(1,0,0,1,350,100)"><g transform="matrix(1,0,0,1,0,0)"><ellipse fill="rgba(34,126,255,1)" transform="translate(-30,-20)" cx="30" cy="20" r="16" stroke-width="0" rx="30" ry="20"/></g></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" style="background: transparent; position: fixed; outline: none;" color-interpolation-filters="sRGB" tabindex="1"><defs/><g transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" stroke="transparent" stroke-width="01"/><g fill="none" transform="matrix(1,0,0,1,0,0)"/><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,84.074188,15.926963)"><path fill="none" d="M 9.802874705427428,69.29096493834652 C -28.465468531081534 -23.096988312782173,60.317087777619264 -23.096988312782173,22.048744541110295 69.29096493834652 L 23.962161702935745,64.67156727579008" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 5.902270540571408,44.346217560541774 C -18.589469130794328 -14.782072520180591,42.63988004762001 -14.782072520180591,18.148140376254275 44.346217560541774 L 20.061557538079725,39.72681989798534" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(0.382683,-0.923880,0.923880,0.382683,23.962162,64.671570)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,180.693695,16.917961)"><path fill="none" d="M 11.306306948953136,67.08203932499369 C -33.415052601042646 -22.360679774997894,72.02766649894892 -22.360679774997894,27.306306948953136 67.08203932499369 L 29.542374926452926,62.60990336999411" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 6.766454082410348,42.932505167995956 C -21.855216029586956 -14.310835055998652,51.38812419440765 -14.310835055998652,22.76645408241035 42.932505167995956 L 25.002522059910138,38.460369212996376" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(0.447214,-0.894427,0.894427,0.447214,29.542376,62.609905)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,325.523956,17.817406)"><path fill="none" d="M 12.995540996018917,63.7050033585344 C -39.77941176823799 -21.235001119511466,88.73149970218117 -21.235001119511466,35.95654693792426 63.7050033585344 L 38.59529457613711,59.45800313463211" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 15.984408254141556,76.44600403024128 C -47.345535062966746 -25.48200134341376,102.2753575131552 -25.48200134341376,38.9454141960469 76.44600403024128 L 41.584161834259746,72.199003806339" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(0.527750,-0.849400,0.849400,0.527750,38.595295,59.458004)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,100,100)"><g transform="matrix(1,0,0,1,0,0)"><circle fill="rgba(34,126,255,1)" transform="translate(-16,-16)" cx="16" cy="16" r="16" stroke-width="0"/></g></g><g fill="none" transform="matrix(1,0,0,1,200,100)"><g transform="matrix(1,0,0,1,-16,-16)"><path fill="rgba(34,126,255,1)" d="M 0,0 l 32,0 l 0,32 l-32 0 z" r="16" stroke-width="0" width="32" height="32"/></g></g><g fill="none" transform="matrix(1,0,0,1,350,100)"><g transform="matrix(1,0,0,1,0,0)"><ellipse fill="rgba(34,126,255,1)" transform="translate(-30,-20)" cx="30" cy="20" r="16" stroke-width="0" rx="30" ry="20"/></g></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" style="background: transparent; position: fixed; outline: none;" color-interpolation-filters="sRGB" tabindex="1"><defs/><g transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" stroke="transparent" stroke-width="01"/><g fill="none" transform="matrix(1,0,0,1,0,0)"/><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,40.871712,87.974792)"><path fill="none" d="M 44.346217560541774,18.14814037625426 C -14.782072520180591 42.63988004762,-14.782072520180591 -18.589469130794342,44.346217560541774 5.9022705405713936 L 39.72681989798534,3.9888533787459464" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 5.902270540571408,44.346217560541774 C -18.589469130794328 -14.782072520180591,42.63988004762001 -14.782072520180591,18.148140376254275 44.346217560541774 L 20.061557538079725,39.72681989798534" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(-0.923880,-0.382683,0.382683,-0.923880,39.726818,3.988853)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,141.067490,85.233543)"><path fill="none" d="M 42.93250516799594,22.76645408241032 C -14.310835055998666 51.388124194407624,-14.310835055998666 -21.855216029586984,42.93250516799594 6.76645408241032 L 38.46036921299636,4.530386104910529" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 6.766454082410348,42.932505167995956 C -21.855216029586956 -14.310835055998652,51.38812419440765 -14.310835055998652,22.76645408241035 42.932505167995956 L 25.002522059910138,38.460369212996376" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(-0.894427,-0.447214,0.447214,-0.894427,38.460369,4.530386)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,235.530518,84.595833)"><path fill="none" d="M 86.75309884027052,23.057838889610196 C -28.91769961342348 54.99944788297347,-28.91769961342348 -24.191107398356685,86.75309884027052 7.750501595006597 L 81.93348223803328,6.419601220283127" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 15.984408254141556,76.44600403024128 C -47.345535062966746 -25.48200134341376,102.2753575131552 -25.48200134341376,38.9454141960469 76.44600403024128 L 41.584161834259746,72.199003806339" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(-0.963923,-0.266180,0.266180,-0.963923,81.933479,6.419601)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,100,100)"><g transform="matrix(1,0,0,1,0,0)"><circle fill="rgba(34,126,255,1)" transform="translate(-16,-16)" cx="16" cy="16" r="16" stroke-width="0"/></g></g><g fill="none" transform="matrix(1,0,0,1,200,100)"><g transform="matrix(1,0,0,1,-16,-16)"><path fill="rgba(34,126,255,1)" d="M 0,0 l 32,0 l 0,32 l-32 0 z" r="16" stroke-width="0" width="32" height="32"/></g></g><g fill="none" transform="matrix(1,0,0,1,350,100)"><g transform="matrix(1,0,0,1,0,0)"><ellipse fill="rgba(34,126,255,1)" transform="translate(-30,-20)" cx="30" cy="20" r="16" stroke-width="0" rx="30" ry="20"/></g></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" style="background: transparent; position: fixed; outline: none;" color-interpolation-filters="sRGB" tabindex="1"><defs/><g transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" stroke="transparent" stroke-width="01"/><g fill="none" transform="matrix(1,0,0,1,0,0)"/><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,114.782074,87.974792)"><path fill="none" d="M 0,5.902270540571408 C 59.12829008072235 -18.589469130794328,59.12829008072235 42.63988004762001,0 18.148140376254275 L 4.619397662556434,20.061557538079725" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 5.902270540571408,44.346217560541774 C -18.589469130794328 -14.782072520180591,42.63988004762001 -14.782072520180591,18.148140376254275 44.346217560541774 L 20.061557538079725,39.72681989798534" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(0.923880,0.382683,-0.382683,0.923880,4.619398,20.061558)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,216,85.233543)"><path fill="none" d="M 0,6.76645408241032 C 57.24334022399461 -21.855216029586984,57.24334022399461 51.388124194407624,0 22.76645408241032 L 4.47213595499958,25.00252205991011" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 6.766454082410348,42.932505167995956 C -21.855216029586956 -14.310835055998652,51.38812419440765 -14.310835055998652,22.76645408241035 42.932505167995956 L 25.002522059910138,38.460369212996376" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(0.894427,0.447214,-0.447214,0.894427,4.472136,25.002522)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,377.716400,84.595833)"><path fill="none" d="M 0,7.7505015950065825 C 115.67079845369398 -24.1911073983567,115.67079845369398 54.999447882973456,0 23.05783888961018 L 4.819616602237249,24.38873926433365" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 15.984408254141556,76.44600403024128 C -47.345535062966746 -25.48200134341376,102.2753575131552 -25.48200134341376,38.9454141960469 76.44600403024128 L 41.584161834259746,72.199003806339" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(0.963923,0.266180,-0.266180,0.963923,4.819617,24.388739)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,100,100)"><g transform="matrix(1,0,0,1,0,0)"><circle fill="rgba(34,126,255,1)" transform="translate(-16,-16)" cx="16" cy="16" r="16" stroke-width="0"/></g></g><g fill="none" transform="matrix(1,0,0,1,200,100)"><g transform="matrix(1,0,0,1,-16,-16)"><path fill="rgba(34,126,255,1)" d="M 0,0 l 32,0 l 0,32 l-32 0 z" r="16" stroke-width="0" width="32" height="32"/></g></g><g fill="none" transform="matrix(1,0,0,1,350,100)"><g transform="matrix(1,0,0,1,0,0)"><ellipse fill="rgba(34,126,255,1)" transform="translate(-30,-20)" cx="30" cy="20" r="16" stroke-width="0" rx="30" ry="20"/></g></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" style="background: transparent; position: fixed; outline: none;" color-interpolation-filters="sRGB" tabindex="1"><defs/><g transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" stroke="transparent" stroke-width="01"/><g fill="none" transform="matrix(1,0,0,1,0,0)"/><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,55.510433,55.510433)"><path fill="none" d="M 29.707494974932892,38.36663257727206 C -29.420795105789473 13.874892905906322,13.874892905906314 -29.420795105789466,38.36663257727205 29.7074949749329 L 36.4532154154466,25.088097312376465" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 5.902270540571408,44.346217560541774 C -18.589469130794328 -14.782072520180591,42.63988004762001 -14.782072520180591,18.148140376254275 44.346217560541774 L 20.061557538079725,39.72681989798534" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(-0.382683,-0.923880,0.923880,-0.382683,36.453217,25.088097)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,153.810211,53.810211)"><path fill="none" d="M 30.1897870448679,38.18978704486787 C -27.05355317912671 9.568116932870566,9.568116932870595 -27.053553179126737,38.1897870448679 30.18978704486787 L 35.95371906736811,25.71765108986829" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 6.766454082410348,42.932505167995956 C -21.855216029586956 -14.310835055998652,51.38812419440765 -14.310835055998652,22.76645408241035 42.932505167995956 L 25.002522059910138,38.460369212996376" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(-0.447214,-0.894427,0.894427,-0.447214,35.953720,25.717651)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,259.776184,31.681915)"><path fill="none" d="M 62.507439069740485,60.6644152119956 C -53.16335938395352 28.72280621863232,15.413378757018108 -52.08751216458337,78.74332207412641 49.84049320907167 L 76.10457443591356,45.59349298516938" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 15.984408254141556,76.44600403024128 C -47.345535062966746 -25.48200134341376,102.2753575131552 -25.48200134341376,38.9454141960469 76.44600403024128 L 41.584161834259746,72.199003806339" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(-0.527749,-0.849400,0.849400,-0.527749,76.104576,45.593494)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,100,100)"><g transform="matrix(1,0,0,1,0,0)"><circle fill="rgba(34,126,255,1)" transform="translate(-16,-16)" cx="16" cy="16" r="16" stroke-width="0"/></g></g><g fill="none" transform="matrix(1,0,0,1,200,100)"><g transform="matrix(1,0,0,1,-16,-16)"><path fill="rgba(34,126,255,1)" d="M 0,0 l 32,0 l 0,32 l-32 0 z" r="16" stroke-width="0" width="32" height="32"/></g></g><g fill="none" transform="matrix(1,0,0,1,350,100)"><g transform="matrix(1,0,0,1,0,0)"><ellipse fill="rgba(34,126,255,1)" transform="translate(-30,-20)" cx="30" cy="20" r="16" stroke-width="0" rx="30" ry="20"/></g></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" style="background: transparent; position: fixed; outline: none;" color-interpolation-filters="sRGB" tabindex="1"><defs/><g transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" stroke="transparent" stroke-width="01"/><g fill="none" transform="matrix(1,0,0,1,0,0)"/><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,106.122932,55.510433)"><path fill="none" d="M 0,29.707494974932892 C 24.491739671365735 -29.420795105789473,67.78742768306151 13.874892905906314,8.659137602339158 38.36663257727205 L 13.278535264895591,36.4532154154466" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 5.902270540571408,44.346217560541774 C -18.589469130794328 -14.782072520180591,42.63988004762001 -14.782072520180591,18.148140376254275 44.346217560541774 L 20.061557538079725,39.72681989798534" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(0.923880,-0.382683,0.382683,0.923880,13.278535,36.453217)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,208,53.810211)"><path fill="none" d="M 0,30.189787044867863 C 28.621670111997304 -27.053553179126745,65.24334022399461 9.56811693287056,8 38.18978704486786 L 12.47213595499958,35.95371906736807" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 6.766454082410348,42.932505167995956 C -21.855216029586956 -14.310835055998652,51.38812419440765 -14.310835055998652,22.76645408241035 42.932505167995956 L 25.002522059910138,38.460369212996376" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(0.894427,-0.447214,0.447214,0.894427,12.472136,35.953720)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,361.480499,31.681915)"><path fill="none" d="M 0,49.840493209071674 C 63.3299433171083 -52.087512164583366,131.9066814580799 28.72280621863233,16.235883004385926 60.66441521199561 L 21.055499606623176,59.33351483727214" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 15.984408254141556,76.44600403024128 C -47.345535062966746 -25.48200134341376,102.2753575131552 -25.48200134341376,38.9454141960469 76.44600403024128 L 41.584161834259746,72.199003806339" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(0.963923,-0.266180,0.266180,0.963923,21.055500,59.333515)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,100,100)"><g transform="matrix(1,0,0,1,0,0)"><circle fill="rgba(34,126,255,1)" transform="translate(-16,-16)" cx="16" cy="16" r="16" stroke-width="0"/></g></g><g fill="none" transform="matrix(1,0,0,1,200,100)"><g transform="matrix(1,0,0,1,-16,-16)"><path fill="rgba(34,126,255,1)" d="M 0,0 l 32,0 l 0,32 l-32 0 z" r="16" stroke-width="0" width="32" height="32"/></g></g><g fill="none" transform="matrix(1,0,0,1,350,100)"><g transform="matrix(1,0,0,1,0,0)"><ellipse fill="rgba(34,126,255,1)" transform="translate(-30,-20)" cx="30" cy="20" r="16" stroke-width="0" rx="30" ry="20"/></g></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" style="background: transparent; position: fixed; outline: none;" color-interpolation-filters="sRGB" tabindex="1"><defs/><g transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" stroke="transparent" stroke-width="01"/><g fill="none" transform="matrix(1,0,0,1,0,0)"/><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,87.974792,40.871712)"><path fill="none" d="M 5.902270540571408,44.346217560541774 C -18.589469130794328 -14.782072520180591,42.63988004762001 -14.782072520180591,18.148140376254275 44.346217560541774 L 20.061557538079725,39.72681989798534" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 5.902270540571408,44.346217560541774 C -18.589469130794328 -14.782072520180591,42.63988004762001 -14.782072520180591,18.148140376254275 44.346217560541774 L 20.061557538079725,39.72681989798534" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(0.382683,-0.923880,0.923880,0.382683,20.061558,39.726818)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,185.233551,41.067493)"><path fill="none" d="M 6.766454082410348,42.932505167995956 C -21.855216029586956 -14.310835055998652,51.38812419440765 -14.310835055998652,22.76645408241035 42.932505167995956 L 25.002522059910138,38.460369212996376" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 6.766454082410348,42.932505167995956 C -21.855216029586956 -14.310835055998652,51.38812419440765 -14.310835055998652,22.76645408241035 42.932505167995956 L 25.002522059910138,38.460369212996376" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(0.447214,-0.894427,0.894427,0.447214,25.002522,38.460369)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g transform="matrix(1,0,0,1,322.535095,5.076406)"><path fill="none" d="M 15.984408254141556,76.44600403024128 C -47.345535062966746 -25.48200134341376,102.2753575131552 -25.48200134341376,38.9454141960469 76.44600403024128 L 41.584161834259746,72.199003806339" stroke-width="1" stroke="rgba(153,173,209,1)" marker-end="[object Object]"/><path fill="none" d="M 15.984408254141556,76.44600403024128 C -47.345535062966746 -25.48200134341376,102.2753575131552 -25.48200134341376,38.9454141960469 76.44600403024128 L 41.584161834259746,72.199003806339" stroke-width="3" stroke="transparent" marker-end="[object Object]"/><g transform="matrix(0.527750,-0.849400,0.849400,0.527750,41.584164,72.199005)"><path fill="rgba(153,173,209,1)" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="1" stroke="rgba(153,173,209,1)"/><path fill="transparent" d="M 0,5 L 10,0 L 10,10 Z" transform="translate(-5,-5)" stroke-width="7" stroke="transparent"/></g></g></g></g><g fill="none" transform="matrix(1,0,0,1,0,0)"><g fill="none" transform="matrix(1,0,0,1,100,100)"><g transform="matrix(1,0,0,1,0,0)"><circle fill="rgba(34,126,255,1)" transform="translate(-16,-16)" cx="16" cy="16" r="16" stroke-width="0"/></g></g><g fill="none" transform="matrix(1,0,0,1,200,100)"><g transform="matrix(1,0,0,1,-16,-16)"><path fill="rgba(34,126,255,1)" d="M 0,0 l 32,0 l 0,32 l-32 0 z" r="16" stroke-width="0" width="32" height="32"/></g></g><g fill="none" transform="matrix(1,0,0,1,350,100)"><g transform="matrix(1,0,0,1,0,0)"><ellipse fill="rgba(34,126,255,1)" transform="translate(-30,-20)" cx="30" cy="20" r="16" stroke-width="0" rx="30" ry="20"/></g></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 4.1 KiB