diff --git a/lib/features/dragging/Dragging.js b/lib/features/dragging/Dragging.js index 52cc5d4ea..79c630734 100644 --- a/lib/features/dragging/Dragging.js +++ b/lib/features/dragging/Dragging.js @@ -143,8 +143,8 @@ export default function Dragging(eventBus, canvas, selection) { var clientRect = canvas._container.getBoundingClientRect(); return { - x: viewbox.x + round((globalPosition.x - clientRect.left) / viewbox.scale), - y: viewbox.y + round((globalPosition.y - clientRect.top) / viewbox.scale) + x: viewbox.x + (globalPosition.x - clientRect.left) / viewbox.scale, + y: viewbox.y + (globalPosition.y - clientRect.top) / viewbox.scale }; } @@ -184,6 +184,7 @@ export default function Dragging(eventBus, canvas, selection) { localCurrent = toLocalPoint(globalCurrent), localDelta = deltaPos(localCurrent, localStart); + // activate context explicitly or once threshold is reached if (!context.active && (activate || getLength(globalDelta) > context.threshold)) { @@ -191,8 +192,8 @@ export default function Dragging(eventBus, canvas, selection) { // starting coordinates assign(payload, { - x: localStart.x + displacement.x, - y: localStart.y + displacement.y, + x: round(localStart.x + displacement.x), + y: round(localStart.y + displacement.y), dx: 0, dy: 0 }, { originalEvent: event }); @@ -226,10 +227,10 @@ export default function Dragging(eventBus, canvas, selection) { // update payload with actual coordinates assign(payload, { - x: localCurrent.x + displacement.x, - y: localCurrent.y + displacement.y, - dx: localDelta.x, - dy: localDelta.y + x: round(localCurrent.x + displacement.x), + y: round(localCurrent.y + displacement.y), + dx: round(localDelta.x), + dy: round(localDelta.y) }, { originalEvent: event }); // emit move event diff --git a/lib/features/replace/Replace.js b/lib/features/replace/Replace.js index ffe1e09f9..f70cdaf93 100644 --- a/lib/features/replace/Replace.js +++ b/lib/features/replace/Replace.js @@ -1,3 +1,5 @@ +var round = Math.round; + /** * Service that allow replacing of elements. */ @@ -28,8 +30,8 @@ Replace.prototype.replaceElement = function(oldElement, newElementData, options) } else { // set center of element for modeling API // if no new width / height is given use old elements size - newElementData.x = Math.ceil(oldElement.x + (newElementData.width || oldElement.width) / 2); - newElementData.y = Math.ceil(oldElement.y + (newElementData.height || oldElement.height) / 2); + newElementData.x = round(oldElement.x + (newElementData.width || oldElement.width) / 2); + newElementData.y = round(oldElement.y + (newElementData.height || oldElement.height) / 2); newElement = modeling.replaceShape(oldElement, newElementData, options); } diff --git a/test/spec/features/dragging/DraggingSpec.js b/test/spec/features/dragging/DraggingSpec.js index 00fdeab6b..dfcf6fbd6 100644 --- a/test/spec/features/dragging/DraggingSpec.js +++ b/test/spec/features/dragging/DraggingSpec.js @@ -303,6 +303,37 @@ describe('features/dragging - Dragging', function() { ]); })); + + it('should normalize to full pixel coordinates', inject( + function(dragging, canvas) { + + // given + canvas.zoom(0.37); + + // assume viewbox has sub-pixel x coordinate + expect(canvas.viewbox().x).not.to.eql(Math.round(canvas.viewbox().x)); + expect(canvas.viewbox().y).not.to.eql(Math.round(canvas.viewbox().y)); + + var events = recordEvents('foo'); + + // when + dragging.init(canvasEvent({ x: 0, y: 0 }), { x: 10.12321312, y: 9.9123821 }, 'foo'); + dragging.move(canvasEvent({ x: 20, y: 10 })); + + dragging.cancel(); + + // then + expect(events.map(raw)).to.eql([ + { type: 'foo.init' }, + { x: 10, y: 10, dx: 0, dy: 0, type: 'foo.start' }, + { x: 64, y: 37, dx: 54, dy: 27, type: 'foo.move' }, + { x: 64, y: 37, dx: 54, dy: 27, type: 'foo.cancel' }, + { x: 64, y: 37, dx: 54, dy: 27, type: 'foo.cleanup' }, + { x: 64, y: 37, dx: 54, dy: 27, type: 'foo.canceled' } + ]); + } + )); + }); });