Skip to content

fix(cdk/drag-drop): pointer position calculation for SVG with viewBox #19863

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/cdk/drag-drop/directives/drag.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,17 @@ describe('CdkDrag', () => {
expect(dragElement.getAttribute('transform')).toBe('translate(50 100)');
}));

it('should drag an SVG element freely to a particular position in SVG viewBox coordinates',
fakeAsync(() => {
const fixture = createComponent(StandaloneDraggableSvgWithViewBox);
fixture.detectChanges();
const dragElement = fixture.componentInstance.dragElement.nativeElement;

expect(dragElement.getAttribute('transform')).toBeFalsy();
dragElementViaMouse(fixture, dragElement, 50, 100);
expect(dragElement.getAttribute('transform')).toBe('translate(100 200)');
}));

it('should drag an element freely to a particular position when the page is scrolled',
fakeAsync(() => {
const fixture = createComponent(StandaloneDraggable);
Expand Down Expand Up @@ -5311,6 +5322,19 @@ class StandaloneDraggableSvg {
@ViewChild('dragElement') dragElement: ElementRef<SVGElement>;
}

@Component({
template: `
<svg width="400px" height="400px" viewBox="0 0 800 800"><g
cdkDrag
#dragElement>
<circle fill="red" r="50" cx="50" cy="50"/>
</g></svg>
`
})
class StandaloneDraggableSvgWithViewBox {
@ViewChild('dragElement') dragElement: ElementRef<SVGElement>;
}

@Component({
template: `
<div #dragElement cdkDrag
Expand Down
31 changes: 26 additions & 5 deletions src/cdk/drag-drop/drag-ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,11 @@ export class DragRef<T = any> {
*/
private _rootElement: HTMLElement;

/**
* Nearest ancestor SVG, relative to which coordinates are calculated if dragging SVGElement
*/
private _ownerSVGElement: SVGSVGElement | null;

/**
* Inline style value of `-webkit-tap-highlight-color` at the time the
* dragging was started. Used to restore the value once we're done dragging.
Expand Down Expand Up @@ -377,6 +382,10 @@ export class DragRef<T = any> {
this._rootElement = element;
}

if (typeof SVGElement !== 'undefined' && this._rootElement instanceof SVGElement) {
this._ownerSVGElement = this._rootElement.ownerSVGElement;
}

return this;
}

Expand Down Expand Up @@ -424,7 +433,7 @@ export class DragRef<T = any> {
this._dropContainer = undefined;
this._resizeSubscription.unsubscribe();
this._parentPositions.clear();
this._boundaryElement = this._rootElement = this._placeholderTemplate =
this._boundaryElement = this._rootElement = this._ownerSVGElement = this._placeholderTemplate =
this._previewTemplate = this._anchor = null!;
}

Expand Down Expand Up @@ -1044,10 +1053,22 @@ export class DragRef<T = any> {
// we can get away with it. See https://bugzilla.mozilla.org/show_bug.cgi?id=1615824.
(event.touches[0] || event.changedTouches[0] || {pageX: 0, pageY: 0}) : event;

return {
x: point.pageX - scrollPosition.left,
y: point.pageY - scrollPosition.top
};
const x = point.pageX - scrollPosition.left;
const y = point.pageY - scrollPosition.top;

// if dragging SVG element, try to convert from the screen coordinate system to the SVG
// coordinate system
if (this._ownerSVGElement) {
const svgMatrix = this._ownerSVGElement.getScreenCTM();
if (svgMatrix) {
const svgPoint = this._ownerSVGElement.createSVGPoint();
svgPoint.x = x;
svgPoint.y = y;
return svgPoint.matrixTransform(svgMatrix.inverse());
}
}

return {x, y};
}


Expand Down