forked from ampproject/amphtml
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
amp-fx-collection: parallax (ampproject#13073)
- Loading branch information
Showing
11 changed files
with
563 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,81 +5,107 @@ | |
<title>AMP Article with parallax title</title> | ||
<link rel="canonical" href="amps.html"> | ||
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"> | ||
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript> | ||
<script async src="https://cdn.ampproject.org/v0.js"></script> | ||
<script async custom-element="amp-fx-collection" src="https://cdn.ampproject.org/v0/amp-fx-collection-0.1.js"></script> | ||
<style amp-custom> | ||
article, header h1 { | ||
.spacer { | ||
margin-top: 10px; | ||
height: 70vh; | ||
width: 100%; | ||
background-image: -webkit-linear-gradient(#EEE 50%, white 50%); | ||
background-image: linear-gradient(#EEE 50%, white 50%); | ||
background-size: 100% 3em; | ||
} | ||
|
||
header { | ||
position: relative; | ||
} | ||
|
||
h1 { | ||
margin: 0px 10px; | ||
} | ||
|
||
header h1 { | ||
position: absolute; | ||
top: 25vh; | ||
top: 20vh; | ||
padding: 5px; | ||
z-index: 1; | ||
max-width: 70vw; | ||
} | ||
|
||
header h1 span { | ||
header h1 span, .title { | ||
background-color: black; | ||
color: white; | ||
line-height: 1.2em; | ||
} | ||
|
||
header amp-img img { | ||
amp-img img { | ||
object-fit: cover; | ||
} | ||
|
||
/* | ||
* Vertically center the tite within the image. | ||
*/ | ||
.vertically-center { | ||
transform: translateY(-50%); | ||
.overlay-top { | ||
position: absolute; | ||
top: 0; | ||
} | ||
|
||
.overlay-container { | ||
position: relative; | ||
overflow: hidden; | ||
} | ||
|
||
main { | ||
font-family: Helvetica, sans-serif; | ||
padding: 10px; | ||
max-width: 412px; | ||
margin: auto; | ||
} | ||
|
||
a, a:visited, a:active { | ||
color: #2196F3; | ||
text-decoration: none; | ||
display: block; | ||
padding: 5px; | ||
} | ||
|
||
.overflow-window { | ||
overflow: hidden; | ||
} | ||
|
||
.overflow-window amp-img { | ||
margin-bottom: -80%; | ||
} | ||
</style> | ||
<script async custom-element="amp-fx-parallax" src="https://cdn.ampproject.org/v0/amp-fx-parallax-0.1.js"></script> | ||
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript> | ||
</head> | ||
<body> | ||
<header> | ||
<h1 amp-fx-parallax="1.7"> | ||
<div class="vertically-center"> | ||
<span>Lorem Ipsum Dolor Sit Amet Consectetur Adipiscing<span> | ||
</div> | ||
</h1> | ||
<amp-img height="50vh" layout="fixed-height" src="img/[email protected]"></amp-img> | ||
</header> | ||
<main> | ||
<header> | ||
<h1 amp-fx="parallax" data-parallax-factor="1.5"> | ||
<span class="title">Lorem Ipsum Dolor Sit Lorem Ipsum<span> | ||
</h1> | ||
<amp-img height="50vh" layout="fixed-height" src="https://picsum.photos/1600/900?image=1069"></amp-img> | ||
</header> | ||
|
||
<article> | ||
<p> | ||
<a href="#scrollToMe" on="tap:scrollToMe.scrollTo(duration=3000)">Tap to auto scroll slowly</a> | ||
<a href="#scrollToMe">Tap to auto scroll fast</a> | ||
</p> | ||
|
||
<article> | ||
<p> | ||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur ullamcorper turpis vel commodo scelerisque. Phasellus | ||
luctus nunc ut elit cursus, et imperdiet diam vehicula. Duis et nisi sed urna blandit bibendum et sit amet erat. Suspendisse | ||
potenti. Curabitur consequat volutpat arcu nec elementum. Etiam a turpis ac libero varius condimentum. Maecenas sollicitudin | ||
felis aliquam tortor vulputate, ac posuere velit semper. | ||
</p> | ||
<p> | ||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur ullamcorper turpis vel commodo scelerisque. Phasellus | ||
luctus nunc ut elit cursus, et imperdiet diam vehicula. Duis et nisi sed urna blandit bibendum et sit amet erat. Suspendisse | ||
potenti. Curabitur consequat volutpat arcu nec elementum. Etiam a turpis ac libero varius condimentum. Maecenas sollicitudin | ||
felis aliquam tortor vulputate, ac posuere velit semper. | ||
</p> | ||
<p> | ||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur ullamcorper turpis vel commodo scelerisque. Phasellus | ||
luctus nunc ut elit cursus, et imperdiet diam vehicula. Duis et nisi sed urna blandit bibendum et sit amet erat. Suspendisse | ||
potenti. Curabitur consequat volutpat arcu nec elementum. Etiam a turpis ac libero varius condimentum. Maecenas sollicitudin | ||
felis aliquam tortor vulputate, ac posuere velit semper. | ||
</p> | ||
<p> | ||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur ullamcorper turpis vel commodo scelerisque. Phasellus | ||
luctus nunc ut elit cursus, et imperdiet diam vehicula. Duis et nisi sed urna blandit bibendum et sit amet erat. Suspendisse | ||
potenti. Curabitur consequat volutpat arcu nec elementum. Etiam a turpis ac libero varius condimentum. Maecenas sollicitudin | ||
felis aliquam tortor vulputate, ac posuere velit semper. | ||
</p> | ||
<p> | ||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur ullamcorper turpis vel commodo scelerisque. Phasellus | ||
luctus nunc ut elit cursus, et imperdiet diam vehicula. Duis et nisi sed urna blandit bibendum et sit amet erat. Suspendisse | ||
potenti. Curabitur consequat volutpat arcu nec elementum. Etiam a turpis ac libero varius condimentum. Maecenas sollicitudin | ||
felis aliquam tortor vulputate, ac posuere velit semper. | ||
</p> | ||
</article> | ||
<div class="spacer"></div> | ||
<div class="overlay-container"> | ||
<amp-img layout=responsive width=1600 height=900 src="https://picsum.photos/1600/900?image=981"></amp-img> | ||
<h1 class="overlay-top" amp-fx="parallax" data-parallax-factor="0.8"> | ||
<span class="title">Slow Lorem Ipsum Dolor Sit Lorem Ipsum<span> | ||
</h1> | ||
</div> | ||
<div class="spacer"></div> | ||
<div class="overflow-window" id="scrollToMe"> | ||
<amp-img amp-fx="parallax" data-parallax-factor="1.2" layout=responsive width=900 height=1600 src="https://picsum.photos/900/1600?image=736"></amp-img> | ||
</div> | ||
<div class="spacer"></div> | ||
<div class="spacer"></div> | ||
</article> | ||
</main> | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
/** | ||
* Copyright 2018 The AMP HTML Authors. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS-IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import {AmpEvents} from '../../../src/amp-events'; | ||
import {listen} from '../../../src/event-helper'; | ||
import {iterateCursor} from '../../../src/dom'; | ||
import {dev, user, rethrowAsync} from '../../../src/log'; | ||
import {map} from '../../../src/utils/object'; | ||
import {Services} from '../../../src/services'; | ||
import {ParallaxProvider} from './providers/parallax'; | ||
|
||
const TAG = 'amp-fx-collection'; | ||
|
||
/** | ||
* Enum for list of supported visual effects. | ||
* @enum {string} | ||
*/ | ||
const FxType = { | ||
PARALLAX: 'parallax', | ||
}; | ||
|
||
/** | ||
* Map of fx type to fx provider class. | ||
* @type {Object<FxType, function(new:FxProviderInterface, !../../../src/service/ampdoc-impl.AmpDoc)>} | ||
*/ | ||
const fxProviders = map({ | ||
[FxType.PARALLAX]: ParallaxProvider, | ||
}); | ||
|
||
/** | ||
* Bootstraps elements that have `amp-fx=<fx1 fx2>` attribute and installs | ||
* the specified effects on them. | ||
*/ | ||
class AmpFxCollection { | ||
|
||
/** | ||
* @param {!../../../src/service/ampdoc-impl.AmpDoc} ampdoc | ||
*/ | ||
constructor(ampdoc) { | ||
|
||
/** @private @const {!../../../src/service/ampdoc-impl.AmpDoc} */ | ||
this.ampdoc_ = ampdoc; | ||
|
||
/** @private @const {!Document|!ShadowRoot} */ | ||
this.root_ = ampdoc.getRootNode(); | ||
|
||
/** @private @const {!Array<!Element>} */ | ||
this.seen_ = []; | ||
|
||
/** @private @const {!../../../src/service/viewer-impl.Viewer} */ | ||
this.viewer_ = Services.viewerForDoc(ampdoc); | ||
|
||
/** @private @const {!Object<FxType, FxProviderInterface>} */ | ||
this.fxProviderInstances_ = map(); | ||
|
||
Promise.all([ | ||
ampdoc.whenReady(), | ||
this.viewer_.whenFirstVisible(), | ||
]).then(() => { | ||
// Scan when page becomes visible. | ||
this.scan_(); | ||
// Rescan as DOM changes happen. | ||
listen(this.root_, AmpEvents.DOM_UPDATE, this.scan_.bind(this)); | ||
}); | ||
} | ||
|
||
/** | ||
* Scans the root for fx-enabled elements and registers them with the | ||
* fx provider. | ||
*/ | ||
scan_() { | ||
const fxElements = this.root_.querySelectorAll('[amp-fx]'); | ||
iterateCursor(fxElements, fxElement => { | ||
if (this.seen_.includes(fxElement)) { | ||
return; | ||
} | ||
|
||
// Don't break for all components if only a subset are misconfigured. | ||
try { | ||
this.register_(fxElement); | ||
this.seen_.push(fxElement); | ||
} catch (e) { | ||
rethrowAsync(e); | ||
} | ||
}); | ||
} | ||
|
||
/** | ||
* Registers an fx-enabled element with its requested fx providers. | ||
* @param {!Element} fxElement | ||
*/ | ||
register_(fxElement) { | ||
dev().assert(fxElement.hasAttribute('amp-fx')); | ||
dev().assert(!this.seen_.includes(fxElement)); | ||
dev().assert(this.viewer_.isVisible()); | ||
|
||
const fxTypes = this.getFxTypes_(fxElement); | ||
|
||
fxTypes.forEach(fxType => { | ||
const fxProvider = this.getFxProvider_(fxType); | ||
fxProvider.installOn(fxElement); | ||
}); | ||
} | ||
|
||
/** | ||
* Returns the array of fx types this component has specified as a | ||
* space-separated list in the value of `amp-fx` attribute. | ||
* e.g. `amp-fx="parallax fade-in" | ||
* | ||
* @param {!Element} fxElement | ||
* @returns {!Array<!FxType>} | ||
*/ | ||
getFxTypes_(fxElement) { | ||
dev().assert(fxElement.hasAttribute('amp-fx')); | ||
const fxTypes = fxElement.getAttribute('amp-fx') | ||
.trim() | ||
.toLowerCase() | ||
.split(/\s+/); | ||
|
||
user().assert(fxTypes.length, 'No value provided for `amp-fx` attribute'); | ||
|
||
// Validate that we support the requested fx types. | ||
fxTypes.forEach(fxType => { | ||
user().assertEnumValue(FxType, fxType, 'amp-fx'); | ||
}); | ||
|
||
return fxTypes; | ||
} | ||
|
||
/** | ||
* Given an fx type, instantiates the appropriate provider if needed and | ||
* returns it. | ||
* @param {FxType} fxType | ||
*/ | ||
getFxProvider_(fxType) { | ||
dev().assert(fxProviders[fxType], | ||
`No provider for ${fxType} found, did you forget to register it?`); | ||
|
||
if (!this.fxProviderInstances_[fxType]) { | ||
this.fxProviderInstances_[fxType] = new fxProviders[fxType](this.ampdoc_); | ||
} | ||
return this.fxProviderInstances_[fxType]; | ||
} | ||
} | ||
|
||
/** | ||
* Defines the expected interface all FxProviders need to implement. | ||
* @interface | ||
*/ | ||
export class FxProviderInterface { | ||
|
||
/** | ||
* @param {!../../../src/service/ampdoc-impl.AmpDoc} unusedAmpDoc | ||
*/ | ||
constructor(unusedAmpDoc) {} | ||
|
||
/** | ||
* | ||
* @param {!Element} unusedElement | ||
*/ | ||
installOn(unusedElement) {} | ||
}; | ||
|
||
AMP.extension(TAG, '0.1', AMP => { | ||
AMP.registerServiceForDoc(TAG, AmpFxCollection); | ||
}); |
Oops, something went wrong.