2018-02-20 12:38:51 +03:00
---
layout: default
title: Dynamic Metrics
---
{%
2019-02-06 22:49:18 +03:00
if site.safe == false %}{%
assign url_root = "/" %}{% else %}{%
assign url_root = "/inter/" %}{% endif %}{%
2018-02-20 12:38:51 +03:00
for file in site.static_files %}{%
assign _path = file.path | remove_first: "/inter" %}{%
if _path == "/dynmetrics/index.css" %}{%
assign index_css_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
2020-04-10 01:54:01 +03:00
elsif _path == "/r/bindings.js" %}{%
2018-02-20 12:38:51 +03:00
assign bindings_js_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
2020-04-10 01:54:01 +03:00
elsif _path == "/r/graphplot.js" %}{%
2018-02-20 12:38:51 +03:00
assign graphplot_js_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
endif %}{%
endfor
%}
< link rel = "stylesheet" href = "index.css?v={{ index_css_v }}" >
2020-04-10 01:54:01 +03:00
< script src = "{{url_root}}r/bindings.js?v={{ bindings_js_v }}" > < / script >
< script src = "{{url_root}}r/graphplot.js?v={{ graphplot_js_v }}" > < / script >
2018-02-20 12:38:51 +03:00
< div class = "row first" > < div >
< h1 > Dynamic Metrics< / h1 >
< p >
There's of course no absolute right or wrong when it comes to expressing
2019-02-03 01:29:56 +03:00
yourself with typography, but Inter Dynamic Metrics provides guidelines
for how to best use Inter.
2018-02-21 05:12:29 +03:00
You simply provide the optical font size,
2019-02-03 08:01:00 +03:00
and the tracking and line height is calculated for you through the following
2018-02-20 12:38:51 +03:00
formula:
< / p >
< p >
< formula >
tracking =
< const > a< / const > + < const > b< / const > ×
2018-02-21 23:20:04 +03:00
< const title = "Base of natural logarithm; ≈2.718" > e< / const > < sup > (< const > c< / const > × < const > z< / const > )< / sup >
2018-02-20 12:38:51 +03:00
< / formula >
2019-02-06 22:49:18 +03:00
<!-- formula>
2019-02-03 08:01:00 +03:00
line height = < num data-binding = "var-l" > 1.4< / num > × < const > z< / const >
2019-02-06 22:49:18 +03:00
< / formula-- >
2019-02-03 01:29:56 +03:00
< formula title = "Values for Inter" >
2019-02-08 05:18:10 +03:00
< g > < const title = "Constant a" > a< / const > = < num data-binding = "var-a" > -0.0223< / num > < / g >
< g > < const title = "Constant b" > b< / const > = < num data-binding = "var-b" > 0.185< / num > < / g >
< g > < const title = "Constant c" > c< / const > = < num data-binding = "var-c" > -0.1745< / num > < / g >
2018-02-21 23:20:04 +03:00
< g > < const > z< / const > = font size< / g >
2018-02-20 12:38:51 +03:00
< / formula >
< / p >
2018-02-21 05:12:29 +03:00
< p class = "wide-window" >
The controls below can be used to play around with the
< const > a< / const > , < const > b< / const > and < const > c< / const > constants to discover
how they affect tracking.
< / p >
< p class = "narrow-window" >
2018-02-20 12:38:51 +03:00
< small > View this on a larger screen to enable interactive control.< / small >
< / p >
< / div > < / div >
< div class = "white full-width row with-sidebar" >
< div class = "samples" >
2018-02-21 05:12:29 +03:00
< p class = "sample" >
2018-02-20 12:38:51 +03:00
< span class = "di" > < span > < / span > < / span >
< span class = "info"
title="size, tracking, (ideal tracking) — progress bar shows distance from ideal"
>15 0.0 ( 0.0 )< / span >
2018-02-21 05:12:29 +03:00
< span contenteditable class = "content" >
2018-02-20 12:38:51 +03:00
Such a riot of sea and wind strews the whole extent of beach with whatever has been lost or thrown overboard, or torn out of sunken ships. Many a man has made a good week’ s work in a single day by what he has found while walking along the Beach when the surf was down.
2018-02-21 05:12:29 +03:00
< / span >
2018-02-20 12:38:51 +03:00
< / p >
< / div >
< div class = "sidebar controls" >
2020-02-09 04:05:32 +03:00
2018-02-20 12:38:51 +03:00
< div class = "control" >
2019-02-06 22:49:18 +03:00
< img title = "Style" class = "icon" src = "icons/style.svg" >
2018-02-20 12:38:51 +03:00
< select data-binding = "style" >
2020-02-09 04:05:32 +03:00
< option value = "thin" > Thin< / option >
< option value = "extra-light" > Extra Ligh< / option >
< option value = "light" > Light< / option >
2019-01-06 22:56:06 +03:00
< option value = "regular" default selected > Regular< / option >
< option value = "medium" > Medium< / option >
< option value = "semi-bold" > Semi Bold< / option >
< option value = "bold" > Bold< / option >
< option value = "extra-bold" > Extra Bold< / option >
< option value = "black" > Black< / option >
2020-02-09 04:05:32 +03:00
< option disabled > ————————————< / option >
< option value = "thin-italic" > Thin Italic< / option >
< option value = "extra-light-italic" > Extra Light Italic< / option >
< option value = "light-italic" > Light Italic< / option >
< option value = "italic" > Italic< / option >
< option value = "medium-italic" > Medium Italic< / option >
< option value = "semi-bold-italic" > Semi Bold Italic< / option >
< option value = "bold-italic" > Bold Italic< / option >
< option value = "extra-bold-italic" > Extra Bold Italic< / option >
2018-02-20 12:38:51 +03:00
< option value = "black-italic" > Black Italic< / option >
< / select >
< / div >
< div class = "control" >
2019-02-06 22:49:18 +03:00
< img title = "Base tracking" class = "icon" src = "icons/letter-spacing.svg" >
2018-02-20 12:38:51 +03:00
< input type = "range" min = "-0.05" max = "0.06" step = "0.001" data-binding = "base-tracking" >
< input type = "number" min = "-0.15" max = "1" step = "0.001" data-binding = "base-tracking" >
< / div >
2019-02-06 22:49:18 +03:00
< div class = "control" >
< img title = "Line height" class = "icon" src = "icons/line-height.svg" >
< input type = "range" min = "1" max = "2" step = "0.01" data-binding = "var-l" >
< input type = "number" min = "1" max = "2" step = "0.01" data-binding = "var-l" >
< / div >
2018-02-20 12:38:51 +03:00
< hr >
2019-02-06 22:49:18 +03:00
2018-02-20 12:38:51 +03:00
< div class = "control" >
< label title = "Constant a" > a< / label >
< input type = "range" min = "-0.05" max = "0" step = "0.001" data-binding = "var-a" >
< input type = "number" min = "-0.05" max = "0" step = "0.0001" data-binding = "var-a" >
< / div >
< div class = "control" >
< label title = "Constant b" > b< / label >
< input type = "range" min = "0" max = "1" step = "0.01" data-binding = "var-b" >
< input type = "number" min = "0" max = "1" step = "0.001" data-binding = "var-b" >
< / div >
< div class = "control" >
< label title = "Constant c" > c< / label >
< input type = "range" min = "-1" max = "0" step = "0.01" data-binding = "var-c" >
< input type = "number" min = "-1" max = "0" step = "0.001" data-binding = "var-c" >
< / div >
2020-02-09 04:05:32 +03:00
2018-02-20 12:38:51 +03:00
< hr >
2020-02-09 04:05:32 +03:00
2018-02-20 12:38:51 +03:00
< div class = "control" >
2019-02-06 22:49:18 +03:00
< label title = "Number of ideal matches" > ni< / label >
< input title = "Number of ideal matches" type = "number" readonly data-binding = "ideal-count" >
< label title = "Distance from ideal" > di< / label >
< input title = "Distance from ideal" type = "number" class = "wide" readonly data-binding = "ideal-distance" >
2018-02-20 12:38:51 +03:00
< / div >
2019-02-06 22:49:18 +03:00
2018-02-20 12:38:51 +03:00
< hr class = "without-bottom-margin" >
2019-02-06 22:49:18 +03:00
2018-02-20 12:38:51 +03:00
< canvas class = "graphplot" > Canvas not Supported< / canvas >
2019-02-06 22:49:18 +03:00
2018-02-21 05:12:29 +03:00
< hr class = "when-selection without-top-margin" >
< h3 class = "when-selection" > CSS< / h3 >
< textarea class = "when-selection" readonly id = "code-output" > < / textarea >
2018-02-20 12:38:51 +03:00
< hr class = "without-top-margin" >
< h3 > Ideal values< / h3 >
< textarea id = "ideal-values" > < / textarea >
< hr class = "without-top-margin" >
< / div >
< / div >
< script type = "text/javascript" > ( f u n c t i o n ( ) {
// internal variables that are user-controllable, but are not part of
// Dynamic Metrics
var baseTracking = 0
var weightClass = 400
2018-02-21 05:12:29 +03:00
function round(num, prec) {
return parseFloat(num.toFixed(prec))
}
2018-02-20 12:38:51 +03:00
// Ideal values designed one by one, by hand.
// font size => tracking
var idealValues = {}
var idealValuesList = []
var idealValuesTextArea = $('textarea#ideal-values')
function setIdealValues(valueMap) {
idealValues = valueMap
idealValuesList = []
Object.keys(idealValues).forEach(function(fontSize) {
idealValuesList.push([fontSize, idealValues[fontSize]])
})
if (idealValuesTextArea.value == '') {
idealValuesTextArea.value = idealValuesList.map(function(t){
return t[0] + '\t' + t[1]
}).join('\n')
}
}
function parseValues(s) {
var values = {}
s = s.replace(/^[\s\r\t\n]+|[\s\r\t\n]+$/g, '') // trim whitespace
s.split(/\s*\r?\n\s*/).map(function(line) {
var t = line.split(/\s+/)
if (t.length == 2) {
t[0] = parseInt(t[0])
t[1] = parseFloat(t[1])
values[t[0]] = t[1]
}
})
return values
}
setIdealValues({
2019-02-06 22:49:18 +03:00
// // 2018
// 6: 0.021,
// 7: 0.017,
// 8: 0.013,
// 9: 0.01,
// 10: 0.007,
// 11: 0.005,
// 12: 0.002,
// 13: 0,
// 14: -0.002,
// 15: -0.004,
// 16: -0.005,
// 17: -0.007,
// 18: -0.008,
// 20: -0.01,
// 24: -0.013,
// 30: -0.016,
// 40: -0.02,
// 80: -0.02,
// 2019-02-02
// 6: 0.066,
// 7: 0.05,
// 8: 0.036,
// 9: 0.025,
// 10: 0.015,
// 11: 0.007,
// 12: 0,
// 13: -0.005,
// 14: -0.01,
// 15: -0.014,
// 16: -0.017,
// 17: -0.02,
// 18: -0.022,
// 20: -0.026,
// 24: -0.03,
// 30: -0.033,
// 40: -0.034,
// 80: -0.034,
2019-02-08 05:18:10 +03:00
// // 2019-02-06
// 6: 0.04,
// 7: 0.032,
// 8: 0.024,
// 9: 0.017,
// 10: 0.01,
// 11: 0.005,
// 12: 0,
// 13: -0.004,
// 14: -0.008,
// 15: -0.011,
// 16: -0.014,
// 17: -0.017,
// 18: -0.019,
// 20: -0.023,
// 24: -0.029,
// 30: -0.034,
// 40: -0.037,
// 80: -0.038,
// 2019-02-07
6: 0.043,
2019-02-06 22:49:18 +03:00
7: 0.032,
8: 0.024,
2019-02-08 05:18:10 +03:00
9: 0.016,
2019-02-06 22:49:18 +03:00
10: 0.01,
11: 0.005,
12: 0,
2019-02-08 05:18:10 +03:00
13: -0.0025,
14: -0.006,
15: -0.009,
16: -0.011,
17: -0.013,
18: -0.014,
20: -0.017,
24: -0.019,
30: -0.021,
40: -0.022,
80: -0.022,
2018-02-20 12:38:51 +03:00
})
// Variables for constants involved in Dynamic Metrics
2018-02-20 12:42:59 +03:00
// var a = -0.012, b = 0.23, c = -0.21; // di=0.002514 on set-2018-02-18
// var a = -0.013, b = 0.251, c = -0.222 // di=0.001742 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
2018-09-28 23:33:56 +03:00
// var a = -0.018, b = 0.21, c = -0.18; // di=0.000532 on set-2018-02-20
2019-02-03 08:01:00 +03:00
// var a = -0.017, b = 0.202, c = -0.175; // 2018-09-28
2019-02-06 22:49:18 +03:00
// var a = -0.02, b = 0.0755, c = -0.102 // 2019-02-02
2019-02-08 05:18:10 +03:00
// var a = -0.038, b = 0.161, c = -0.12 // 2019-02-06
var a = -0.0223, b = 0.185, c = -0.1745 // 2019-02-07
2019-02-03 08:01:00 +03:00
2018-02-20 12:38:51 +03:00
var l = 1.4
2019-02-03 01:29:56 +03:00
// _InterDynamicTracking is a version of InterDynamicTracking that
2018-02-21 23:20:04 +03:00
// uses some global variables that are adjustable.
2018-02-20 12:38:51 +03:00
//
2019-02-03 01:29:56 +03:00
function _InterDynamicTracking(fontSize, weightClass) {
2018-02-20 12:42:59 +03:00
// Note: weightClass is currently unused
2018-02-20 12:38:51 +03:00
//
// y = -0.01021241 + 0.3720623 * e ^ (-0.2808687 * x)
// [6-35] 0.05877 .. -0.0101309 (13==0; stops growing around 30-35)
// See https://gist.github.com/rsms/8efdbca5f8145a584ed08a7c3d6e5788
//
return a + b * Math.pow(Math.E, c * fontSize)
}
2019-02-03 01:29:56 +03:00
function InterDynamicLineHeight(fontSize, weightClass) {
2018-02-20 12:38:51 +03:00
return Math.round(fontSize * l)
}
var NPOS = Number.MAX_SAFE_INTEGER
function Sample(fontSize) {
this.rootEl = sampleTemplate.cloneNode(true)
this.infoEl = $('.info', this.rootEl)
2018-02-21 05:12:29 +03:00
this.contentEl = $('.content', this.rootEl)
2018-02-20 12:38:51 +03:00
this.diEl = $('.di', this.rootEl)
this.diEl.classList.add('unavailable')
this.style = this.rootEl.style
this.maxBoxWidth = 0
this.fontSize = 0
this.tracking = 0
this.lineHeight = 0
this.idealTracking = NPOS
this.matchesIdeal = false
this.setFontSize(fontSize)
this.render()
2018-02-21 05:12:29 +03:00
// listen for focus events on the editable content
var s = this
this.contentEl.addEventListener(
'focus',
function(){ s.onReceivedFocus() },
{passive:true, capture:false}
)
this.contentEl.addEventListener(
'blur',
function(){ s.onLostFocus() },
{passive:true, capture:false}
)
2018-02-20 12:38:51 +03:00
}
2018-02-21 05:12:29 +03:00
Sample.prototype.onReceivedFocus = function() {}
Sample.prototype.onLostFocus = function() {}
2018-02-20 12:38:51 +03:00
Sample.prototype.idealDistance = function(fontSize) {
// returns the distance from the ideal (or NPOS if no "ideal" data available)
if (this.idealTracking == NPOS) {
return NPOS
}
return (
Math.max(this.tracking, this.idealTracking) -
Math.min(this.tracking, this.idealTracking)
)
}
Sample.prototype.setFontSize = function(fontSize) {
this.fontSize = fontSize
2019-02-03 01:29:56 +03:00
this.tracking = baseTracking + _InterDynamicTracking(fontSize, weightClass)
this.lineHeight = InterDynamicLineHeight(fontSize, weightClass)
2018-02-20 12:38:51 +03:00
this.maxBoxWidth = Math.round(fontSize * (this.tracking + 1) * 25)
var idealTracking = idealValues[this.fontSize]
if (idealTracking === undefined) {
if (this.idealTracking != NPOS) {
this.diEl.classList.add('unavailable')
}
this.idealTracking = NPOS
this.matchesIdeal = false
} else {
if (this.idealTracking == NPOS) {
this.diEl.classList.remove('unavailable')
}
this.idealTracking = idealTracking
// match to a precision of 3
this.matchesIdeal = this.tracking.toFixed(3) == idealTracking.toFixed(3)
var di = 1
if (this.matchesIdeal) {
this.diEl.classList.add('match')
} else {
this.diEl.classList.remove('match')
di = 1 - Math.min(1, this.idealDistance() * 50)
}
this.diEl.firstChild.style.width = (di * this.maxBoxWidth) + 'px'
}
}
2018-02-21 05:12:29 +03:00
Sample.prototype.cssProperties = function() {
2018-02-21 23:20:04 +03:00
return [
['font-size', round(this.fontSize, 3) + 'px'],
['letter-spacing', round(this.tracking, 3) + 'em'],
['line-height', round(this.lineHeight, 3) + 'px'],
]
2018-02-21 05:12:29 +03:00
}
2019-02-03 08:01:00 +03:00
Sample.prototype.setText = function(text) {
this.contentEl.innerText = text
this.render()
}
2018-02-20 12:38:51 +03:00
Sample.prototype.render = function() {
this.style.fontSize = this.fontSize + 'px'
this.style.letterSpacing = this.tracking + 'em'
this.style.lineHeight = this.lineHeight + 'px'
var SP = '\u00A0\u00A0\u00A0'
this.infoEl.innerText = (
this.fontSize +
SP + this.tracking.toFixed(3) +
// SP + this.lineHeight.toFixed(3) +
(
this.idealTracking != NPOS ? (
SP + '( ' + this.idealTracking +
(this.matchesIdeal ? ' \u2713' : '') +
' )'
) : ''
)
)
this.style.maxWidth = this.maxBoxWidth + 'px'
}
var bindings = new Bindings()
2018-02-21 05:12:29 +03:00
var samplesEl = $('.samples')
2018-02-20 12:38:51 +03:00
var sampleTemplate
var samples = [] // Sample[]
2018-02-21 05:12:29 +03:00
var focusedSample = null // Sample | null
2018-02-20 12:38:51 +03:00
var graph = new GraphPlot($('canvas.graphplot'))
graph.setOrigin(-0.2, 0.8)
graph.setScale(0.049, 5)
function addChildren(targetNode, children) {
targetNode.style.visibility = 'hidden'
var i = 0;
for (; i < children.length ; i + + ) {
targetNode.appendChild(children[i])
}
targetNode.style.visibility = null
}
function initSamples() {
sampleTemplate = $('.sample', samplesEl)
samplesEl.removeChild(sampleTemplate)
// small and medium sizes
var i, fontSize = 6, endFontSize = 16
for (; fontSize < = endFontSize; fontSize++) {
samples.push(new Sample(fontSize))
}
// a few select large samples
samples.push(new Sample(17))
samples.push(new Sample(18))
samples.push(new Sample(20))
samples.push(new Sample(24))
samples.push(new Sample(30))
samples.push(new Sample(40))
2019-02-03 08:01:00 +03:00
samples.push(new Sample(80))
2018-02-20 12:38:51 +03:00
2018-02-21 05:12:29 +03:00
// connect focus events
var onSampleReceivedFocus = function() { setSelectedSample(this) }
samples.forEach(function(s) {
s.onReceivedFocus = onSampleReceivedFocus
})
2018-02-20 12:38:51 +03:00
// add to dom in one go
addChildren(samplesEl, samples.map(function(s) { return s.rootEl }))
}
2018-02-21 05:12:29 +03:00
function setSelectedSample(sample) {
if (focusedSample !== sample) {
if (focusedSample) {
focusedSample.rootEl.classList.remove('selected')
}
if (sample) {
sample.rootEl.classList.add('selected')
}
focusedSample = sample
updateSelection()
}
}
2018-02-20 12:38:51 +03:00
function updateSample(sample) {
sample.setFontSize(sample.fontSize) // updates derived values
sample.render()
}
function updateSamples() {
samples.forEach(updateSample)
updateIdealMatches()
updateGraphPlot()
2018-02-21 05:12:29 +03:00
updateCodeView()
2018-02-20 12:38:51 +03:00
}
function updateIdealMatches() {
// ideal-distance
var idealCount = 0
var distance = 0
var ndistances = 0
samples.forEach(function(sample) {
if (sample.matchesIdeal) {
idealCount++
}
var di = sample.idealDistance()
if (di != NPOS) {
distance += di
ndistances++
}
})
distance = distance / ndistances
2020-02-09 04:05:32 +03:00
2018-02-20 12:38:51 +03:00
bindings.setValue('ideal-distance', distance.toFixed(6))
bindings.setValue('ideal-count', idealCount)
}
function updateGraphPlot() {
graph.clear()
graph.plotLine(idealValuesList, '#0d3')
2019-02-08 05:18:10 +03:00
graph.plotf(
x => _InterDynamicTracking(x, weightClass),
'rgba(0, 0, 0, 0.5)'
)
2018-02-21 05:12:29 +03:00
if (focusedSample) {
var graphedFontSize = Math.min(24, focusedSample.fontSize) // clamp to [-inf,24]
graph.plotPoints([
[graphedFontSize, focusedSample.tracking]
], 'rgb(45, 143, 255)')
}
}
var codeOutput = $('#code-output')
codeOutput.addEventListener('focus', function(ev) {
ev.preventDefault()
ev.stopPropagation()
codeOutput.select()
}, {passive:false,capture:true})
2018-02-21 23:20:04 +03:00
codeOutput.addEventListener('pointerdown', function(ev) {
// TODO: don't do this if codeOutput is focused
ev.preventDefault()
ev.stopPropagation()
codeOutput.select()
document.execCommand("copy")
HUDNotification.show('Copied to clipboard')
}, {passive:false,capture:true})
2018-02-21 05:12:29 +03:00
function updateCodeView() {
var s = ''
if (focusedSample) {
2018-02-21 23:20:04 +03:00
var props = focusedSample.cssProperties()
2018-02-21 05:12:29 +03:00
props.forEach(function(prop, i) {
2018-02-21 23:20:04 +03:00
var name = prop[0], value = prop[1]
s += name + ': ' + value + ';'
2018-02-21 05:12:29 +03:00
if (i != props.length-1) {
s += '\n'
}
})
}
codeOutput.value = s
}
function updateSelection() {
var controlsEl = $('.controls')
if (focusedSample) {
controlsEl.classList.add('has-selected-sample')
} else {
controlsEl.classList.remove('has-selected-sample')
}
updateGraphPlot()
updateCodeView()
2018-02-20 12:38:51 +03:00
}
bindings.configure('base-tracking', 0, 'float', function (tracking) {
baseTracking = tracking
updateSamples()
})
bindings.configure('var-a', a, 'float', function (v) {
a = v
updateSamples()
})
bindings.configure('var-b', b, 'float', function (v) {
b = v
updateSamples()
})
bindings.configure('var-c', c, 'float', function (v) {
c = v
updateSamples()
})
bindings.configure('var-l', l, 'float', function (v) {
l = v
updateSamples()
})
bindings.configure('ideal-count', 0, 'int', function (v) {})
bindings.configure('ideal-distance', 0, 'float', function (v) {})
bindings.configure('style', null, null, function (style) {
2018-02-21 05:12:29 +03:00
var cl = samplesEl.classList
2018-02-20 12:38:51 +03:00
cl.remove('font-style-regular')
cl.remove('font-style-italic')
cl.remove('font-style-medium')
cl.remove('font-style-medium-italic')
2018-09-28 23:33:56 +03:00
cl.remove('font-style-semi-bold')
cl.remove('font-style-semi-bold-italic')
2018-02-20 12:38:51 +03:00
cl.remove('font-style-bold')
cl.remove('font-style-bold-italic')
2018-09-28 23:33:56 +03:00
cl.remove('font-style-extra-bold')
cl.remove('font-style-extra-bold-italic')
2018-02-20 12:38:51 +03:00
cl.remove('font-style-black')
cl.remove('font-style-black-italic')
cl.add('font-style-' + style)
weightClass = (
style.indexOf('black') != -1 ? 900 :
style.indexOf('bold') != -1 ? 700 :
style.indexOf('medium') != -1 ? 500 :
400
)
updateSamples()
})
2018-02-20 13:10:20 +03:00
bindings.bindAllInputs('[data-binding]')
2018-02-20 12:38:51 +03:00
// double-click base tracking to reset
$('input[type="range"][data-binding="base-tracking"]').addEventListener(
'dblclick',
function(ev) { bindings.setValue('base-tracking', 0) }
)
2018-09-28 23:33:56 +03:00
;[
['var-a',a],
['var-b',b],
['var-c',c],
['var-l',l],
['base-tracking', 0]
].forEach(p => {
let bindname = p[0], defval = p[1]
$$('input[type="range"][data-binding="'+bindname+'"]').forEach(e => {
e.addEventListener('dblclick', ev =>
bindings.setValue(bindname, defval))
})
})
2018-02-20 12:38:51 +03:00
// allow editing of ideal values
idealValuesTextArea.addEventListener('input', function(ev) {
setIdealValues(parseValues(idealValuesTextArea.value))
updateSamples()
})
2018-02-21 05:12:29 +03:00
// listen for clicks onto "background", to deselect any selected sample
document.body.addEventListener('pointerdown', function(ev){
if (
ev.target === document.body ||
ev.target === samplesEl ||
ev.target.classList & & ev.target.classList.contains('row')
) {
setSelectedSample(null)
}
})
2018-02-20 12:38:51 +03:00
// start
initSamples()
updateSamples()
})();< / script >