website: dynamic metrics update
This commit is contained in:
parent
118377c5ed
commit
fa662b9e1d
8 changed files with 161 additions and 36 deletions
|
|
@ -1,2 +1,2 @@
|
||||||
<link rel="preload" href="font-files/Inter-upright.var.woff2?v=3.3" as="font" type="font/woff2" crossorigin>
|
<link rel="preload" href="/font-files/Inter-upright.var.woff2?v=3.3" as="font" type="font/woff2" crossorigin>
|
||||||
<link rel="preload" href="font-files/Inter-italic.var.woff2?v=3.3" as="font" type="font/woff2" crossorigin>
|
<link rel="preload" href="/font-files/Inter-italic.var.woff2?v=3.3" as="font" type="font/woff2" crossorigin>
|
||||||
|
|
@ -75,6 +75,7 @@ formula.code {
|
||||||
outline: none;
|
outline: none;
|
||||||
margin-right: 50px;
|
margin-right: 50px;
|
||||||
margin-bottom: 50px;
|
margin-bottom: 50px;
|
||||||
|
min-width: 50px;
|
||||||
}
|
}
|
||||||
.samples .sample > * {
|
.samples .sample > * {
|
||||||
display: block;
|
display: block;
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ endfor
|
||||||
yourself with typography, but Inter Dynamic Metrics provides guidelines
|
yourself with typography, but Inter Dynamic Metrics provides guidelines
|
||||||
for how to best use Inter.
|
for how to best use Inter.
|
||||||
You simply provide the optical font size,
|
You simply provide the optical font size,
|
||||||
and the tracking and leading is calculated for you through the following
|
and the tracking and line height is calculated for you through the following
|
||||||
formula:
|
formula:
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -42,12 +42,12 @@ endfor
|
||||||
<const title="Base of natural logarithm; ≈2.718">e</const><sup>(<const>c</const> × <const>z</const>)</sup>
|
<const title="Base of natural logarithm; ≈2.718">e</const><sup>(<const>c</const> × <const>z</const>)</sup>
|
||||||
</formula>
|
</formula>
|
||||||
<formula>
|
<formula>
|
||||||
leading = round(<num data-binding="var-l">1.4</num> × <const>z</const>)
|
line height = <num data-binding="var-l">1.4</num> × <const>z</const>
|
||||||
</formula>
|
</formula>
|
||||||
<formula title="Values for Inter">
|
<formula title="Values for Inter">
|
||||||
<g><const title="Constant a">a</const> = <num data-binding="var-a">-0.016</num></g>
|
<g><const title="Constant a">a</const> = <num data-binding="var-a">-0.02</num></g>
|
||||||
<g><const title="Constant b">b</const> = <num data-binding="var-b">0.21</num></g>
|
<g><const title="Constant b">b</const> = <num data-binding="var-b">0.205</num></g>
|
||||||
<g><const title="Constant c">c</const> = <num data-binding="var-c">-0.18</num></g>
|
<g><const title="Constant c">c</const> = <num data-binding="var-c">-0.175</num></g>
|
||||||
<g><const>z</const> = font size</g>
|
<g><const>z</const> = font size</g>
|
||||||
</formula>
|
</formula>
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -194,24 +194,24 @@ function parseValues(s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
setIdealValues({
|
setIdealValues({
|
||||||
// 2018-09-28
|
6: 0.021,
|
||||||
6: 0.054,
|
7: 0.017,
|
||||||
7: 0.042,
|
8: 0.013,
|
||||||
8: 0.033,
|
9: 0.01,
|
||||||
9: 0.025,
|
10: 0.007,
|
||||||
10: 0.018,
|
11: 0.005,
|
||||||
11: 0.012,
|
12: 0.002,
|
||||||
12: 0.008,
|
13: 0,
|
||||||
13: 0.004,
|
14: -0.002,
|
||||||
14: 0,
|
15: -0.004,
|
||||||
15: -0.002,
|
|
||||||
16: -0.005,
|
16: -0.005,
|
||||||
17: -0.007,
|
17: -0.007,
|
||||||
18: -0.008,
|
18: -0.008,
|
||||||
20: -0.011,
|
20: -0.01,
|
||||||
24: -0.014,
|
24: -0.013,
|
||||||
30: -0.016,
|
30: -0.016,
|
||||||
40: -0.017,
|
40: -0.02,
|
||||||
|
80: -0.02,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -222,7 +222,9 @@ setIdealValues({
|
||||||
// var a = -0.015, b = 0.283, c = -0.23; // di=0.00221 on set-2018-02-18
|
// var a = -0.015, b = 0.283, c = -0.23; // di=0.00221 on set-2018-02-18
|
||||||
// var a = -0.0149, b = 0.298, c = -0.23; // di=0.000484 on set-2018-02-19
|
// var a = -0.0149, b = 0.298, c = -0.23; // di=0.000484 on set-2018-02-19
|
||||||
// var a = -0.018, b = 0.21, c = -0.18; // di=0.000532 on set-2018-02-20
|
// var a = -0.018, b = 0.21, c = -0.18; // di=0.000532 on set-2018-02-20
|
||||||
var a = -0.017, b = 0.202, c = -0.175; // di=0.000247 on 2018-09-28
|
// var a = -0.017, b = 0.202, c = -0.175; // 2018-09-28
|
||||||
|
var a = -0.02, b = 0.0755, c = -0.102 // 2019-02-02
|
||||||
|
|
||||||
|
|
||||||
var l = 1.4
|
var l = 1.4
|
||||||
|
|
||||||
|
|
@ -238,10 +240,6 @@ function _InterDynamicTracking(fontSize, weightClass) {
|
||||||
// See https://gist.github.com/rsms/8efdbca5f8145a584ed08a7c3d6e5788
|
// See https://gist.github.com/rsms/8efdbca5f8145a584ed08a7c3d6e5788
|
||||||
//
|
//
|
||||||
return a + b * Math.pow(Math.E, c * fontSize)
|
return a + b * Math.pow(Math.E, c * fontSize)
|
||||||
// [6 - 38] 0.05798 .. -0.01099 (midpoint = 12.533)
|
|
||||||
//
|
|
||||||
// y = 0.025 - (ln(x) * 0.01)
|
|
||||||
// return 0.025 - Math.log(fontSize) * 0.01
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -335,6 +333,11 @@ Sample.prototype.cssProperties = function() {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Sample.prototype.setText = function(text) {
|
||||||
|
this.contentEl.innerText = text
|
||||||
|
this.render()
|
||||||
|
}
|
||||||
|
|
||||||
Sample.prototype.render = function() {
|
Sample.prototype.render = function() {
|
||||||
this.style.fontSize = this.fontSize + 'px'
|
this.style.fontSize = this.fontSize + 'px'
|
||||||
this.style.letterSpacing = this.tracking + 'em'
|
this.style.letterSpacing = this.tracking + 'em'
|
||||||
|
|
@ -393,6 +396,7 @@ function initSamples() {
|
||||||
samples.push(new Sample(24))
|
samples.push(new Sample(24))
|
||||||
samples.push(new Sample(30))
|
samples.push(new Sample(30))
|
||||||
samples.push(new Sample(40))
|
samples.push(new Sample(40))
|
||||||
|
samples.push(new Sample(80))
|
||||||
|
|
||||||
// connect focus events
|
// connect focus events
|
||||||
var onSampleReceivedFocus = function() { setSelectedSample(this) }
|
var onSampleReceivedFocus = function() { setSelectedSample(this) }
|
||||||
|
|
|
||||||
|
|
@ -100,8 +100,8 @@ html { font-family: 'Inter', sans-serif; }
|
||||||
<div class="row"><div>
|
<div class="row"><div>
|
||||||
<h2><a id="weights" href="#weights">Weights & Styles</a></h2>
|
<h2><a id="weights" href="#weights">Weights & Styles</a></h2>
|
||||||
<p>
|
<p>
|
||||||
There are six weights, each with italic counterparts,
|
There are nine weights, each with italic counterparts,
|
||||||
making a total of 12 styles.
|
making a total of 18 styles.
|
||||||
</p>
|
</p>
|
||||||
<img src="res/weights-and-styles.svg" style="opacity:0.88;width:100%;display:block;margin:3em 0 3em 0">
|
<img src="res/weights-and-styles.svg" style="opacity:0.88;width:100%;display:block;margin:3em 0 3em 0">
|
||||||
</div></div>
|
</div></div>
|
||||||
|
|
@ -564,10 +564,10 @@ var unitEl = $('#dynmet-unit')
|
||||||
|
|
||||||
var unitFormatters = [
|
var unitFormatters = [
|
||||||
['em', 'em', function(fontSize, tracking) {
|
['em', 'em', function(fontSize, tracking) {
|
||||||
return tracking.toFixed(3)
|
return tracking.toFixed(3).replace(/(?:\.000|0+)$/, '')
|
||||||
}],
|
}],
|
||||||
['px', 'px', function(fontSize, tracking) {
|
['px', 'px', function(fontSize, tracking) {
|
||||||
return (fontSize * tracking).toFixed(1)
|
return (fontSize * tracking).toFixed(2).replace(/(?:\.00|0+)$/, '')
|
||||||
}],
|
}],
|
||||||
['%', 'percent', function(fontSize, tracking) {
|
['%', 'percent', function(fontSize, tracking) {
|
||||||
return (tracking * 100).toFixed(1)
|
return (tracking * 100).toFixed(1)
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,8 @@ var HUDNotification = {
|
||||||
// the compensating tracking in EM.
|
// the compensating tracking in EM.
|
||||||
//
|
//
|
||||||
function InterDynamicTracking(fontSize) {
|
function InterDynamicTracking(fontSize) {
|
||||||
|
var a = -0.02, b = 0.0755, c = -0.102;
|
||||||
// tracking = a + b * e ^ (c * fontSize)
|
// tracking = a + b * e ^ (c * fontSize)
|
||||||
var a = -0.017, b = 0.202, c = -0.175;
|
|
||||||
return a + b * Math.pow(Math.E, c * fontSize)
|
return a + b * Math.pow(Math.E, c * fontSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,22 +8,33 @@ body {
|
||||||
text-align:center;
|
text-align:center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.live > hr {
|
||||||
|
margin: 3rem 0 4rem 0;
|
||||||
|
background: black;
|
||||||
|
height: 2px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
livesample {
|
livesample {
|
||||||
display: block;
|
display: block;
|
||||||
color: #111;
|
color: #111;
|
||||||
outline: none;
|
outline: none;
|
||||||
/*padding-left: 20px;
|
margin-top: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*livesample {
|
||||||
|
padding-left: 20px;
|
||||||
border-left: 2px solid transparent;
|
border-left: 2px solid transparent;
|
||||||
margin-left:-22px;*/
|
margin-left:-22px;
|
||||||
margin-top: 1em;
|
|
||||||
margin-bottom: 1.6em;
|
|
||||||
}
|
}
|
||||||
livesample:hover {
|
livesample:hover {
|
||||||
border-left-color: rgb(3, 102, 214);
|
border-left-color: rgb(3, 102, 214);
|
||||||
}
|
}
|
||||||
/*livesample:focus {
|
livesample:focus {
|
||||||
border-left-color: #eee;
|
border-left-color: #eee;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
livesample > p {
|
livesample > p {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,17 @@ endfor
|
||||||
|
|
||||||
<div class="row"><div>
|
<div class="row"><div>
|
||||||
<div class="live">
|
<div class="live">
|
||||||
|
<livesample data-ctxedit="sample-x1"
|
||||||
|
style="font-size:80px;line-height:1.0" contenteditable>
|
||||||
|
Interfacing mechanisms
|
||||||
|
</livesample>
|
||||||
|
|
||||||
|
<livesample data-ctxedit="sample-x2"
|
||||||
|
style="font-weight:100;font-size:80px;line-height:1.2" contenteditable>
|
||||||
|
XP–45 / vessel
|
||||||
|
</livesample>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
<livesample contenteditable class="s1" data-ctxedit="sample1">
|
<livesample contenteditable class="s1" data-ctxedit="sample1">
|
||||||
Fabulous typography encountering spring
|
Fabulous typography encountering spring
|
||||||
|
|
|
||||||
98
misc/dynmet-search.js
Normal file
98
misc/dynmet-search.js
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
//
|
||||||
|
// Program that searches for optimal a,b,c values for dynamic metrics.
|
||||||
|
//
|
||||||
|
// Provide ideal tracking values for font sizes in idealTracking and start
|
||||||
|
// this program. It will run forever and print to stdout when it finds
|
||||||
|
// better a,b,c values that brings you closer to the ideal values.
|
||||||
|
//
|
||||||
|
// These are the initial a,b,c values. (Update if you find better values.)
|
||||||
|
let a = -0.02, b = 0.0755, c = -0.1021 // 0.00092
|
||||||
|
//
|
||||||
|
// These are the ideal tracking values.
|
||||||
|
let idealTracking = {
|
||||||
|
// 6: 0.05,
|
||||||
|
// 7: 0.04,
|
||||||
|
// 8: 0.03,
|
||||||
|
9: 0.01,
|
||||||
|
// 10: 0.015,
|
||||||
|
11: 0.005,
|
||||||
|
12: 0.0025,
|
||||||
|
13: 0,
|
||||||
|
// 14: 0,
|
||||||
|
// 15: -0.002,
|
||||||
|
16: -0.005,
|
||||||
|
// 17: -0.008,
|
||||||
|
18: -0.01,
|
||||||
|
// 20: -0.014,
|
||||||
|
// 24: -0.016,
|
||||||
|
// 30: -0.019,
|
||||||
|
40: -0.022,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let idealTrackingList = Object.keys(idealTracking).map(fontSize =>
|
||||||
|
[fontSize, idealTracking[fontSize]]
|
||||||
|
)
|
||||||
|
|
||||||
|
function sample(a, b, c) {
|
||||||
|
let idealDist = 0.0
|
||||||
|
for (let [fontSize, idealTracking] of idealTrackingList) {
|
||||||
|
|
||||||
|
let tracking = a + b * Math.pow(Math.E, c * fontSize)
|
||||||
|
|
||||||
|
let dist = Math.abs(tracking - idealTracking)
|
||||||
|
|
||||||
|
idealDist += dist
|
||||||
|
// console.log(`${fontSize} d=${tracking - idealTracking} d'=${dist}`)
|
||||||
|
}
|
||||||
|
// console.log(`idealDist=${idealDist}`)
|
||||||
|
return idealDist / idealTrackingList.length
|
||||||
|
}
|
||||||
|
|
||||||
|
const prec = 4 // precision
|
||||||
|
let bestConstants = { a, b, c }
|
||||||
|
let isneg = {
|
||||||
|
a: a < 0,
|
||||||
|
b: b < 0,
|
||||||
|
c: c < 0,
|
||||||
|
}
|
||||||
|
let bestDistance = sample(a, b, c)
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
'------------------------------------------------------------------\n' +
|
||||||
|
`| Started at ${(new Date()).toLocaleString()} with initial values:\n` +
|
||||||
|
`| a = ${bestConstants.a}, b = ${bestConstants.b},` +
|
||||||
|
` c = ${bestConstants.c} // D ${bestDistance.toFixed(5)}\n` +
|
||||||
|
`| Ctrl-C to end.\n` +
|
||||||
|
'------------------------------------------------------------------'
|
||||||
|
)
|
||||||
|
|
||||||
|
function logNewBest() {
|
||||||
|
console.log(
|
||||||
|
`new best: a = ${a.toFixed(prec)}, b = ${b.toFixed(prec)}, c = ${c.toFixed(prec)} // D ${bestDistance.toFixed(5)}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
// a = parseFloat((bestConstants.a * ((Math.random() * 2.0) - 1.0)).toFixed(prec))
|
||||||
|
// b = parseFloat((bestConstants.b * ((Math.random() * 2.0) - 1.0)).toFixed(prec))
|
||||||
|
// c = parseFloat((bestConstants.c * ((Math.random() * 2.0) - 1.0)).toFixed(prec))
|
||||||
|
|
||||||
|
let a2 = bestConstants.a * ((Math.random() * 2.0) - 1.0)
|
||||||
|
let b2 = bestConstants.b * ((Math.random() * 2.0) - 1.0)
|
||||||
|
let c2 = bestConstants.c * ((Math.random() * 2.0) - 1.0)
|
||||||
|
|
||||||
|
if (isneg.a) { if (a2 > 0) { a2 = a } } else if (a2 < 0) { a2 = a }
|
||||||
|
if (isneg.b) { if (b2 > 0) { b2 = b } } else if (b2 < 0) { b2 = b }
|
||||||
|
if (isneg.c) { if (c2 > 0) { c2 = c } } else if (c2 < 0) { c2 = c }
|
||||||
|
|
||||||
|
a = a2
|
||||||
|
b = b2
|
||||||
|
c = c2
|
||||||
|
|
||||||
|
let dist = sample(a, b, c)
|
||||||
|
if (dist < bestDistance) {
|
||||||
|
bestDistance = dist
|
||||||
|
logNewBest()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in a new issue