Skip to content

Commit

Permalink
Merge bbfc507 into b8d20a4
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaoiver committed Jul 25, 2022
2 parents b8d20a4 + bbfc507 commit 933947d
Show file tree
Hide file tree
Showing 35 changed files with 1,755 additions and 630 deletions.
28 changes: 6 additions & 22 deletions packages/g-plugin-dragndrop/src/DragndropPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import type {
RenderingService,
} from '@antv/g';
import {
Element,
inject,
RenderingContext,
RenderingPluginContribution,
Expand All @@ -29,19 +28,6 @@ export class DragndropPlugin implements RenderingPlugin {
@inject(DragndropPluginOptions)
private dragndropPluginOptions: DragndropPluginOptions;

private findClosestDraggable(event: FederatedPointerEvent) {
const composedPath = event.composedPath();

for (let i = 0; i < composedPath.length; i++) {
const target = composedPath[i] as Element;
if (Element.isElement(target) && target.getAttribute('draggable')) {
return target;
}
}

return null;
}

apply(renderingService: RenderingService) {
const document = this.renderingContext.root.ownerDocument;

Expand All @@ -60,7 +46,7 @@ export class DragndropPlugin implements RenderingPlugin {
const isDocument = (target as unknown as IDocument) === document;

const draggableEventTarget =
isDocument && isDocumentDraggable ? document : this.findClosestDraggable(event);
isDocument && isDocumentDraggable ? document : target?.closest('[draggable=true]');

// `draggable` may be set on ancestor nodes:
// @see https://github.com/antvis/G/issues/1088
Expand Down Expand Up @@ -105,17 +91,15 @@ export class DragndropPlugin implements RenderingPlugin {
lastDragClientCoordinates = [event.clientX, event.clientY];

if (!isDocument) {
// prevent from picking the dragging element
const pointerEventsOldValue = target.style.pointerEvents;
target.style.pointerEvents = 'none';

const point =
overlap === 'pointer' ? [event.canvasX, event.canvasY] : target.getBounds().center;
const elemBelow = await document.elementFromPoint(point[0], point[1]);
target.style.pointerEvents = pointerEventsOldValue;
const elementsBelow = await document.elementsFromPoint(point[0], point[1]);

// prevent from picking the dragging element
const elementBelow = elementsBelow[elementsBelow.indexOf(target) + 1];

const droppableBelow =
elemBelow?.closest('[droppable=true]') || (isDocumentDroppable ? document : null);
elementBelow?.closest('[droppable=true]') || (isDocumentDroppable ? document : null);
if (currentDroppable !== droppableBelow) {
if (currentDroppable) {
// null when we were not over a droppable before this event
Expand Down
2 changes: 2 additions & 0 deletions packages/g/src/__tests__/canvas.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ describe('Canvas', () => {
expect(e.viewportY).to.almost.eqls(100 - top);
expect(e.canvasX).to.almost.eqls(100 - left);
expect(e.canvasY).to.almost.eqls(100 - top);
expect(e.x).to.almost.eqls(100 - left);
expect(e.y).to.almost.eqls(100 - top);

const viewport = canvas.canvas2Viewport({ x: e.canvasX, y: e.canvasY });

Expand Down
18 changes: 16 additions & 2 deletions packages/g/src/display-objects/DisplayObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,15 +214,29 @@ export class DisplayObject<
});
}

cloneNode(deep?: boolean): this {
cloneNode(deep?: boolean, customCloneFunc?: (name: string, attribute: any) => any): this {
const clonedStyle = { ...this.attributes };
for (const attributeName in clonedStyle) {
const attribute = clonedStyle[attributeName];

// @see https://github.com/antvis/G/issues/1095
if (attribute instanceof DisplayObject) {
clonedStyle[attributeName] = attribute.cloneNode(deep);
}
// TODO: clone other type
if (customCloneFunc) {
clonedStyle[attributeName] = customCloneFunc(attributeName, attribute);
}
}

const cloned = new (this.constructor as ConstructorTypeOf<DisplayObject>)({
// copy id & name
// @see https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode#notes
id: this.id,
name: this.name,
className: this.name,
interactive: this.interactive,
style: { ...this.attributes },
style: clonedStyle,
});

// apply transform
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ interface BProps extends BaseCustomElementStyleProps {
}

describe('CustomElement', () => {
afterEach(() => {
canvas.removeChildren();
});

afterAll(() => {
canvas.destroy();
});

it('should create custom element correctly.', async () => {
const connectedCallback = sinon.spy();
const disconnectedCallback = sinon.spy();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { DisplayObject, Group, Shape } from '@antv/g';
import type { BaseCustomElementStyleProps, DisplayObjectConfig } from '@antv/g';
import { Canvas, Circle, CustomElement, DisplayObject, Group, Shape } from '@antv/g';
import { Renderer as CanvasRenderer } from '@antv/g-canvas';
import chai, { expect } from 'chai';
// @ts-ignore
import chaiAlmost from 'chai-almost';
Expand All @@ -9,7 +11,28 @@ import sinonChai from 'sinon-chai';
chai.use(chaiAlmost());
chai.use(sinonChai);

const $container = document.createElement('div');
$container.id = 'container';
document.body.prepend($container);

const renderer = new CanvasRenderer();
// create a canvas
const canvas = new Canvas({
container: 'container',
width: 600,
height: 500,
renderer,
});

describe('DisplayObject Node API', () => {
afterEach(() => {
canvas.removeChildren();
});

afterAll(() => {
canvas.destroy();
});

it('should update transform with its parent group', () => {
const group1 = new DisplayObject({});
const group2 = new DisplayObject({});
Expand Down Expand Up @@ -325,4 +348,65 @@ describe('DisplayObject Node API', () => {
expect(cloned.children[0].style.fontSize).to.be.eqls(group2.style.fontSize);
expect(cloned.children[0].style.transform).to.be.eqls(group2.style.transform);
});

it('should (deep) cloneNode for custom elements correctly', async () => {
interface AProps extends BaseCustomElementStyleProps {
size: number;
circle: Circle;
}
class ElementA extends CustomElement<AProps> {
constructor(options: DisplayObjectConfig<AProps>) {
super(options);
}
connectedCallback() {
const { circle } = this.style;
this.appendChild(circle);
}
disconnectedCallback() {}
attributeChangedCallback<Key extends never>(
name: Key,
oldValue: {}[Key],
newValue: {}[Key],
) {}
}

await canvas.ready;

const circle = new Circle({
name: 'testname',
id: 'testid',
className: 'testclassname',
style: {
fill: 'red',
r: 10,
},
});
const a = new ElementA({
style: {
size: 10,
circle,
},
});

// before appending to canvas
let cloned = a.cloneNode(true);
expect(cloned.style.size).to.be.eqls(10);
expect(cloned.style.circle).to.be.not.eql(circle);
expect(cloned.style.circle.entity).to.be.not.eql(circle.entity);
expect(cloned.childNodes.length).to.be.eqls(0);

// after appending to canvas
canvas.appendChild(a);
cloned = a.cloneNode(true);

expect(cloned.style.size).to.be.eqls(10);
expect(cloned.style.circle).to.be.not.eql(circle);
expect(cloned.style.circle.entity).to.be.not.eql(circle.entity);
expect(cloned.childNodes.length).to.be.eqls(1);
expect((cloned.childNodes[0] as Circle).name).to.be.eqls('testname');
expect((cloned.childNodes[0] as Circle).id).to.be.eqls('testid');
expect((cloned.childNodes[0] as Circle).className).to.be.eqls('testclassname');
expect((cloned.childNodes[0] as Circle).style.fill).to.be.eqls('red');
expect((cloned.childNodes[0] as Circle).style.r).to.be.eqls(10);
});
});
6 changes: 0 additions & 6 deletions packages/g/src/dom/FederatedMouseEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,6 @@ export class FederatedMouseEvent
get clientY(): number {
return this.client.y;
}
get x(): number {
return this.clientX;
}
get y(): number {
return this.clientY;
}

/**
* The movement in this pointer relative to the last `mousemove` event.
Expand Down
1 change: 1 addition & 0 deletions packages/g/src/plugins/PrepareRendererPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ export class PrepareRendererPlugin implements RenderingPlugin {
// @see https://github.com/mourner/rbush#bulk-inserting-data
this.rBush.load(bulk);

bulk.length = 0;
this.toSync.clear();
}
}
41 changes: 27 additions & 14 deletions packages/g/src/services/SceneGraphService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,24 +320,28 @@ export class DefaultSceneGraphService implements SceneGraphService {
*/
setPosition = (() => {
const parentInvertMatrix = mat4.create();
const tmpPosition = vec3.create();

return (element: INode, position: vec3 | vec2) => {
const transform = (element as Element).transformable;
position = vec3.fromValues(position[0], position[1], position[2] || 0);

if (vec3.equals(this.getPosition(element), position)) {
tmpPosition[0] = position[0];
tmpPosition[1] = position[1];
tmpPosition[2] = position[2] || 0;

if (vec3.equals(this.getPosition(element), tmpPosition)) {
return;
}

transform.position = position;
vec3.copy(transform.position, tmpPosition);

if (element.parentNode === null || !(element.parentNode as Element).transformable) {
vec3.copy(transform.localPosition, position);
vec3.copy(transform.localPosition, tmpPosition);
} else {
const parentTransform = (element.parentNode as Element).transformable;
mat4.copy(parentInvertMatrix, parentTransform.worldTransform);
mat4.invert(parentInvertMatrix, parentInvertMatrix);
vec3.transformMat4(transform.localPosition, position, parentInvertMatrix);
vec3.transformMat4(transform.localPosition, tmpPosition, parentInvertMatrix);
}

this.dirtifyLocal(element, transform);
Expand All @@ -347,15 +351,24 @@ export class DefaultSceneGraphService implements SceneGraphService {
/**
* move to position in local space
*/
setLocalPosition(element: INode, position: vec3 | vec2) {
const transform = (element as Element).transformable;
position = vec3.fromValues(position[0], position[1], position[2] || 0);
if (vec3.equals(transform.localPosition, position)) {
return;
}
vec3.copy(transform.localPosition, position);
this.dirtifyLocal(element, transform);
}
setLocalPosition = (() => {
const tmpPosition = vec3.create();

return (element: INode, position: vec3 | vec2) => {
const transform = (element as Element).transformable;

tmpPosition[0] = position[0];
tmpPosition[1] = position[1];
tmpPosition[2] = position[2] || 0;

if (vec3.equals(transform.localPosition, tmpPosition)) {
return;
}

vec3.copy(transform.localPosition, tmpPosition);
this.dirtifyLocal(element, transform);
};
})();

/**
* scale in local space
Expand Down
14 changes: 10 additions & 4 deletions packages/g/src/shapes/AABB.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ export class AABB {
);
}

center: vec3;
center: vec3 = vec3.create();

halfExtents: vec3;
halfExtents: vec3 = vec3.create();

min: vec3 = vec3.create();
max: vec3 = vec3.create();
Expand All @@ -26,8 +26,14 @@ export class AABB {
}

update(center?: vec3, halfExtents?: vec3) {
this.center = vec3.copy(vec3.create(), center || vec3.create());
this.halfExtents = vec3.copy(vec3.create(), halfExtents || vec3.fromValues(0, 0, 0));
if (center) {
vec3.copy(this.center, center);
}

if (halfExtents) {
vec3.copy(this.halfExtents, halfExtents || vec3.fromValues(0, 0, 0));
}

this.min = vec3.sub(this.min, this.center, this.halfExtents);
this.max = vec3.add(this.max, this.center, this.halfExtents);
}
Expand Down

0 comments on commit 933947d

Please sign in to comment.