Skip to content

Commit

Permalink
Reorganize files, update code documentation a bit.
Browse files Browse the repository at this point in the history
  • Loading branch information
Sepand Parhami committed Oct 16, 2018
1 parent 7c792e9 commit 7a4a1df
Show file tree
Hide file tree
Showing 16 changed files with 90 additions and 21 deletions.
1 change: 1 addition & 0 deletions index.ts
@@ -0,0 +1 @@
export {prepareImageAnimation} from './src/transform-img/index.js';
15 changes: 12 additions & 3 deletions src/img-dimensions.ts
Expand Up @@ -15,9 +15,18 @@
*/

/**
* @fileoverview Provides a function the dimensions of the rendered image
* inside of an <img> tag.
*
* @fileoverview Provides a function to calculate the dimensions of the
* rendered image inside of an `<img>` Element. For example, if you have an
* `<img>` with `object-fit: contain` and an image that is portrait inside of
* an `<img>` with landscape dimensions, you will have something looks like:
* _____________
* | | | |
* | i | r | i |
* |___|_____|___|
*
* Where the area denoted by `r` is the rendered image and the areas denoted
* by `i` are extra spacing on either side of the rendered image to center it
* within the containing `<img>` Element.
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit
*/

Expand Down
2 changes: 1 addition & 1 deletion src/replacement-img.ts
Expand Up @@ -20,7 +20,7 @@ import {getRenderedDimensions} from './img-dimensions.js';
* Creates a replacement for a given img, which should render the same as the
* source img, but implemented with a cropping container and and img using
* `object-fit: fill`. This can be used to implement a transition of the image.
* The crop can be transitioned by scaling up the container while scaping down
* The crop can be transitioned by scaling up the container while scaling down
* the image by the inverse amount.
* @param srcImg
* @param srcImgRect
Expand Down
2 changes: 1 addition & 1 deletion src/test-img-dimensions.ts
Expand Up @@ -15,7 +15,7 @@
*/

import {getRenderedDimensions} from './img-dimensions';
import {imgLoadPromise} from './utils';
import {imgLoadPromise} from './testing/utils';

const {expect} = chai;
const fourByThreeUri = 'data:image/gif;base64,R0lGODdhBAADAIAAAP///////ywAAAAABAADAAACA4SPVgA7';
Expand Down
2 changes: 1 addition & 1 deletion src/test-replacement-img.ts
Expand Up @@ -15,7 +15,7 @@
*/

import {createReplacement} from './replacement-img';
import {imgLoadPromise} from './utils';
import {imgLoadPromise} from './testing/utils';

const {expect} = chai;
const fourByThreeUri = 'data:image/gif;base64,R0lGODdhBAADAIAAAP///////ywAAAAABAADAAACA4SPVgA7';
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
30 changes: 30 additions & 0 deletions src/transform-img/README.md
@@ -0,0 +1,30 @@
# Transform Img

## Overview

This directory contains logic for transforming an image from one location to
another. The animation is comprised of 3 parts:

* Scaling up the image in the x and y directions to the final scale
* Translating the image in the x and y directions to the final location
* Changing the crop in the x and y directions to the final crop

Each of these are implemented in seprate file.

## Implementation

In order to have the animation perform well, including on older devices, only
CPU accelrated animatable properties. As a result, the 'crop' portion of the
animation is implemented by scaling up a cropping container (with
`overflow: hidden`) and counteracting the scaling with an inverse scale on a
child container.

The animations are implemented by taking the larger size and animating using
that as a reference point for scaling. That is, when the transition is where
the larger image is (whether that is the starting state or ending state), the
scale values will all be `1.0`. This is done to avoid rounding errors from
the various scale animations from having a user perceivable impact. The errors
are much less or not at all noticable for the smaller image. When we are going
from a small image to a large image (say scaling by 5x), we will animate the
scale from `0.2` to `1.0`. If we were to run the reverse operation, we would
scale from `1.0` to `0.2`.
21 changes: 17 additions & 4 deletions src/crop-animation.ts → src/transform-img/crop-animation.ts
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import {Curve, getBezierCurveValue} from './bezier-curve-utils.js';
import {Curve, getBezierCurveValue} from '../bezier-curve-utils.js';

