Skip to content

Instantly share code, notes, and snippets.

@vincentriemer
Created May 20, 2018 14:16
Show Gist options
  • Save vincentriemer/b8e5e97a92a44638a118016801d378cd to your computer and use it in GitHub Desktop.
Save vincentriemer/b8e5e97a92a44638a118016801d378cd to your computer and use it in GitHub Desktop.
Example React Native DOM native module which provides the ability to load fonts from the worker thread
/**
* This is the "native" module that runs on the main thread
* To add this to the bridge the exported class gets added to the `nativeModules` array in the `bootstrap.js` file.
*
* @flow
*/
import {
RCT_EXPORT_METHOD,
RCT_EXPORT_MODULE,
RCTFunctionTypePromise,
} from "react-native-dom";
import FontFaceObserver from "fontfaceobserver";
import type { RCTBridge } from "react-native-dom";
@RCT_EXPORT_MODULE("FontLoader")
export default class FontLoader {
bridge: RCTBridge;
constructor(bridge: RCTBridge) {
this.bridge = bridge;
}
@RCT_EXPORT_METHOD(RCTFunctionTypePromise)
loadFont(name: string, url: string, resolveId: number, rejectId: number) {
// generate font-face css string
const fontStyles = `@font-face {
src: url(${url});
font-family: ${name}
}`;
// create stylesheet
const style: any = document.createElement("style");
style.type = "text/css";
if (style.styleSheet) {
style.styleSheet.cssText = fontStyles;
} else {
style.appendChild(document.createTextNode(fontStyles));
}
// inject stylesheet
if (document.head) {
document.head.appendChild(style);
} else {
return this.bridge.callbackFromId(rejectId);
}
// load font
const font = new FontFaceObserver(name);
font
.load()
.then(this.bridge.callbackFromId(resolveId))
.catch(this.bridge.callbackFromId(rejectId));
}
}
/**
* This is the interface that's interacted with from the worker thread, inspired by the Expo font API
*
* @flow
*/
import { NativeModules } from "react-native";
import resolveAssetSource from "resolveAssetSource";
const FontLoader = NativeModules.FontLoader;
export const Font = {
loadedFonts: [],
isLoaded(fontName: string) {
return this.loadedFonts.includes(fontName);
},
loadAsync(fontConfig: { [fontName: string]: string }) {
return Promise.all(
Object.entries(fontConfig).map(([name, assetId]) => {
const asset = resolveAssetSource(assetId);
if (asset) {
return FontLoader.loadFont(name, asset.uri).then(() => {
this.loadedFonts.push(name);
});
} else {
return Promise.reject();
}
})
);
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment