Skip to content

Commit

Permalink
♻️ Refactor math utils in extensions (ampproject#21876)
Browse files Browse the repository at this point in the history
  • Loading branch information
rcebulko authored and rsimha committed May 21, 2019
1 parent aa327ef commit d60e2ad
Show file tree
Hide file tree
Showing 7 changed files with 193 additions and 76 deletions.
38 changes: 9 additions & 29 deletions extensions/amp-image-lightbox/0.1/amp-image-lightbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {Gestures} from '../../../src/gesture';
import {Keys} from '../../../src/utils/key-codes';
import {Services} from '../../../src/services';
import {bezierCurve} from '../../../src/curve';
import {boundValue, clamp, distance, magnitude} from '../../../src/utils/math';
import {continueMotion} from '../../../src/motion';
import {dev, userAssert} from '../../../src/log';
import {isLoaded} from '../../../src/event-helper';
Expand Down Expand Up @@ -406,19 +407,6 @@ export class ImageViewer {
});
}

/**
* Returns value bound to min and max values +/- extent.
* @param {number} v
* @param {number} min
* @param {number} max
* @param {number} extent
* @return {number}
* @private
*/
boundValue_(v, min, max, extent) {
return Math.max(min - extent, Math.min(max + extent, v));
}

/**
* Returns the scale within the allowed range with possible extent.
* @param {number} s
Expand All @@ -427,7 +415,7 @@ export class ImageViewer {
* @private
*/
boundScale_(s, allowExtent) {
return this.boundValue_(
return boundValue(
s,
this.minScale_,
this.maxScale_,
Expand All @@ -443,7 +431,7 @@ export class ImageViewer {
* @private
*/
boundX_(x, allowExtent) {
return this.boundValue_(
return boundValue(
x,
this.minX_,
this.maxX_,
Expand All @@ -459,7 +447,7 @@ export class ImageViewer {
* @private
*/
boundY_(y, allowExtent) {
return this.boundValue_(
return boundValue(
y,
this.minY_,
this.maxY_,
Expand Down Expand Up @@ -580,7 +568,7 @@ export class ImageViewer {
* @private
*/
onZoomInc_(centerClientX, centerClientY, deltaX, deltaY) {
const dist = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
const dist = magnitude(deltaX, deltaY);

const zoomSign =
Math.abs(deltaY) > Math.abs(deltaX)
Expand Down Expand Up @@ -678,9 +666,7 @@ export class ImageViewer {
*/
set_(newScale, newPosX, newPosY, animate) {
const ds = newScale - this.scale_;
const dx = newPosX - this.posX_;
const dy = newPosY - this.posY_;
const dist = Math.sqrt(dx * dx + dy * dy);
const dist = distance(this.posX_, this.posY_, newPosX, newPosY);

let dur = 0;
if (animate) {
Expand Down Expand Up @@ -1093,10 +1079,7 @@ class AmpImageLightbox extends AMP.BaseElement {
const scaleX = rect.width != 0 ? imageBox.width / rect.width : 1;
// Duration will be somewhere between 0.2 and 0.8 depending on how far
// the image needs to move.
const motionTime = Math.max(
0.2,
Math.min(0.8, (Math.abs(dy) / 250) * 0.8)
);
const motionTime = clamp((Math.abs(dy) / 250) * 0.8, 0.2, 0.8);
anim.add(
0,
tr.setStyles(clone, {
Expand Down Expand Up @@ -1214,10 +1197,7 @@ class AmpImageLightbox extends AMP.BaseElement {
// Duration will be somewhere between 0.2 and 0.8 depending on how far
// the image needs to move. Start the motion later too, but no later
// than 0.2.
const motionTime = Math.max(
0.2,
Math.min(0.8, (Math.abs(dy) / 250) * 0.8)
);
const motionTime = clamp((Math.abs(dy) / 250) * 0.8, 0.2, 0.8);
anim.add(
Math.min(0.8 - motionTime, 0.2),
(time, complete) => {
Expand All @@ -1242,7 +1222,7 @@ class AmpImageLightbox extends AMP.BaseElement {

// Duration will be somewhere between 300ms and 700ms depending on
// how far the image needs to move.
dur = Math.max(Math.min((Math.abs(dy) / 250) * dur, dur), 300);
dur = clamp((Math.abs(dy) / 250) * dur, 300, dur);
}

return anim.start(dur).thenAlways(() => {
Expand Down
4 changes: 2 additions & 2 deletions extensions/amp-image-slider/0.1/amp-image-slider.js
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,7 @@ export class AmpImageSlider extends AMP.BaseElement {
width = layoutBox.width;
left = layoutBox.left;
right = layoutBox.right;
const newPos = Math.max(left, Math.min(pointerX, right));
const newPos = clamp(pointerX, left, right);
const newPercentage = (newPos - left) / width;
this.mutateElement(() => {
this.updatePositions_(newPercentage);
Expand All @@ -661,7 +661,7 @@ export class AmpImageSlider extends AMP.BaseElement {
right = rect.right;
},
() => {
const newPos = Math.max(left, Math.min(pointerX, right));
const newPos = clamp(pointerX, left, right);
const newPercentage = (newPos - left) / width;
this.updatePositions_(newPercentage);
}
Expand Down
26 changes: 6 additions & 20 deletions extensions/amp-image-viewer/0.1/amp-image-viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
import {Gestures} from '../../../src/gesture';
import {Layout} from '../../../src/layout';
import {bezierCurve} from '../../../src/curve';
import {boundValue, distance, magnitude} from '../../../src/utils/math';
import {closestAncestorElementBySelector, elementByTag} from '../../../src/dom';
import {continueMotion} from '../../../src/motion';
import {createCustomEvent} from '../../../src/event-helper';
Expand Down Expand Up @@ -543,19 +544,6 @@ export class AmpImageViewer extends AMP.BaseElement {
}
}

/**
* Returns value bound to min and max values +/- extent.
* @param {number} v
* @param {number} min
* @param {number} max
* @param {number} extent
* @return {number}
* @private
*/
boundValue_(v, min, max, extent) {
return Math.max(min - extent, Math.min(max + extent, v));
}

/**
* Returns the scale within the allowed range with possible extent.
* @param {number} s
Expand All @@ -564,7 +552,7 @@ export class AmpImageViewer extends AMP.BaseElement {
* @private
*/
boundScale_(s, allowExtent) {
return this.boundValue_(
return boundValue(
s,
this.minScale_,
this.maxScale_,
Expand All @@ -580,7 +568,7 @@ export class AmpImageViewer extends AMP.BaseElement {
* @private
*/
boundX_(x, allowExtent) {
return this.boundValue_(
return boundValue(
x,
this.minX_,
this.maxX_,
Expand All @@ -596,7 +584,7 @@ export class AmpImageViewer extends AMP.BaseElement {
* @private
*/
boundY_(y, allowExtent) {
return this.boundValue_(
return boundValue(
y,
this.minY_,
this.maxY_,
Expand Down Expand Up @@ -742,7 +730,7 @@ export class AmpImageViewer extends AMP.BaseElement {
if (dir == 0) {
return;
}
const dist = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
const dist = magnitude(deltaX, deltaY);
const newScale = this.startScale_ * (1 + (dir * dist) / 100);
const deltaCenterX = this.elementBox_.width / 2 - centerClientX;
const deltaCenterY = this.elementBox_.height / 2 - centerClientY;
Expand Down Expand Up @@ -851,9 +839,7 @@ export class AmpImageViewer extends AMP.BaseElement {
*/
set_(newScale, newPosX, newPosY, animate) {
const ds = newScale - this.scale_;
const dx = newPosX - this.posX_;
const dy = newPosY - this.posY_;
const dist = Math.sqrt(dx * dx + dy * dy);
const dist = distance(this.posX_, this.posY_, newPosX, newPosY);

let dur = 0;
if (animate) {
Expand Down
27 changes: 6 additions & 21 deletions extensions/amp-pan-zoom/0.1/amp-pan-zoom.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {Gestures} from '../../../src/gesture';
import {Layout} from '../../../src/layout';
import {Services} from '../../../src/services';
import {bezierCurve} from '../../../src/curve';
import {clamp} from '../../../src/utils/math';
import {boundValue, distance, magnitude} from '../../../src/utils/math';
import {continueMotion} from '../../../src/motion';
import {createCustomEvent, listen} from '../../../src/event-helper';
import {dev, userAssert} from '../../../src/log';
Expand Down Expand Up @@ -651,19 +651,6 @@ export class AmpPanZoom extends AMP.BaseElement {
}
}

/**
* Returns value bound to min and max values +/- extent.
* @param {number} value
* @param {number} min
* @param {number} max
* @param {number} extent
* @return {number}
* @private
*/
boundValue_(value, min, max, extent) {
return clamp(value, min - extent, max + extent);
}

/**
* Returns the scale within the allowed range with possible extent.
* @param {number} s
Expand All @@ -673,7 +660,7 @@ export class AmpPanZoom extends AMP.BaseElement {
*/
boundScale_(s, allowExtent) {
const extent = allowExtent ? 0.25 : 0;
return this.boundValue_(s, this.minScale_, this.maxScale_, extent);
return boundValue(s, this.minScale_, this.maxScale_, extent);
}

/**
Expand All @@ -686,7 +673,7 @@ export class AmpPanZoom extends AMP.BaseElement {
boundX_(x, allowExtent) {
const maxExtent = this.elementBox_.width * 0.25;
const extent = allowExtent && this.scale_ > 1 ? maxExtent : 0;
return this.boundValue_(x, this.minX_, this.maxX_, extent);
return boundValue(x, this.minX_, this.maxX_, extent);
}

/**
Expand All @@ -699,7 +686,7 @@ export class AmpPanZoom extends AMP.BaseElement {
boundY_(y, allowExtent) {
const maxExtent = this.elementBox_.height * 0.25;
const extent = allowExtent && this.scale_ > 1 ? maxExtent : 0;
return this.boundValue_(y, this.minY_, this.maxY_, extent);
return boundValue(y, this.minY_, this.maxY_, extent);
}

/**
Expand Down Expand Up @@ -865,7 +852,7 @@ export class AmpPanZoom extends AMP.BaseElement {
return Promise.resolve();
}
const {width, height} = this.elementBox_;
const dist = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
const dist = magnitude(deltaX, deltaY);
const newScale = this.startScale_ * (1 + (dir * dist) / 100);
const deltaCenterX = width / 2 - this.getOffsetX_(centerClientX);
const deltaCenterY = height / 2 - this.getOffsetY_(centerClientY);
Expand Down Expand Up @@ -946,9 +933,7 @@ export class AmpPanZoom extends AMP.BaseElement {
*/
set_(newScale, newPosX, newPosY, animate) {
const ds = newScale - this.scale_;
const dx = newPosX - this.posX_;
const dy = newPosY - this.posY_;
const dist = Math.sqrt(dx * dx + dy * dy);
const dist = distance(this.posX_, this.posY_, newPosX, newPosY);

const dur = animate
? Math.min(
Expand Down
4 changes: 2 additions & 2 deletions extensions/amp-video-docking/0.1/amp-video-docking.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import {installStylesForDoc} from '../../../src/style-installer';
import {isFiniteNumber} from '../../../src/types';
import {isRTL, removeElement, scopedQuerySelector} from '../../../src/dom';
import {layoutRectLtwh, moveLayoutRect} from '../../../src/layout-rect';
import {mapRange} from '../../../src/utils/math';
import {magnitude, mapRange} from '../../../src/utils/math';
import {once} from '../../../src/utils/function';
import {
px,
Expand Down Expand Up @@ -1515,7 +1515,7 @@ export class VideoDocking {
offset.y = 0;

// Prevents dragging misfires.
const offsetDist = Math.sqrt(Math.pow(offset.x, 2) + Math.pow(offset.y, 2));
const offsetDist = magnitude(offset.x, offset.y);
if (offsetDist <= 10) {
return;
}
Expand Down
42 changes: 41 additions & 1 deletion src/utils/math.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
* limitations under the License.
*/

import {devAssert} from '../log';

/**
* Maps a value in a first range to its equivalent in a second range
* Ex.: 5 in the range [0,10] gives 60 in the range[40,80]
Expand Down Expand Up @@ -79,7 +81,8 @@ export function mod(a, b) {
}

/**
* Restricts a number to be in the given min/max range.
* Restricts a number to be in the given min/max range. The minimum value must
* be less than or equal to the maximum value.
*
* Examples:
* clamp(0.5, 0, 1) -> 0.5
Expand All @@ -92,5 +95,42 @@ export function mod(a, b) {
* @return {number} the clamped value.
*/
export function clamp(val, min, max) {
devAssert(min <= max, 'Minimum value is greater than the maximum.');
return Math.min(Math.max(val, min), max);
}

/**
* Returns value bound to min and max values +/- extent. The lower bound must
* be less than or equal to the upper bound.
* @param {number} val the value to bound.
* @param {number} min the lower bound.
* @param {number} max the upper bound
* @param {number} extent the allowed extent beyond the bounds.
* @return {number} the bounded value.
*/
export function boundValue(val, min, max, extent) {
devAssert(min <= max, 'Lower bound is greater than the upper bound.');
return clamp(val, min - extent, max + extent);
}

/**
* Returns the length of a vector given in X- and Y-coordinates.
* @param {number} deltaX distance in the X direction.
* @param {number} deltaY distance in the Y direction.
* @return {number} the magnitude of the vector.
*/
export function magnitude(deltaX, deltaY) {
return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
}

/**
* Returns the distance between two points.
* @param {number} x1 X-coordinate of the first point.
* @param {number} y1 Y-coordinate of the first point.
* @param {number} x2 X-coordinate of the second point.
* @param {number} y2 Y-coordinate of the second point.
* @return {number} the distance between the two points.
*/
export function distance(x1, y1, x2, y2) {
return magnitude(x2 - x1, y2 - y1);
}
Loading

0 comments on commit d60e2ad

Please sign in to comment.