Skip to content

Commit ecdb715

Browse files
committed
fix: correct the offset of the mirror
1 parent 5acbf88 commit ecdb715

File tree

4 files changed

+82
-7
lines changed

4 files changed

+82
-7
lines changed

jsconfig.json

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"compilerOptions": {
3+
"baseUrl": ".",
4+
"paths": {
5+
"helper": ["./scripts/test/helper.js"],
6+
"shared/*": ["./src/shared/*"]
7+
}
8+
}
9+
}

src/Draggable/Plugins/Mirror/Mirror.js

+60-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import AbstractPlugin from 'shared/AbstractPlugin';
2+
import {browserInfo} from 'shared/utils';
23

34
import {
45
MirrorCreateEvent,
@@ -277,13 +278,14 @@ export default class Mirror extends AbstractPlugin {
277278
[onMirrorCreated]({mirror, source, sensorEvent}) {
278279
const mirrorClasses = this.draggable.getClassNamesFor('mirror');
279280

280-
const setState = ({mirrorOffset, initialX, initialY, ...args}) => {
281+
const setState = ({mirrorOffset, correctOffset, initialX, initialY, ...args}) => {
281282
this.mirrorOffset = mirrorOffset;
283+
this.correctOffset = correctOffset;
282284
this.initialX = initialX;
283285
this.initialY = initialY;
284286
this.lastMovedX = initialX;
285287
this.lastMovedY = initialY;
286-
return {mirrorOffset, initialX, initialY, ...args};
288+
return {mirrorOffset, correctOffset, initialX, initialY, ...args};
287289
};
288290

289291
mirror.style.display = 'none';
@@ -304,6 +306,7 @@ export default class Mirror extends AbstractPlugin {
304306
// Fix reflow here
305307
.then(computeMirrorDimensions)
306308
.then(calculateMirrorOffset)
309+
.then(calculateCorrectOffset)
307310
.then(resetMirror)
308311
.then(addMirrorClasses)
309312
.then(positionMirror({initial: true}))
@@ -334,6 +337,7 @@ export default class Mirror extends AbstractPlugin {
334337
mirror: mirrorEvent.mirror,
335338
sensorEvent: mirrorEvent.sensorEvent,
336339
mirrorOffset: this.mirrorOffset,
340+
correctOffset: this.correctOffset,
337341
options: this.options,
338342
initialX: this.initialX,
339343
initialY: this.initialY,
@@ -406,6 +410,49 @@ function calculateMirrorOffset({sensorEvent, sourceRect, options, ...args}) {
406410
});
407411
}
408412

413+
/**
414+
* Calculates correct offset
415+
* Adds correctOffset to state, because `position: fixed;` has some except
416+
* See https://developer.mozilla.org/en-US/docs/Web/CSS/position
417+
* @param {Object} state
418+
* @param {HTMLElement} state.mirror
419+
* @return {Promise}
420+
* @private
421+
*/
422+
function calculateCorrectOffset({mirror, ...args}) {
423+
return withPromise((resolve) => {
424+
let x = 0;
425+
let y = 0;
426+
let container = mirror;
427+
428+
if (!browserInfo.IE11OrLess) {
429+
do {
430+
if (container && container.getBoundingClientRect) {
431+
const containerStyle = getComputedStyle(container);
432+
if (
433+
(containerStyle.transform && containerStyle.transform !== 'none') ||
434+
(containerStyle.perspective && containerStyle.perspective !== 'none') ||
435+
(containerStyle.filter && containerStyle.filter !== 'none')
436+
) {
437+
const containerRect = container.getBoundingClientRect();
438+
439+
// Set relative to edges of padding box of container
440+
x = containerRect.top + parseInt(containerStyle['border-top-width'], 10);
441+
y = containerRect.left + parseInt(containerStyle['border-left-width'], 10);
442+
443+
break;
444+
}
445+
}
446+
/* jshint boss:true */
447+
} while ((container = container.parentNode));
448+
}
449+
450+
const correctOffset = {x, y};
451+
452+
resolve({mirror, correctOffset, ...args});
453+
});
454+
}
455+
409456
/**
410457
* Applys mirror styles
411458
* @param {Object} state
@@ -426,7 +473,7 @@ function resetMirror({mirror, source, options, ...args}) {
426473
offsetWidth = computedSourceStyles.getPropertyValue('width');
427474
}
428475

429-
mirror.style.display = null;
476+
mirror.style.display = '';
430477
mirror.style.position = 'fixed';
431478
mirror.style.pointerEvents = 'none';
432479
mirror.style.top = 0;
@@ -478,6 +525,7 @@ function removeMirrorID({mirror, ...args}) {
478525
* @param {HTMLElement} state.mirror
479526
* @param {SensorEvent} state.sensorEvent
480527
* @param {Object} state.mirrorOffset
528+
* @param {Object} state.correctOffset
481529
* @param {Number} state.initialY
482530
* @param {Number} state.initialX
483531
* @param {Object} state.options
@@ -489,6 +537,7 @@ function positionMirror({withFrame = false, initial = false} = {}) {
489537
mirror,
490538
sensorEvent,
491539
mirrorOffset,
540+
correctOffset,
492541
initialY,
493542
initialX,
494543
scrollOffset,
@@ -505,18 +554,22 @@ function positionMirror({withFrame = false, initial = false} = {}) {
505554
mirror,
506555
sensorEvent,
507556
mirrorOffset,
557+
correctOffset,
508558
options,
509559
...args,
510560
};
511561

512562
if (mirrorOffset) {
563+
const thresholdX = options.thresholdX || 1;
564+
const thresholdY = options.thresholdY || 1;
565+
513566
const x = passedThreshX
514-
? Math.round((sensorEvent.clientX - mirrorOffset.left - scrollOffset.x) / (options.thresholdX || 1)) *
515-
(options.thresholdX || 1)
567+
? Math.round((sensorEvent.clientX - mirrorOffset.left - scrollOffset.x - correctOffset.x) / thresholdX) *
568+
thresholdX
516569
: Math.round(lastMovedX);
517570
const y = passedThreshY
518-
? Math.round((sensorEvent.clientY - mirrorOffset.top - scrollOffset.y) / (options.thresholdY || 1)) *
519-
(options.thresholdY || 1)
571+
? Math.round((sensorEvent.clientY - mirrorOffset.top - scrollOffset.y - correctOffset.y) / thresholdY) *
572+
thresholdY
520573
: Math.round(lastMovedY);
521574

522575
if ((options.xAxis && options.yAxis) || initial) {

src/shared/utils/browserInfo/index.js

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
function userAgent(pattern) {
2+
if (typeof window !== 'undefined' && window.navigator) {
3+
return Boolean(navigator.userAgent.match(pattern));
4+
}
5+
return false;
6+
}
7+
8+
const browserInfo = {
9+
IE11OrLess: userAgent(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i),
10+
};
11+
12+
export default browserInfo;

src/shared/utils/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export {default as closest} from './closest';
22
export {default as requestNextAnimationFrame} from './requestNextAnimationFrame';
33
export {default as distance} from './distance';
44
export {default as touchCoords} from './touchCoords';
5+
export {default as browserInfo} from './browserInfo';

0 commit comments

Comments
 (0)