fix(elements): fix incorrect ports position when rotate node

This commit is contained in:
antv 2024-08-01 19:25:42 +08:00
parent 36411e5882
commit bae52457be
3 changed files with 79 additions and 2 deletions

View File

@ -0,0 +1,29 @@
import { createGraph } from '@@/utils';
describe('element port rotate', () => {
it('default', async () => {
const graph = createGraph({
data: {
nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],
},
node: {
type: 'rect',
style: {
size: [50, 150],
port: true,
portR: 3,
ports: [
{ key: 'port-1', placement: [0, 0.15] },
{ key: 'port-2', placement: 'left' },
{ key: 'port-3', placement: [0, 0.85] },
],
transform: 'rotate(45deg)',
},
},
});
await graph.draw();
await expect(graph).toMatchSnapshot(__filename);
});
});

View File

@ -0,0 +1,23 @@
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" style="background: transparent; position: absolute; outline: none;" color-interpolation-filters="sRGB" tabindex="1">
<defs/>
<g >
<g fill="none">
<g fill="none">
<g fill="none" x="100" y="100" transform="matrix(0.707107,0.707107,-0.707107,0.707107,100,100)">
<g>
<path fill="rgba(23,131,255,1)" d="M -25,-75 l 50,0 l 0,150 l-50 0 z" class="key" stroke-width="0" stroke="rgba(0,0,0,1)" width="50" height="150" x="-25" y="-75"/>
</g>
<g transform="matrix(1,0,0,1,-25,-52.500000)">
<circle fill="rgba(23,131,255,1)" class="port-port-1" stroke-width="1" stroke="rgba(0,0,0,1)" stroke-opacity="0.65" r="3"/>
</g>
<g transform="matrix(1,0,0,1,-25,0)">
<circle fill="rgba(23,131,255,1)" class="port-port-2" stroke-width="1" stroke="rgba(0,0,0,1)" stroke-opacity="0.65" r="3"/>
</g>
<g transform="matrix(1,0,0,1,-25,52.500000)">
<circle fill="rgba(23,131,255,1)" class="port-port-3" stroke-width="1" stroke="rgba(0,0,0,1)" stroke-opacity="0.65" r="3"/>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -1,6 +1,7 @@
import type { BaseStyleProps, CircleStyleProps, DisplayObject, DisplayObjectConfig, Group } from '@antv/g';
import { Circle as GCircle } from '@antv/g';
import type { CategoricalPalette } from '../../palettes/types';
import type { RuntimeContext } from '../../runtime/types';
import type { NodeData } from '../../spec';
import type {
BaseElementStyleProps,
@ -24,6 +25,7 @@ import { omitStyleProps, subObject, subStyleProps } from '../../utils/prefix';
import { parseSize } from '../../utils/size';
import { mergeOptions } from '../../utils/style';
import { getWordWrapWidthByBox } from '../../utils/text';
import { setVisibility } from '../../utils/visibility';
import { BaseElement } from '../base-element';
import { effect } from '../effect';
import type { BadgeStyleProps, IconStyleProps, LabelStyleProps } from '../shapes';
@ -328,8 +330,8 @@ export abstract class BaseNode<S extends BaseNodeStyleProps = BaseNodeStyleProps
protected getPortXY(attributes: Required<S>, style: NodePortStyleProps): Point {
const { placement = 'left' } = style;
const bounds = this.getShape('key').getLocalBounds();
return getPortXYByPlacement(bounds, placement as PortPlacement);
const keyShape = this.getShape('key');
return getPortXYByPlacement(getBoundsInOffscreen(this.context, keyShape), placement as PortPlacement);
}
/**
@ -385,6 +387,7 @@ export abstract class BaseNode<S extends BaseNodeStyleProps = BaseNodeStyleProps
@effect((self, attributes) => self.getPortsStyle(attributes))
protected drawPortShapes(attributes: Required<S>, container: Group): void {
const portsStyle = this.getPortsStyle(attributes);
Object.keys(portsStyle).forEach((key) => {
this.upsert(`port-${key}`, GCircle, portsStyle[key] as CircleStyleProps, container);
});
@ -429,3 +432,25 @@ export abstract class BaseNode<S extends BaseNodeStyleProps = BaseNodeStyleProps
this.drawLabelShape(this.parsedAttributes, this);
}
}
/**
*
* @param context
* @param shape
*/
function getBoundsInOffscreen(context: RuntimeContext, shape: DisplayObject) {
if (!context) return shape.getLocalBounds();
// 将主图形靠背至全局空间,避免受到父级 transform 的影响
// 合理的操作应该是靠背至离屏画布,但目前 G 有点问题
// Move the main graphic to the global space to avoid being affected by the parent transform
// The reasonable operation should be moved to the off-screen canvas, but there is a problem with G at present
const canvas = context.canvas.getLayer();
const substitute = shape.cloneNode();
setVisibility(substitute, 'hidden');
canvas.appendChild(substitute);
const bounds = substitute.getLocalBounds();
canvas.removeChild(substitute);
return bounds;
}