test: 🚨 add getMatrixOfElement test demo

This commit is contained in:
vector
2021-04-21 09:46:27 +08:00
parent b978482c28
commit 87958cb494

View File

@ -0,0 +1,346 @@
import React from 'react'
import { Graph, Node, Dom, Rectangle } from '@antv/x6'
import { Button } from 'antd'
import '../index.less'
export default class Example extends React.Component {
private container: HTMLDivElement
private graph: Graph
private source: Node
componentDidMount() {
this.graph = new Graph({
container: this.container,
width: 800,
height: 600,
grid: true,
resizing: true,
rotating: true,
panning: true,
mousewheel: true,
})
this.source = this.graph.addNode({
shape: 'rect',
x: 80,
y: 80,
width: 160,
height: 160,
markup: [
{
tagName: 'rect',
selector: 'shape1',
},
{
tagName: 'rect',
selector: 'shape2',
},
{
tagName: 'rect',
selector: 'shape3',
},
{
tagName: 'circle',
selector: 'shape4',
},
{
tagName: 'circle',
selector: 'shape5',
},
{
tagName: 'text',
selector: 'shape6',
},
{
tagName: 'g',
selector: 'g1',
children: [
{
tagName: 'g',
selector: 'g2',
children: [
{
tagName: 'rect',
selector: 'shape7',
},
],
},
],
},
],
attrs: {
shape1: {
id: 's1',
refWidth: '100%',
refHeight: '100%',
stroke: 'black',
},
shape2: {
id: 's2',
x: 10,
y: 100,
width: 50,
height: 50,
stroke: 'green',
fill: 'transparent',
},
shape3: {
id: 's3',
refX: '50%',
refY: '50%',
refWidth: '50%',
refHeight: '50%',
stroke: 'green',
fill: 'transparent',
},
shape4: {
id: 's4',
cx: 40,
cy: 40,
r: 40,
stroke: 'red',
fill: 'white',
},
shape5: {
id: 's5',
refCx: '50%',
refCy: '50%',
refR: '20%',
stroke: 'red',
fill: 'white',
},
shape6: {
id: 's6',
text: 'text',
},
g1: {
transform: 'matrix(1.2,0,0,1.2,80,80)',
},
g2: {
transform: 'matrix(1,0,0,1,100,100)',
},
shape7: {
id: 's7',
x: 30,
y: 30,
width: 50,
height: 50,
fill: 'yellow',
},
},
ports: {
groups: {
top: {
position: {
name: 'top',
args: {
dx: 10,
dy: -10,
angle: 20,
},
},
attrs: {
circle: {
r: 8,
magnet: true,
stroke: 'red',
strokeWidth: 2,
fill: '#fff',
id: 's8',
},
},
},
right: {
position: {
name: 'absolute',
args: { x: 50, y: 50 },
},
markup: {
tagName: 'rect',
selector: 'shape9',
attrs: {
x: 50,
y: 50,
width: 30,
height: 30,
fill: '#fff',
stroke: 'blue',
id: 's9',
},
},
},
bottom: {
position: {
name: 'line',
args: {
start: { x: 10, y: 10 },
end: { x: 210, y: 10 },
},
},
attrs: {
circle: {
id: 's10',
},
},
},
},
items: [
{
id: '1',
group: 'top',
},
{
id: '2',
group: 'right',
},
{
id: '3',
group: 'bottom',
},
],
},
})
}
refContainer = (container: HTMLDivElement) => {
this.container = container
}
getMatrixOfElement = (elem: Element, target: Element) => {
let matrix = Dom.createSVGMatrix()
let node = elem
const matrixList = []
while (node && node !== target) {
const transform = node.getAttribute('transform') || null
const nodeMatrix = Dom.transformStringToMatrix(transform)
matrixList.push(nodeMatrix)
node = node.parentElement as Element
}
matrixList.reverse().forEach((m) => {
matrix = matrix.multiply(m)
})
return matrix
}
getBoundingRectOfElement = (elem: Element) => {
let node = elem
let tagName = elem.tagName.toLowerCase()
if (tagName === 'g') {
node = elem.firstElementChild as Element
tagName = node.tagName.toLowerCase()
}
const attr = (name: string) => {
const s = node.getAttribute(name)
const v = s ? parseFloat(s) : 0
return Number.isNaN(v) ? 0 : v
}
let x, y, r, width, height, bbox
switch (tagName) {
case 'rect':
x = attr('x')
y = attr('y')
width = attr('width')
height = attr('height')
bbox = new Rectangle(x, y, width, height)
break
case 'circle':
x = attr('cx')
y = attr('cy')
r = attr('r')
bbox = new Rectangle(x - r, y - r, 2 * r, 2 * r)
break
default:
break
}
return bbox
}
test = () => {
const view = this.graph.findViewByCell(this.source)
const container = view?.container
const q = [
container?.querySelector('#s1')!,
container?.querySelector('#s2')!,
container?.querySelector('#s3')!,
container?.querySelector('#s4')!,
container?.querySelector('#s5')!,
container?.querySelector('#s6')!,
container?.querySelector('#s7')!,
container?.querySelector('#s8')!,
container?.querySelector('#s9')!,
container?.querySelector('#s10')!,
]
const fix = (num: number) => num.toFixed(1)
const isSameMatrix = (matrix1: DOMMatrix, matrix2: DOMMatrix) => {
return (
fix(matrix1.a) === fix(matrix2.a) &&
fix(matrix1.b) === fix(matrix2.b) &&
fix(matrix1.c) === fix(matrix2.c) &&
fix(matrix1.d) === fix(matrix2.d) &&
fix(matrix1.e) === fix(matrix2.e) &&
fix(matrix1.f) === fix(matrix2.f)
)
}
const isSameBounding = (rect1: Rectangle, rect2: Rectangle) => {
return (
fix(rect1.x) === fix(rect2.x) &&
fix(rect1.y) === fix(rect2.y) &&
fix(rect1.width) === fix(rect2.width) &&
fix(rect1.height) === fix(rect2.height)
)
}
// matrix
let s = performance.now()
const oldMatrixList = q.map((item) => view?.getMatrixOfElement(item))
console.log('old getMatrixOfElement spend:', performance.now() - s)
s = performance.now()
const newMatrixList = q.map((item) =>
this.getMatrixOfElement(item, container!),
)
console.log('new getMatrixOfElement spend:', performance.now() - s)
let isSame = oldMatrixList.every((item, index) => {
const martix = newMatrixList[index]
if (item && martix) {
return isSameMatrix(item, martix)
}
return true
})
console.log(`getMatrixOfElement test ${isSame ? 'success' : 'failed'}`)
// bounding
s = performance.now()
const oldBoundingList = q.map((item) =>
view?.getBoundingRectOfElement(item),
)
console.log('old getBoundingRectOfElement spend:', performance.now() - s)
s = performance.now()
const newBoundingList = q.map((item) => this.getBoundingRectOfElement(item))
console.log('new getBoundingRectOfElement spend:', performance.now() - s)
isSame = oldBoundingList.every((item, index) => {
const bounding = newBoundingList[index]
if (item && bounding) {
return isSameBounding(item, bounding)
}
return true
})
console.log(
`getBoundingRectOfElement test ${isSame ? 'success' : 'failed'}`,
)
}
render() {
return (
<div className="x6-graph-wrap">
<div ref={this.refContainer} className="x6-graph" />
<Button onClick={this.test}>Test</Button>
</div>
)
}
}