This repository has been archived by the owner on Apr 4, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfontloader.coffee
292 lines (175 loc) · 5.27 KB
/
fontloader.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
###
Fontloader
@steveruizok
# Introduction
Using non-standard fonts can create big headaches for your Framer projects. This
module ensures that all of your local or web fonts are correctly loaded before
your code runs.
# Installation
1. Drop `fontloader.coffee` into your project's modules folder
2. Place local copies of your fonts (ie, 'YourFont-Regular.ttf) into your project's folder
3. Require this module at the top your project's code.
If you're loading local files...
```coffeescript
{ loadLocalFonts } = require 'fontloader'
```
If you're loading web fonts...
```coffeescript
{ loadWebFonts } = require 'fontloader'
```
# Usage
The module's two functions, loadLocalFonts and loadWebFonts, both take one or more objects
as separate arguments. These objects share two properties: `fontFamily` (the name of the font)
and `fontWeight` (the weight to load). If you're loading local fonts, you'll also need to
provide `src`, the path for the file to load.
## loadWebFonts(fonts)
```coffeescript
amitaRegular =
fontFamily: "Amita"
fontWeight: 400
amitaBold =
fontFamily: "Amita"
fontWeight: 700
monoton =
fontFamily: "Monoton"
fontWeight: 500
loadWebFonts([amitaRegular, amitaBold, monoton])
## loadLocalFonts(fonts)
```coffeescript
amitaRegular =
fontFamily: "Amita"
fontWeight: 400
src: "Amita-Regular.ttf"
amitaBold =
fontFamily: "Amita"
fontWeight: 700
src: "Amita-Bold.ttf"
monoton =
fontFamily: "Monoton"
fontWeight: 500
src: "Monoton-Regular.ttf"
loadLocalFonts([amitaRegular, amitaBold, monoton])
```
## Local Paths
By default, this module will look for fonts in the root of your project's
folder (i.e. myProject.framer/Monoton-Regular.ttf). If I wanted to put the
font somewhere else, such as a folder called fonts, I would include this
in the `src`.
```coffeescript
loadLocalFonts
fontFamily: "Monoton"
fontWeight: 500
src: "fonts/Monoton-Regular.ttf"
```
# About
TextLayers automatically set their size based on the text they contain.
If your TextLayers get created before the font is actually loaded, then
they'll set their size based on the standard device font. Then, as the
font actually loads, the text inside of the TextLayer will adjust to the
correct size and appearance, but the TextLayer will remain at the first size.
1. The TextLayer instance is created, sized using the standard size.
______________
[ hello world! ]
2. The non-standard font loads, but the TextLayer doesn't update.
______________
[ h e l l o w ]o r l d !
In addition to giving an easy way to load local fonts, this module tests
to see whether each of your fonts have loaded, then restarts the prototype
once they have all loaded.
###
# Load Local Fonts
exports.loadLocalFonts = (fonts) ->
unless _.isArray(fonts)
fonts = [fonts]
Framer.DefaultContext.visible = false
# ----------------
# CSS Insert
cssString = ""
for font in fonts
cssString += """
@font-face {
font-family: #{font.fontFamily};
font-weight: #{font.fontWeight ? 400};
font-style: #{font.fontStyle ? "normal"};
src: url(#{font.src});
}
"""
Utils.insertCSS(cssString)
loadFonts(fonts)
# Load Web Fonts
exports.loadWebFonts = (fonts) ->
if not _.isArray(fonts) then fonts = [fonts]
Framer.DefaultContext.visible = false
# ----------------
# CSS Insert
for font in fonts
Utils.loadWebFont(font.fontFamily, font.fontWeight ? 400)
loadFonts(fonts)
loadFonts = (fonts) ->
# ----------------
# Test Elements
testBed = document.createElement "div"
_.assign testBed.style,
position: "absolute"
fontFamily: "nonsense"
padding: 0
opacity: 0
document.body.appendChild(testBed)
controlSpan = document.createElement "span"
_.assign controlSpan.style,
position: "absolute"
fontSize: "200px"
top: 0
left: 0
controlSpan.textContent = "Hello world!"
testBed.appendChild(controlSpan)
tests = fonts.map (f, i) ->
testSpan = document.createElement "span"
testSpan.textContent = "Hello world!"
_.assign testSpan.style,
fontFamily: f.fontFamily
position: "absolute"
fontSize: "200px"
top: (100 * i) + "px"
left: 0
testBed.appendChild(testSpan)
return testSpan
# ----------------
# Functions
# Test for fonts
testForFonts = ->
results = tests.map (testSpan) ->
return testSpan.clientWidth isnt controlSpan.clientWidth
for result in results
unless result
return false
return true
# Loop the test until the font is found
loopForFonts = (i) ->
if i > 20
throw "Couldn't find that font."
i++
fontsAreLoaded = testForFonts()
if fontsAreLoaded
complete(true)
return
Utils.delay .5, -> loopForFonts(i)
# Finish up - clear divs and restart the prototype if we looped
complete = (reset = false) ->
document.body.removeChild(testBed)
Framer.DefaultContext.visible = true
if reset
Utils.delay .01, ->
Framer.CurrentContext.reset()
CoffeeScript.load("app.coffee")
# ----------------
# Kickoff
# Before trying to loop, see if the fonts are already loaded. If
# they are, clean up and don't loop again; if not, start the loop.
# Since this code will run even after our loop completes, we want
# to be sure not to get stuck in an endless reload loop.
fontsAreLoaded = testForFonts()
if fontsAreLoaded
complete()
else
loopForFonts(0)