Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ios, android): support loading font dynamically #4067

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/api/hippy-react/modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,22 @@ AsyncStorage 是一个简单的、异步的、持久化的 Key-Value 存储系

---

# FontLoaderModule

提供通过url动态下载远程字体或者动态加载JSBundle包中字体的能力,下载的远程字体将保存在应用Cache目录下,由Hippy统一管理,可能被终端系统删除。常用字体不推荐使用该模块动态远程下载。


## 方法

### FontLoaderModule.load

`(fontFamily: string, fontUrl: string) => Promise<string>` 通过fontUrl异步下载字体,下载完成后会刷新终端文本。

> - fontFamily - 下载字体的字体家族,用于保存文件和检索字体文件
> - fontUrl - 下载字体的地址,可以是http网络地址,也可以本地文件地址或者以“hpfile://./”为前缀的JSbundle包中的相对地址

---

# NetInfo

[[NetInfo 范例]](//github.com/Tencent/Hippy/tree/master/examples/hippy-react-demo/src/modules/NetInfo)
Expand Down
15 changes: 15 additions & 0 deletions docs/api/hippy-vue/vue-native.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,21 @@ console.log(Vue.Native.getElemCss(this.demon1Point)) // => { height: 80, left: 0

---

# FontLoaderModule

提供通过url动态下载远程字体或者动态加载JSBundle包中字体的能力,下载的远程字体将保存在应用Cache目录下,由Hippy统一管理,可能被终端系统删除。常用字体不推荐使用该模块动态远程下载。

## 方法

### FontLoader.load

`(fontFamily: string, fontUrl: string) => Promise<string>` 通过fontUrl异步下载字体,下载完成后会刷新终端文本。

> * fontFamily - 下载字体的字体家族,用于保存文件和检索字体文件
> * fontUrl - 下载字体的地址,可以是http网络地址,也可以本地文件地址或者以“hpfile://./”为前缀的JSbundle包中的相对地址

---

# ImageLoader

通过该模块可以对远程图片进行相应操作
Expand Down
8 changes: 8 additions & 0 deletions docs/api/style/appearance.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,14 @@
| ------------------------ | ---- | ------------ |
| enum('normal', 'italic') | 否 | Android、iOS |

# fontUrl

动态加载字体的url,会在渲染时异步动态加载,可以是远程字体地址或者是使用JSBundle包中字体路径的相对地址。

| 类型 | 必需 | 支持平台 |
| ------------------------ | ---- | ------------ |
| string | 否 | Android、iOS |

# fontWeight

字体粗细
Expand Down
141 changes: 141 additions & 0 deletions driver/js/examples/hippy-react-demo/src/modules/FontLoader/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import React from 'react';
import {
View,
ScrollView,
StyleSheet,
Text,
TextInput,
FontLoaderModule,
} from '@hippy/react';

const styles = StyleSheet.create({
itemTitle: {
alignItems: 'flex-start',
justifyContent: 'center',
height: 40,
borderWidth: 1,
borderStyle: 'solid',
borderColor: '#e0e0e0',
borderRadius: 2,
backgroundColor: '#fafafa',
padding: 10,
marginTop: 10,
},
wrapper: {
borderColor: '#eee',
borderWidth: 1,
borderStyle: 'solid',
paddingHorizontal: 10,
paddingVertical: 5,
marginVertical: 10,
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'flex-start',
},
infoContainer: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-start',
marginTop: 5,
marginBottom: 5,
flexWrap: 'wrap',
},
text_style: {
fontSize: 16,
},
input_url_style: {
height: 60,
marginVertical: 10,
fontSize: 16,
color: '#242424',
},
input_font_style: {
height: 30,
marginVertical: 10,
fontSize: 16,
color: '#242424',
},
});

