Allow viewport to be used for constraining popup position
This commit is contained in:
parent
21dbb19565
commit
d59f2022b9
@ -258,6 +258,7 @@ class Popup {
|
|||||||
Popup._getPositionForVerticalText
|
Popup._getPositionForVerticalText
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const viewport = Popup._getViewport(optionsGeneral.popupScaleRelativeToVisualViewport);
|
||||||
const scale = this._contentScale;
|
const scale = this._contentScale;
|
||||||
const scaleRatio = this._containerSizeContentScale === null ? 1.0 : scale / this._containerSizeContentScale;
|
const scaleRatio = this._containerSizeContentScale === null ? 1.0 : scale / this._containerSizeContentScale;
|
||||||
this._containerSizeContentScale = scale;
|
this._containerSizeContentScale = scale;
|
||||||
@ -265,8 +266,7 @@ class Popup {
|
|||||||
elementRect,
|
elementRect,
|
||||||
Math.max(containerRect.width * scaleRatio, optionsGeneral.popupWidth * scale),
|
Math.max(containerRect.width * scaleRatio, optionsGeneral.popupWidth * scale),
|
||||||
Math.max(containerRect.height * scaleRatio, optionsGeneral.popupHeight * scale),
|
Math.max(containerRect.height * scaleRatio, optionsGeneral.popupHeight * scale),
|
||||||
document.body.clientWidth,
|
viewport,
|
||||||
window.innerHeight,
|
|
||||||
scale,
|
scale,
|
||||||
optionsGeneral,
|
optionsGeneral,
|
||||||
writingMode
|
writingMode
|
||||||
@ -353,49 +353,49 @@ class Popup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static _getPositionForHorizontalText(elementRect, width, height, maxWidth, maxHeight, offsetScale, optionsGeneral) {
|
static _getPositionForHorizontalText(elementRect, width, height, viewport, offsetScale, optionsGeneral) {
|
||||||
let x = elementRect.left + optionsGeneral.popupHorizontalOffset * offsetScale;
|
|
||||||
const overflowX = Math.max(x + width - maxWidth, 0);
|
|
||||||
if (overflowX > 0) {
|
|
||||||
if (x >= overflowX) {
|
|
||||||
x -= overflowX;
|
|
||||||
} else {
|
|
||||||
width = maxWidth;
|
|
||||||
x = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const preferBelow = (optionsGeneral.popupHorizontalTextPosition === 'below');
|
const preferBelow = (optionsGeneral.popupHorizontalTextPosition === 'below');
|
||||||
|
const horizontalOffset = optionsGeneral.popupHorizontalOffset * offsetScale;
|
||||||
const verticalOffset = optionsGeneral.popupVerticalOffset * offsetScale;
|
const verticalOffset = optionsGeneral.popupVerticalOffset * offsetScale;
|
||||||
const [y, h, below] = Popup._limitGeometry(
|
|
||||||
|
const [x, w] = Popup._getConstrainedPosition(
|
||||||
|
elementRect.right - horizontalOffset,
|
||||||
|
elementRect.left + horizontalOffset,
|
||||||
|
width,
|
||||||
|
viewport.left,
|
||||||
|
viewport.right,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
const [y, h, below] = Popup._getConstrainedPositionBinary(
|
||||||
elementRect.top - verticalOffset,
|
elementRect.top - verticalOffset,
|
||||||
elementRect.bottom + verticalOffset,
|
elementRect.bottom + verticalOffset,
|
||||||
height,
|
height,
|
||||||
maxHeight,
|
viewport.top,
|
||||||
|
viewport.bottom,
|
||||||
preferBelow
|
preferBelow
|
||||||
);
|
);
|
||||||
|
return [x, y, w, h, below];
|
||||||
return [x, y, width, h, below];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static _getPositionForVerticalText(elementRect, width, height, maxWidth, maxHeight, offsetScale, optionsGeneral, writingMode) {
|
static _getPositionForVerticalText(elementRect, width, height, viewport, offsetScale, optionsGeneral, writingMode) {
|
||||||
const preferRight = Popup._isVerticalTextPopupOnRight(optionsGeneral.popupVerticalTextPosition, writingMode);
|
const preferRight = Popup._isVerticalTextPopupOnRight(optionsGeneral.popupVerticalTextPosition, writingMode);
|
||||||
const horizontalOffset = optionsGeneral.popupHorizontalOffset2 * offsetScale;
|
const horizontalOffset = optionsGeneral.popupHorizontalOffset2 * offsetScale;
|
||||||
const verticalOffset = optionsGeneral.popupVerticalOffset2 * offsetScale;
|
const verticalOffset = optionsGeneral.popupVerticalOffset2 * offsetScale;
|
||||||
|
|
||||||
const [x, w] = Popup._limitGeometry(
|
const [x, w] = Popup._getConstrainedPositionBinary(
|
||||||
elementRect.left - horizontalOffset,
|
elementRect.left - horizontalOffset,
|
||||||
elementRect.right + horizontalOffset,
|
elementRect.right + horizontalOffset,
|
||||||
width,
|
width,
|
||||||
maxWidth,
|
viewport.left,
|
||||||
|
viewport.right,
|
||||||
preferRight
|
preferRight
|
||||||
);
|
);
|
||||||
const [y, h, below] = Popup._limitGeometry(
|
const [y, h, below] = Popup._getConstrainedPosition(
|
||||||
elementRect.bottom - verticalOffset,
|
elementRect.bottom - verticalOffset,
|
||||||
elementRect.top + verticalOffset,
|
elementRect.top + verticalOffset,
|
||||||
height,
|
height,
|
||||||
maxHeight,
|
viewport.top,
|
||||||
|
viewport.bottom,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
return [x, y, w, h, below];
|
return [x, y, w, h, below];
|
||||||
@ -424,23 +424,36 @@ class Popup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static _limitGeometry(positionBefore, positionAfter, size, limit, preferAfter) {
|
static _getConstrainedPosition(positionBefore, positionAfter, size, minLimit, maxLimit, after) {
|
||||||
let after = preferAfter;
|
size = Math.min(size, maxLimit - minLimit);
|
||||||
let position = 0;
|
|
||||||
const overflowBefore = Math.max(0, size - positionBefore);
|
let position;
|
||||||
const overflowAfter = Math.max(0, positionAfter + size - limit);
|
if (after) {
|
||||||
if (overflowAfter > 0 || overflowBefore > 0) {
|
position = Math.max(minLimit, positionAfter);
|
||||||
if (overflowAfter < overflowBefore) {
|
position = position - Math.max(0, (position + size) - maxLimit);
|
||||||
size = Math.max(0, size - overflowAfter);
|
|
||||||
position = positionAfter;
|
|
||||||
after = true;
|
|
||||||
} else {
|
} else {
|
||||||
size = Math.max(0, size - overflowBefore);
|
position = Math.min(maxLimit, positionBefore) - size;
|
||||||
position = Math.max(0, positionBefore - size);
|
position = position + Math.max(0, minLimit - position);
|
||||||
after = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return [position, size, after];
|
||||||
|
}
|
||||||
|
|
||||||
|
static _getConstrainedPositionBinary(positionBefore, positionAfter, size, minLimit, maxLimit, after) {
|
||||||
|
const overflowBefore = minLimit - (positionBefore - size);
|
||||||
|
const overflowAfter = (positionAfter + size) - maxLimit;
|
||||||
|
|
||||||
|
if (overflowAfter > 0 || overflowBefore > 0) {
|
||||||
|
after = (overflowAfter < overflowBefore);
|
||||||
|
}
|
||||||
|
|
||||||
|
let position;
|
||||||
|
if (after) {
|
||||||
|
size -= Math.max(0, overflowAfter);
|
||||||
|
position = Math.max(minLimit, positionAfter);
|
||||||
} else {
|
} else {
|
||||||
position = preferAfter ? positionAfter : positionBefore - size;
|
size -= Math.max(0, overflowBefore);
|
||||||
|
position = Math.min(maxLimit, positionBefore) - size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [position, size, after];
|
return [position, size, after];
|
||||||
@ -479,6 +492,29 @@ class Popup {
|
|||||||
// NOP
|
// NOP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static _getViewport(useVisualViewport) {
|
||||||
|
if (useVisualViewport) {
|
||||||
|
const visualViewport = window.visualViewport;
|
||||||
|
if (visualViewport !== null && typeof visualViewport === 'object') {
|
||||||
|
const left = visualViewport.offsetLeft;
|
||||||
|
const top = visualViewport.offsetTop;
|
||||||
|
return {
|
||||||
|
left,
|
||||||
|
top,
|
||||||
|
right: left + visualViewport.width,
|
||||||
|
bottom: top + visualViewport.height
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
right: document.body.clientWidth,
|
||||||
|
bottom: window.innerHeight
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Popup.outerStylesheet = null;
|
Popup.outerStylesheet = null;
|
||||||
|
Loading…
Reference in New Issue
Block a user