feat: ✨ add primer
and useForeignObject
option for react-shape
primer: basic svg shape for calc connection point, useForeignObject: support render react component to svg `g` element
This commit is contained in:
@ -25,6 +25,7 @@ class MyComponent extends React.Component<{ node?: Node; text: string }> {
|
||||
height: '100%',
|
||||
textAlign: 'center',
|
||||
lineHeight: '60px',
|
||||
borderRadius: 30,
|
||||
background: color,
|
||||
}}
|
||||
>
|
||||
@ -46,9 +47,10 @@ export default class Example extends React.Component {
|
||||
|
||||
const source = graph.addNode({
|
||||
shape: 'react-shape',
|
||||
primer: 'circle',
|
||||
x: 80,
|
||||
y: 80,
|
||||
width: 160,
|
||||
width: 60,
|
||||
height: 60,
|
||||
data: {},
|
||||
xxx: {},
|
||||
@ -59,14 +61,31 @@ export default class Example extends React.Component {
|
||||
shape: 'react-shape',
|
||||
x: 320,
|
||||
y: 320,
|
||||
width: 160,
|
||||
height: 60,
|
||||
width: 120,
|
||||
height: 48,
|
||||
component: (node) => {
|
||||
return <div>{node.attr('body/fill')}</div>
|
||||
return (
|
||||
<div style={{ lineHeight: '48px', textAlign: 'center' }}>
|
||||
{node.attr('body/fill')}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
// component: () => <Test text="target" />,
|
||||
})
|
||||
|
||||
graph.addNode({
|
||||
shape: 'react-shape',
|
||||
primer: 'circle',
|
||||
x: 80,
|
||||
y: 320,
|
||||
width: 60,
|
||||
height: 60,
|
||||
useForeignObject: false,
|
||||
component: () => {
|
||||
return <circle stroke="red" cx="30" cy="30" r="30"/>
|
||||
},
|
||||
})
|
||||
|
||||
graph.addEdge({
|
||||
source,
|
||||
target,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Node, Markup } from '@antv/x6'
|
||||
import { Node, Markup, ObjectExt } from '@antv/x6'
|
||||
import { Definition } from './registry'
|
||||
|
||||
export class ReactShape<
|
||||
@ -35,27 +35,50 @@ export class ReactShape<
|
||||
}
|
||||
|
||||
export namespace ReactShape {
|
||||
export type Primer =
|
||||
| 'rect'
|
||||
| 'circle'
|
||||
| 'path'
|
||||
| 'ellipse'
|
||||
| 'polygon'
|
||||
| 'polyline'
|
||||
|
||||
export interface Properties extends Node.Properties {
|
||||
primer?: Primer
|
||||
useForeignObject?: boolean
|
||||
component?: Definition | string
|
||||
}
|
||||
}
|
||||
|
||||
export namespace ReactShape {
|
||||
ReactShape.config({
|
||||
view: 'react-shape-view',
|
||||
markup: [
|
||||
function getMarkup(useForeignObject: boolean, primer: Primer = 'rect') {
|
||||
const markup: Markup.JSONMarkup[] = [
|
||||
{
|
||||
tagName: 'rect',
|
||||
tagName: primer,
|
||||
selector: 'body',
|
||||
},
|
||||
{
|
||||
...Markup.getForeignObjectMarkup(),
|
||||
},
|
||||
{
|
||||
tagName: 'text',
|
||||
selector: 'label',
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
if (useForeignObject) {
|
||||
markup.push(Markup.getForeignObjectMarkup())
|
||||
} else {
|
||||
markup.push({
|
||||
tagName: 'g',
|
||||
selector: 'content',
|
||||
})
|
||||
}
|
||||
|
||||
markup.push({
|
||||
tagName: 'text',
|
||||
selector: 'label',
|
||||
})
|
||||
|
||||
return markup
|
||||
}
|
||||
|
||||
ReactShape.config<Properties>({
|
||||
view: 'react-shape-view',
|
||||
markup: getMarkup(true),
|
||||
attrs: {
|
||||
body: {
|
||||
fill: 'none',
|
||||
@ -76,6 +99,46 @@ export namespace ReactShape {
|
||||
textVerticalAnchor: 'middle',
|
||||
},
|
||||
},
|
||||
propHooks(metadata: Properties) {
|
||||
if (metadata.markup == null) {
|
||||
const primer = metadata.primer
|
||||
const useForeignObject = metadata.useForeignObject
|
||||
if (primer != null || useForeignObject != null) {
|
||||
metadata.markup = getMarkup(useForeignObject !== false, primer)
|
||||
if (primer) {
|
||||
if (metadata.attrs == null) {
|
||||
metadata.attrs = {}
|
||||
}
|
||||
let attrs = {}
|
||||
if (primer === 'circle') {
|
||||
attrs = {
|
||||
refCx: '50%',
|
||||
refCy: '50%',
|
||||
refR: '50%',
|
||||
}
|
||||
} else if (primer === 'ellipse') {
|
||||
attrs = {
|
||||
refCx: '50%',
|
||||
refCy: '50%',
|
||||
refRx: '50%',
|
||||
refRy: '50%',
|
||||
}
|
||||
}
|
||||
|
||||
if (primer !== 'rect') {
|
||||
metadata.attrs = ObjectExt.merge({}, metadata.attrs, {
|
||||
body: {
|
||||
refWidth: null,
|
||||
refHeight: null,
|
||||
...attrs,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return metadata
|
||||
},
|
||||
})
|
||||
|
||||
Node.registry.register('react-shape', ReactShape, true)
|
||||
|
@ -14,7 +14,9 @@ export class ReactShapeView extends NodeView<ReactShape> {
|
||||
}
|
||||
|
||||
getComponentContainer() {
|
||||
return this.selectors.foContent as HTMLDivElement
|
||||
return this.cell.prop('useForeignObject') === false
|
||||
? (this.selectors.content as SVGElement)
|
||||
: (this.selectors.foContent as HTMLDivElement)
|
||||
}
|
||||
|
||||
confirmUpdate(flag: number) {
|
||||
|
Reference in New Issue
Block a user