export default class LoadFontExample extends React.Component {
constructor(props) {
super(props);
this.state = {
fontFamily: '',
inputFontFamily: '',
fontUrl: '',
loadState: '',
};
}

fillExample() {
this.setState({ inputFontFamily: 'TencentSans W7' });
this.setState({ fontUrl: 'https://infra-packages.openhippy.com/test/resources/TencentSans_W7.ttf' });
// this.setState({ fontUrl: 'hpfile://./assets/hanyihuaxianzijianti.ttf' }
}

async loadFont() {
this.setState({ fontFamily: this.state.inputFontFamily });
await FontLoaderModule.load(this.state.fontFamily, this.state.fontUrl)
.then((result) => {
this.setState({ loadState: result });
})
.catch((error) => {
this.setState({ loadState: error });
});
}

render() {
return (
<ScrollView style={{ paddingHorizontal: 10 }}>
<View style={styles.itemTitle}>
<Text>通过组件fontUrl属性动态下载并使用字体</Text>
</View>
<Text style={styles.text_style}
fontFamily='TencentSans W3'
fontUrl='https://infra-packages.openhippy.com/test/resources/TencentSans_W3.otf'>
This sentence will use font 'TencentSans W3' downloaded dynamically according to 'fontUrl' property.
</Text>
<Text style={styles.text_style}
fontFamily='TencentSans W3'>
这句话将使用通过fontUrl属性下载的'TencentSans W3'字体.
</Text>
<View style={styles.itemTitle}>
<Text>下载并使用字体</Text>
</View>
<Text style={styles.text_style} fontFamily={this.state.fontFamily}>
This sentence will be set the specific font after download.
</Text>
<Text style={styles.text_style} fontFamily={this.state.fontFamily}>
这句话将用指定的下载字体显示。
</Text>
<TextInput
style={styles.input_font_style}
fontFamily={this.state.fontFamily}
placeholder="Input font family"
value={this.state.inputFontFamily}
onChangeText={(text) => this.setState({inputFontFamily: text})}
/>
<TextInput
style={styles.input_url_style}
placeholder="Input font url"
value={this.state.fontUrl}
onChangeText={(text) => this.setState({fontUrl: text})}
/>
<View style={[styles.wrapper]}
>
<View style={[styles.infoContainer]}>
<View style={{ backgroundColor: 'grey', padding: 10, borderRadius: 10, marginRight: 10 }} onClick={() => this.fillExample()}>
<Text style={{ color: 'white' }}>填充示例</Text>
</View>
<View style={{ backgroundColor: 'grey', padding: 10, borderRadius: 10, marginRight: 10 }} onClick={() => this.loadFont()}>
<Text style={{ color: 'white' }}>下载字体</Text>
</View>
</View>
</View>
<Text>load state: {this.state.loadState}</Text>
</ScrollView>
);
}
}
1 change: 1 addition & 0 deletions driver/js/examples/hippy-react-demo/src/modules/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export { default as AsyncStorage } from './AsyncStorage';
export { default as NetInfo } from './NetInfo';
export { default as WebSocket } from './WebSocket';
export { default as UIManagerModule } from './UIManagerModule';
export { default as FontLoader } from './FontLoader';
8 changes: 8 additions & 0 deletions driver/js/examples/hippy-react-demo/src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,14 @@ export default [
type: Type.MODULE,
},
},
{
path: '/FontLoader',
name: 'FontLoader 模块',
component: PAGE_LIST.FontLoader,
meta: {
type: Type.MODULE,
},
},
{
path: '/Others',
name: 'Others',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,48 @@
</div>
</div>

<!-- FontLoader使用 -->
<div
v-if="Vue.Native.FontLoader"
class="native-block"
>
<label class="vue-native-title">FontLoader 使用</label>
<span :fontFamily="fontFamily">
This sentence will be set the specific font after download.
</span>
<span :fontFamily="fontFamily">
这句话将用指定的下载字体显示。
</span>
<input
:fontFamily="fontFamily"
v-model="inputFontFaimly"
placeholder="Input font family"
placeholder-text-color="#40b883"
:editable="true"
>
<input
v-model="fontUrl"
placeholder="Input font url"
placeholder-text-color="#40b883"
:editable="true"
>
<div class="item-wrapper">
<button
class="item-button"
@click="fillExample"
>
<span>填写示例</span>
</button>
<button
class="item-button"
@click="load"
>
<span>下载字体</span>
</button>
</div>
<span>load state: {{ loadState }}</span>
</div>

<!-- Fetch使用 -->
<div
class="native-block"
Expand Down Expand Up @@ -323,6 +365,10 @@ export default {
cookieString: 'ready to set',
cookiesValue: '',
hasLayout: false,
inputFontFaimly: '',
fontUrl: '',
fontFamily: '',
loadState: '',
};
},
async created() {
Expand All @@ -334,7 +380,7 @@ export default {
this.netInfoListener = Vue.Native.NetInfo.addEventListener('change', (info) => {
this.netInfoText = `收到通知: ${info.network_info}`;
});
fetch('https://hippyjs.org', {
fetch('https://openhippy.com/', {
mode: 'no-cors', // 2.14.0 or above supports other options(not only method/headers/url/body)
}).then((responseJson) => {
this.fetchText = `成功状态: ${responseJson.status}`;
Expand Down Expand Up @@ -402,12 +448,29 @@ export default {
console.log('ImageLoader getSize', result);
this.imageSize = `${result.width}x${result.height}`;
},
async load() {
this.fontFamily = this.inputFontFaimly;
console.log('fontFamily:', this.fontFamily)
console.log('fontUrl:', this.fontUrl)
let result;
try {
result = await Vue.Native.FontLoader.load(this.fontFamily, this.fontUrl);
} catch (error) {
result = error.message;
}
this.loadState = result;
},
fillExample() {
this.inputFontFaimly = 'HYHuaXianZi J';
this.fontUrl = 'https://zf.sc.chinaz.com/Files/DownLoad/upload/2024/1009/hanyihuaxianzijianti.ttf';
},

setCookie() {
Vue.Native.Cookie.set('https://hippyjs.org', 'name=hippy;network=mobile');
Vue.Native.Cookie.set('https://openhippy.com/', 'name=hippy;network=mobile');
this.cookieString = '\'name=hippy;network=mobile\' is set';
},
getCookie() {
Vue.Native.Cookie.getAll('https://hippyjs.org').then((cookies) => {
Vue.Native.Cookie.getAll('https://openhippy.com/').then((cookies) => {
this.cookiesValue = cookies;
});
},
Expand Down
Loading
Loading