-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
336 lines (269 loc) · 11.7 KB
/
index.html
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
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
<!DOCTYPE html><head>
<meta charset="utf-8" />
<base lang="en-US" title="Fancy Font Flipping For Fun!">
<!-- CSS -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Barlow:wght@200;300;400;500;600;700&display=swap" rel="stylesheet">
<style>
body {
position: relative;
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: Barlow, arial, sans-serif;
background-color: #F9F2DD;
}
#mainBlock {
padding: 16px 2px;
text-align: center;
--samplesBG: #bad;
--samplesBGhalf: #bad;
background-color: #a0a0a0;
background-color: var(--samplesBG);
}
.patch {
display: inline-block;
margin: 6px;
padding: 16px 4px;
vertical-align: middle;
width: 110px;
height: 150px;
text-align: center;
line-height: 1.1;
border-radius: 20px;
text-shadow: 4px 5px 4px var(--textShadow);
box-shadow:
inset 6px 6px 14px #1346,
inset 2px 2px 9px 2px var(--samplesBGhalf),
2px 2px 6px #2468;
}
h1 {
position: relative;
margin: 16px 0 -14px;
padding: 16px 26px 16px 132px;
color: #308;
top: -16px;
text-align: left;
font-style: oblique;
background-color: #efe8aa;
box-shadow: inset 6px 6px 14px #1349,
inset 2px 2px 9px 2px #fff9,
2px 2px 6px #2468;
}
h2, summary {
position: relative;
margin: 8px 0 0 132px;
color: #308;
top:-6px;
font-size: 1.4em;
text-align: left;
font-style: oblique;
}
h3 {
position: relative;
margin: 12px 0;
padding: 4px 24px 22px 162px;
color: #308;
top: 18px;
font-size: 1.4em;
text-align: left;
font-style: oblique;
background-color: #efe8aa;
box-shadow: inset 6px 6px 14px #1349,
inset 2px 2px 9px 2px #fff9,
2px 2px 6px #2468;
}
.inputLabel {position: relative;font-size: 0.6em; top: -8px;}
.inputLabel input {
position: relative;
margin: -12px 0 0 24px;
width: 120px;
height: 50px;
top: 14px;
background: currentColor;
border: 2px solid #123;
border-radius: 18px;
}
p {
position: relative;
max-width: 720px;
left:112px;
margin: 4px 24px;
padding: 4px 12px;
vertical-align: middle;
text-align: left;
color: #005;
font-size: 18.8px;
font-weight: 400;
}
.copy {
margin: 2px;
padding: 4px;
vertical-align: bottom;
text-align: center;
font-size: 12px;
}
</style>
</head>
<body>
<h1>Fancy Font Flipping For Fun!<span class="inputLabel"><input id="picker" type="color" onBlur="setBG(value)" onInput="setBG(value)" value="#a0a0a0" /> ⇦ Set Page Background</span> </h1>
<details><summary>Automatic Font Color based on Background Lightness (v02)</summary>
<p>Each patch has data which also serves as an example. The font is smaller than optimum to stress the critical importance of spatial frequency.
<p>The top few lines are those automatically set based on the background color, and should always be easilly readable. The bottom line is the opposite color for comparison purposes, and may often be unreadable.
<p>The technology shown here is part of the <a href="https://github.com/Myndex/SAPC-APCA#apca-the-revolution-will-be-readable">SAPC Research Project. </a></details>
<div id="mainBlock">
</div>
<div class="copy">Copyright © 2021 by Myndex Research. All Rights Reserved.
</div>
</body>
<script>
///// FOR DISCUSSION OF THIS TOPIC SEE: ///////////////////////////////////
///// https://gist.github.com/Myndex/e1025706436736166561d339fd667493
///// OR
///// See: https://stackoverflow.com/a/69869976/10315269
/////
///// Also See: https://www.myndex.com/APCA/
///// BEGIN DEMO /////////////////////////////////////////////////////////
//////// APPEARANCE SETTINGS ////////////////////////////
const textShadow = "0.0"; // text shadow, is an alpha 0.0 to 1.0. 0.0 is OFF
// Note that it affects perceived text contrast!
const shadowSelect = true; // trendy shadows set true or false
const font = 12; // pick a value 8 to 14
const fontWeight = 300; // pick a value 200,300,400,500,600,700
const offset = font * 3.33;// amount of text size increase for mid contrast
// contrast is related to spatial frequency
// i.e. size & weight of the font
const greyscales = 11; // How many patches of grey from black to white
// Set to 0 to disable greyscales
// Greyscales are useful to better see flip point
// Suggested values 11, 31, 76 — you want the flip
// in the horizontal middle to see side by side.
const greyAlternates = 0; // 1 = show alternate grey exponents.
// 0 = show only main page lightness exponent
//////// PERCEPTUAL LIGHTNESS SETTINGS ////////////////////////////
const rgbTRC = 2.2; // 2.213; // 2.4; // The simple sRGB exponent
const rgbEnc = 1 / rgbTRC; // The sRGB inversion
const lightExp = 0.678 //0.678; // 0.678; // 0.7833;
// SAPC perceptual contrast lightness (mode a) (experimental)
const darkExp = 1 / lightExp; // Inversion of lightExp
const percOffset = 0.03;
// For grayscale based on flip curve (or not)
const darkExpGrad = darkExp; // 3.5; // Smoother grad
const percOffGrad = percOffset; // 0.3; // Smoother rag
//////// FLIP POINT SETTINGS ////////////////////////////
// const flipPointY = 0.42; // for Y flip, unused.
const flipPointLs = 0.5; // flip factor
const lo = 0.35, hi = 0.65; // Ls Mid range area (font enlarging)
// ( lo + hi ) * flipPointLs should be 0.5
const centerLs = ( lo + hi ) * flipPointLs; // flip point
//////// GREYSCALE SETTINGS ////////////////////////////
// Place exponents in this array to
// make additional grayscale grads
const perceptExp = [darkExpGrad,3.5,1/0.75,1/0.678,1/0.5,1/0.4,1/0.4108,1/0.333333]; // last is ~LAB
const greyOffset = [percOffGrad,0.3,0,0,0,0,0,0.16]; // last is LAB
const patches = 1001; // total patches including greyscale
let gsc = 0; // grayscale counter
const greyLength = greyscales - 1;
const greyRows = 1 + greyAlternates * (perceptExp.length - 2); // Number of differrent greyscale rows
//////// DOM VARIABLES ////////////////////////////
let container = document.getElementById('mainBlock');
let picker = document.getElementById('picker');
// container.style.setProperty("--textShadow", "rgba(0,0,0,"+textShadow+")");
let boxShadow = (shadowSelect) ?
"--textShadow: rgba(0,0,0,"+textShadow+");" :
"box-shadow: none; text-shadow:none;";
//////// MISC VARIABLES ////////////////////////////
// vars needed for rand colors and output
let r = 0.0, g = 0.0, b = 0.0;
let elemt;
let bgRGB = [0,0,0], bgColor = "#bad", textAttr = [];
let i = 0;
//////// FUNCTIONS ////////////////////////////
///// setBG /////
// utility to set the underlying BG color
// Accessed using the color picker
function setBG (bg = "#bbaadd") {
// container.setAttribute('style','background-color:' + bg );
container.style.setProperty("--samplesBG", bg);
container.style.setProperty("--samplesBGhalf", bg + "88");
picker.setAttribute('style','color:' + bg );
}; // Sets the overall page background.
// Notice how black or white changes your perception of contrast
///// getTextAttributes /////
function getTextAttributes (Rs,Gs,Bs,pExp = darkExp, pOff = percOffset) { // Do the stuff
let textSize = font;
let textWeight = fontWeight;
let Ys = Math.pow(Rs,rgbTRC) * 0.2126 +
Math.pow(Gs,rgbTRC) * 0.7152 +
Math.pow(Bs,rgbTRC) * 0.0722; // Andy's Easy Luminance Estimate for sRGB.
// For Rec709 HDTV change the 2.2 to 2.4,
// and use different coefficients for P3 etc!!
let Ls = Math.pow(Ys, 1/pExp) * (pOff + 1) - pOff; // Ls is SAPC Screen lightness, similar to L* but
// for self illuminated monitors & contrast
// perceptual text color flipper.
let textColor = (Ls < centerLs) ? ["#fff","#000"] : ["#000","#fff"];
// let textColor = (Ys < flipPointY) ? ["#fff","#000"] : ["#000","#fff"]; // alt luminance text color flipper.
if (Ls > lo && Ls < hi) { // Determine center based on range.
let offsetF = offset;
offsetF = (Ls < centerLs) ? (Ls - lo) * offsetF : (hi - Ls) * offsetF;
textSize = textSize + offsetF;
textWeight = fontWeight;
} // scale up fonts for the lower contrast mid luminances.
// **Loosely** based on part of APCA for WCAG 3 beta (spot reading)
return [textColor[0],textSize.toFixed(1) + 'px',textWeight,(Ys*100).toFixed(1),
(Ls*100).toFixed(1), textColor[1], pExp.toFixed(3),]
}; // End getTextAttributes
///// createRGB /////
// Creates the greyscale and random colors
// There is the assumption that the random values are already
// in sRGB space so random colors are better distributed
let createRGB = function (LsValue) { // Create random colors and greyscales
if (greyscales && LsValue < greyLength * greyRows + greyRows) {// perceptual greyscale
if (LsValue > (greyLength * (gsc + 1) + (1 * gsc))) { gsc++ };
r = g = b = Math.pow(Math.pow((((LsValue -
(greyLength*gsc+(gsc*1)))/greyLength)+greyOffset[gsc])/
(greyOffset[gsc]+1),perceptExp[gsc]),rgbEnc);
} else {
gsc = 0;
r = Math.random();
g = Math.random();
b = Math.random();
};
return [r, g, b, perceptExp[gsc], greyOffset[gsc]]
}; // End createRGB
///// intRGBcolor /////
// take decimal 0-1 RGB and make #hex string
// NOTE: This assumes sRGB encoded values on input
let intRGBcolor = function (r, g, b) {
return '#'+((r*255)&0xff).toString(16).padStart(2,'0')
+((g*255)&0xff).toString(16).padStart(2,'0')
+((b*255)&0xff).toString(16).padStart(2,'0');
}; // End intRGBcolor
///////// MAIN //////////////////////
setBG('#a0a0a0'); // starting BG color
///// OUTPUT (NAKED LOOP) /////
for ( ; i < patches; i++) { // output loop
bgRGB = createRGB(i);
bgColor = intRGBcolor(bgRGB[0], bgRGB[1], bgRGB[2]);
textAttr = getTextAttributes(bgRGB[0], bgRGB[1], bgRGB[2]); //, bgRGB[3], bgRGB[4]);
elemt = document.createElement('div');
elemt.setAttribute('class', 'patch');
elemt.setAttribute('style','font-size: ' + textAttr[1]
+ '; font-weight:' + textAttr[2]
+ '; background-color:' + bgColor
+ '; color:' + textAttr[0]
+ ';' + boxShadow
);
elemt.innerHTML = bgColor+"<br>"+textAttr[1]+"<br>Ys " + textAttr[3]
+ "<br>Ls " + textAttr[4]
+ "<br>| | |||||||||| | |<br><span style='position:relative;"
+ "top:-6px; color:" + textAttr[5]
+ "'>| | |||||||||| | |<br>pEx "
+ textAttr[6] + "</span>"; // Text on Patches
container.appendChild(elemt);
} // End loop
///// END DEMO ///////////////////////////////////////////////////////////
//// Copyright © 2021 by Myndex Research. All Rights Reserved. ////////////
</script>
</html>