interface Scale {
x: number,
Expand Down Expand Up @@ -60,9 +60,14 @@ function generateCropKeyframes({
let scaleElementKeyframes = '';
let counterScaleKeyframes = '';

// Generates one step for each frame. This is just a guide, the actual values
// will be interoplated from these, but just to make sure we have enough
// steps for the browser to work with to make it smooth.
/*
* Generates keyframes for the browser to interpolate from. We simply need to
* make sure there are enough for this to be smooth. Note: we are generating
* keyframes as a function of `t` in the Bezier curve formula and not time.
* The keyframes generated will be more clustered when the output (y) value
* is more rapidly changing, so we should not have too much error no matter
* which two keyframes the browser interpolates between.
*/
for (let i = 0; i <= numSamples; i++) {
const t = i * (1 / numSamples);
// The progress through the animation at this point.
Expand Down Expand Up @@ -95,6 +100,14 @@ function generateCropKeyframes({
`;
}

/**
* Prepares a crop animation. This is done by scaling up the croping container
* while scaling down a nested container to preserve the scale of the inner
* content. This function sets up the animation by setting the appropriate
* style properties on the desired Elements. The returned style text needs
* to be inserted for the animation to run.
* @return CSS style text to perform the aniamtion.
*/
export function prepareCropAnimation({
scaleElement,
counterScaleElement,
Expand Down
1 change: 1 addition & 0 deletions src/transform-img/index.ts
@@ -0,0 +1 @@
export {prepareImageAnimation} from './transform-img.js';
Expand Up @@ -14,8 +14,15 @@
* limitations under the License.
*/

import {Curve, curveToString} from './bezier-curve-utils.js';
import {Curve, curveToString} from '../bezier-curve-utils.js';


/**
* Prepares a scale animation. This function sets up the animation by setting
* the appropriate style properties on the desired Element. The returned style
* text needs to be inserted for the animation to run.
* @return CSS style text to perform the aniamtion.
*/
export function prepareScaleAnimation({
element,
largerImgWidth,
Expand Down
Expand Up @@ -15,12 +15,12 @@
*/

import {prepareImageAnimation} from './transform-img';
import {imgLoadPromise} from './utils';
import {imgLoadPromise} from '../testing/utils';
import {
setup as setupAnimations,
tearDown as tearDownAnimations,
offset,
} from './animation-test-controller';
} from '../testing/animation-test-controller';

const {expect} = chai;
const threeByFourUri = 'data:image/gif;base64,R0lGODdhAwAEAIAAAP///////ywAAAAAAwAEAAACA4SPVgA7';
Expand Down
19 changes: 13 additions & 6 deletions src/transform-img.ts → src/transform-img/transform-img.ts
Expand Up @@ -14,9 +14,9 @@
* limitations under the License.
*/

import {Curve} from './bezier-curve-utils.js';
import {getRenderedDimensions} from './img-dimensions.js';
import {createReplacement} from './replacement-img.js';
import {Curve} from '../bezier-curve-utils.js';
import {getRenderedDimensions} from '../img-dimensions.js';
import {createReplacement} from '../replacement-img.js';
import {prepareCropAnimation} from './crop-animation.js';
import {prepareScaleAnimation} from './scale-animation.js';
import {prepareTranslateAnimation} from './translate-animation.js';
Expand All @@ -27,7 +27,9 @@ import {prepareTranslateAnimation} from './translate-animation.js';
let keyframesPrefixCounter: number = 0;

/**
* @param namespace
* Gets a prefix name to use for the keyframes, avoiding clashing with other
* keyframes that may be defined.
* @param namespace A namespace to use as a prefix.
* @return The prefix to use for the various keyframes.
*/
function getKeyframesPrefix(namespace: string): string {
Expand All @@ -39,6 +41,7 @@ function getKeyframesPrefix(namespace: string): string {
/**
* Prepares an animation from one image to another. Creates a a temporary
* replacement image that is transitioned between the two images.
* @param options
* @param options.transitionContainer The container to place the transition
* image in. Defaults to document.body.
* @param options.styleContainer The container to place the generated
Expand All @@ -55,10 +58,14 @@ function getKeyframesPrefix(namespace: string): string {
* should include animationDuration. It might also include animationDelay.
* @param options.translateCurve Control points for a Bezier curve to use for
* the translation portion of animation. Defaults to `curve`.
* @param options.styles Styles to apply to the transitioning Elements. This
* should include animationDuration. It might also include animationDelay.
* @param options.translateStyles Styles to apply to the translating Elements.
* This should include animationDuration. It might also include
* animationDelay. Defaults to `styles`.
* @param options.scaleCurve Control points for a Bezier curve to use for
* the translation portion of animation. Defaults to `curve`.
* @param options.scaleStyles Styles to apply to the scaling Elements. This
* should include animationDuration. It might also include animationDelay.
* Defaults to `styles`.
* @param options.keyframesNamespace A namespace to use for the generated
* keyframes to ensure they do not clash with existing keyframes.
*/
Expand Down
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import {Curve, curveToString} from './bezier-curve-utils.js';
import {Curve, curveToString} from '../bezier-curve-utils.js';

export function prepareTranslateAnimation({
element,
Expand Down
3 changes: 2 additions & 1 deletion tsconfig.json
Expand Up @@ -19,6 +19,7 @@
"sourceMap": true
},
"include": [
"src/*.ts"
"index.ts",
"src/**/*.ts",
]
}

0 comments on commit 7a4a1df

Please sign in to comment.