-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
amp-font extension + Font loader with promises! -
- Loading branch information
1 parent
bcaac9b
commit ef040b6
Showing
11 changed files
with
1,000 additions
and
1 deletion.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
<!doctype html> | ||
<html ⚡> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>Font example</title> | ||
<link rel="canonical" href="amps.html" > | ||
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"> | ||
<style amp-custom> | ||
@font-face { | ||
font-family: 'Comic AMP'; | ||
font-style: normal; | ||
font-weight: 400; | ||
src: url(fonts/ComicAMP.ttf) format('truetype'); | ||
} | ||
|
||
@font-face { | ||
font-family: 'Comic AMP Bold'; | ||
font-style: bold; | ||
font-weight: 600; | ||
src: url(fonts/ComicAMPBold.ttf) format('truetype'); | ||
} | ||
|
||
.comic-amp-font-loaded { | ||
font-family: 'Comic AMP', serif, sans-serif; | ||
} | ||
|
||
.comic-amp-bold-font-loaded .comic-amp-bold { | ||
font-family: 'Comic AMP Bold', serif, sans-serif; | ||
color: #000; | ||
} | ||
|
||
h1 { | ||
font-size: 50px; | ||
font-weight: bold; | ||
} | ||
|
||
p { | ||
font-size: 20px; | ||
font-weight: normal; | ||
} | ||
|
||
.comic-amp-font-loading { | ||
color: #00f; | ||
} | ||
|
||
.comic-amp-bold-font-loading .comic-amp-bold { | ||
color: #0ff; | ||
} | ||
|
||
.comic-amp-font-missing, | ||
.comic-amp-bold-font-missing .comic-amp-bold { | ||
color: #f00; | ||
} | ||
</style> | ||
<script async custom-element="amp-font" src="https://cdn.ampproject.org/v0/amp-font-0.1.js"></script> | ||
<style>body {opacity: 0}</style><noscript><style>body {opacity: 1}</style></noscript> | ||
<script async src="https://cdn.ampproject.org/v0.js"></script> | ||
</head> | ||
<body class="comic-amp-font-loading comic-amp-bold-font-loading"> | ||
|
||
<h1> Lorem Ipsum </h1> | ||
|
||
<h2 class="comic-amp-bold">amp-font</h2> | ||
|
||
<p> | ||
"Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit..." | ||
"There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain..." | ||
</p> | ||
<p class="comic-amp-bold"> | ||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur gravida ipsum vel hendrerit ultricies. Sed bibendum erat sit amet dui mattis imperdiet. Duis feugiat lobortis neque nec accumsan. Nam lacinia placerat enim in cursus. Sed id gravida arcu, sed condimentum mauris. Vestibulum convallis risus ut est ultrices mollis. Curabitur sit amet lorem et leo maximus consectetur non aliquet risus. Pellentesque tempus malesuada eros quis convallis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi dolor risus, convallis eget bibendum at, auctor vel enim. Phasellus posuere dictum fermentum. | ||
</p> | ||
<p> | ||
Quisque ultricies id augue a convallis. Vivamus euismod est quis tellus laoreet lacinia. In quam tellus, mollis nec porta eget, volutpat sit amet nibh. Duis ac odio sem. Sed consequat, ante gravida fringilla suscipit, libero libero ullamcorper metus, nec porta est elit at est. Curabitur vel diam ligula. Nulla bibendum malesuada odio. | ||
</p> | ||
<p class="comic-amp-bold"> | ||
Pellentesque ultricies quam diam, sit amet sollicitudin ante imperdiet a. Pellentesque porta semper nisi, et lobortis est laoreet ac. Vivamus pulvinar egestas purus, vitae pharetra nisl mattis at. Duis gravida ac quam vel commodo. Pellentesque dignissim luctus magna, a fermentum ligula porttitor non. Duis sodales interdum urna, eu viverra elit dapibus vitae. Sed aliquet magna non erat suscipit, vel elementum nisl lacinia. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In eu tempor purus. Cras non libero vehicula, finibus arcu eget, eleifend nulla. Vestibulum non sollicitudin turpis. Fusce condimentum posuere risus nec congue. Curabitur aliquam lorem dolor. | ||
</p> | ||
<p> | ||
Sed mollis, justo ac volutpat gravida, nisl eros imperdiet massa, sed aliquam nulla odio in urna. Pellentesque eros urna, rutrum vel luctus id, ultrices a libero. Morbi ante justo, gravida et velit at, convallis tristique metus. Nam elementum luctus facilisis. Vestibulum nec augue dignissim, gravida odio nec, volutpat libero. Cras vitae sagittis tellus, sed tincidunt ipsum. Maecenas et mauris id nunc porttitor tempus sit amet at libero. | ||
</p> | ||
<p class="comic-amp-bold"> | ||
Aenean ullamcorper risus quam, molestie sodales lacus volutpat at. Nunc vulputate est ut faucibus faucibus. Proin posuere viverra vestibulum. Vestibulum pretium nunc ut euismod sollicitudin. Etiam ornare posuere libero. Vestibulum urna massa, viverra sed ullamcorper ac, hendrerit sed dui. Vestibulum interdum lectus tellus, ut consequat quam pulvinar vitae. Mauris porttitor nulla porta urna convallis accumsan. Curabitur eget ante in libero fringilla elementum. Curabitur tempus arcu massa, gravida tristique erat convallis vitae. Sed lacinia elit justo, eget mollis dui vehicula sit amet. Nunc dignissim condimentum nunc, id pulvinar purus mattis ut. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque lacinia nibh ac enim laoreet imperdiet. | ||
</p> | ||
|
||
<amp-font | ||
layout="nodisplay" | ||
font-family="Comic AMP" | ||
timeout="2000" | ||
on-error-remove-class="comic-amp-font-loading" | ||
on-error-add-class="comic-amp-font-missing" | ||
on-load-remove-class="comic-amp-font-loading" | ||
on-load-add-class="comic-amp-font-loaded"> | ||
</amp-font> | ||
<amp-font | ||
layout="nodisplay" | ||
font-family="Comic AMP Bold" | ||
timeout="3000" | ||
font-weight="bold" | ||
on-error-remove-class="comic-amp-bold-font-loading" | ||
on-error-add-class="comic-amp-bold-font-missing" | ||
on-load-remove-class="comic-amp-bold-font-loading" | ||
on-load-add-class="comic-amp-bold-font-loaded"> | ||
</amp-font> | ||
</body> | ||
</html> |
Binary file not shown.
Binary file not shown.
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,197 @@ | ||
/** | ||
* Copyright 2015 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. | ||
*/ | ||
|
||
|
||
/** | ||
* @fileoverview Triggers and monitors loading of custom fonts on AMP pages. | ||
* Example: | ||
* <code> | ||
* <amp-font | ||
* font-family="My Font" | ||
* timeout="3s" | ||
* font-weight="bold" | ||
* on-error-add-class="myfont2-missing" | ||
* on-error-remove-class="myfont3-loaded" | ||
* on-load-add-class="myfont2-loaded" | ||
* on-load-remove-class="myfont1-loaded" | ||
* layout="nodisplay"> | ||
* </amp-font> | ||
* </code> | ||
* | ||
* the amp-font element's layout type is nodisplay. | ||
*/ | ||
|
||
import {FontLoader} from './fontloader'; | ||
import {timer} from '../../../src/timer'; | ||
import * as style from '../../../src/style'; | ||
|
||
/** @private @const {number} */ | ||
const DEFAULT_TIMEOUT_ = 3000; | ||
|
||
/** @private @const {string} */ | ||
const DEFAULT_WEIGHT_ = '400'; | ||
|
||
/** @private @const {string} */ | ||
const DEFAULT_VARIANT_ = 'normal'; | ||
|
||
/** @private @const {string} */ | ||
const DEFAULT_STYLE_ = 'normal'; | ||
|
||
/** @private @const {string} */ | ||
const DEFAULT_SIZE_ = 'medium'; | ||
|
||
/** @private @const {number}*/ | ||
/** | ||
* https://output.jsbin.com/badore - is js bin experiment to test timeouts on | ||
* various mobile devices. Loade the page and try refreshing it to serve the | ||
* font from cache. | ||
* | ||
* Font load times (from the browser cache) documented as follows: | ||
* Wifi | ||
* iPhone6(iOs 9.1) - safari - 2ms ~ 14ms | ||
* Windows phone(8.1 Update 2) - IE - 20ms ~ 46ms | ||
* Nexus5 (Android 6.0.0) - Chrome(44.0.2403.133) - 24ms ~ 52ms | ||
* Samsung Galaxy S4 (Android 4.4.2) - Default Browser - 7ms - 24ms | ||
* | ||
* LTE | ||
* iPhone6(iOs 9.1) - safari - 6ms ~ 14ms | ||
* Nexus5 (Android 6.0.0) - Chrome(46.0.2) - 46ms ~ 100ms | ||
*/ | ||
const CACHED_FONT_LOAD_TIME_ = 100; | ||
|
||
|
||
export class AmpFont extends AMP.BaseElement { | ||
|
||
|
||
/** @override */ | ||
prerenderAllowed() { | ||
return true; | ||
} | ||
|
||
|
||
/** @override */ | ||
buildCallback() { | ||
/** @private @const {string} */ | ||
this.fontFamily_ = AMP.assert(this.element.getAttribute('font-family'), | ||
'The font-family attribute is required for <amp-font> %s', | ||
this.element); | ||
/** @private @const {string} */ | ||
this.fontWeight_ = | ||
this.element.getAttribute('font-weight') || DEFAULT_WEIGHT_; | ||
/** @private @const {string} */ | ||
this.fontStyle_ = | ||
this.element.getAttribute('font-style') || DEFAULT_STYLE_; | ||
/** @private @const {string} */ | ||
this.fontVariant_ = | ||
this.element.getAttribute('font-variant') || DEFAULT_VARIANT_; | ||
/** @private @const {!Document} */ | ||
this.document_ = this.getWin().document; | ||
/** @private @const {!Element} */ | ||
this.documentElement_ = this.document_.documentElement; | ||
/** @private @const {!FontLoader} */ | ||
this.fontLoader_ = new FontLoader(this.getWin()); | ||
this.startLoad_(); | ||
} | ||
|
||
|
||
/** | ||
* Starts to download the font. | ||
* @private | ||
*/ | ||
startLoad_() { | ||
/** @type FontConfig */ | ||
const fontConfig = { | ||
style: this.fontStyle_, | ||
variant: this.fontVariant_, | ||
weight: this.fontWeight_, | ||
size: DEFAULT_SIZE_, | ||
family: this.fontFamily_ | ||
}; | ||
this.fontLoader_.load(fontConfig, this.getTimeout_()).then(() => { | ||
this.onFontLoadSuccess_(); | ||
}).catch(error => { | ||
this.onFontLoadError_(); | ||
throw error; | ||
}); | ||
} | ||
|
||
|
||
/** | ||
* @private | ||
*/ | ||
onFontLoadSuccess_() { | ||
const addClassName = this.element.getAttribute('on-load-add-class'); | ||
const removeClassName = | ||
this.element.getAttribute('on-load-remove-class'); | ||
this.onFontLoadFinish_(addClassName, removeClassName); | ||
} | ||
|
||
|
||
/** | ||
* @private | ||
*/ | ||
onFontLoadError_() { | ||
const addClassName = this.element.getAttribute('on-error-add-class'); | ||
const removeClassName = | ||
this.element.getAttribute('on-error-remove-class'); | ||
this.onFontLoadFinish_(addClassName, removeClassName); | ||
} | ||
|
||
|
||
/** | ||
* @param {?string} addClassName css class to be added to the | ||
* document-element. | ||
* @param {?string} removeClassName css class to be removed from the | ||
* document-element. | ||
* @private | ||
*/ | ||
onFontLoadFinish_(addClassName, removeClassName) { | ||
if (addClassName) { | ||
this.documentElement_.classList.add(addClassName); | ||
} | ||
if (removeClassName) { | ||
this.documentElement_.classList.remove(removeClassName); | ||
this.document_.body.classList.remove(removeClassName); | ||
}; | ||
this.dispose_(); | ||
} | ||
|
||
|
||
/** | ||
* @private | ||
*/ | ||
dispose_() { | ||
this.fontLoader_ = null; | ||
} | ||
|
||
|
||
/** | ||
* Computes and returns the time (in ms) to wait for font download. | ||
* @returns {number} time (in ms) to wait for font download. | ||
* @private | ||
*/ | ||
getTimeout_() { | ||
let timeoutInMs = parseInt(this.element.getAttribute('timeout'), 10); | ||
timeoutInMs = isNaN(timeoutInMs) || timeoutInMs < 0 ? | ||
DEFAULT_TIMEOUT_ : timeoutInMs; | ||
timeoutInMs = Math.max( | ||
(timeoutInMs - timer.timeSinceStart()), CACHED_FONT_LOAD_TIME_); | ||
return timeoutInMs; | ||
} | ||
} | ||
|
||
|
||
AMP.registerElement('amp-font', AmpFont); |
Oops, something went wrong.