diff --git a/.eslintrc.js b/.eslintrc.js index bed00d4..e529dd8 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -18,6 +18,7 @@ module.exports = { 'fetch', 'Object.assign', 'requestAnimationFrame', + 'performance.now', ], }, }; diff --git a/README.md b/README.md index c5594aa..1243cfa 100644 --- a/README.md +++ b/README.md @@ -497,7 +497,7 @@ Implementing FLIP animations without a large refactoring was the biggest challenge of this case study, especially in combination with drag & drop. After days of work I was able to implement the algorithm in isolation and coordinate it with other concerns at the application's root level. -The `useCapture` mode of `addEventListener` was proven to be useful +The `useCapture` mode of `addEventListener` proved to be very useful in this case. Reference: diff --git a/public/index.html b/public/index.html index e09875d..e1062d1 100644 --- a/public/index.html +++ b/public/index.html @@ -23,11 +23,12 @@ + diff --git a/public/scripts/AppFps.js b/public/scripts/AppFps.js new file mode 100644 index 0000000..589fa16 --- /dev/null +++ b/public/scripts/AppFps.js @@ -0,0 +1,39 @@ +/* global VT */ +window.VT = window.VT || {}; + +VT.AppFps = function (el) { + var times = []; + + tick(); + + function tick() { + requestAnimationFrame(tick); + + times.push(performance.now()); + + if (times.length < 60) return; + + var min = Infinity; + var max = 0; + var sum = 0; + + for (var i = 1; i < 60; ++i) { + var delta = times[i] - times[i - 1]; + min = Math.min(min, delta); + max = Math.max(max, delta); + sum += delta; + } + + var fps = (60 / sum) * 1000; + + el.innerText = + fps.toFixed(0) + + ' fps (' + + min.toFixed(0) + + ' ms - ' + + max.toFixed(0) + + ' ms)'; + + times = []; + } +}; diff --git a/public/scripts/TodoApp.js b/public/scripts/TodoApp.js index ca034a0..4bc444c 100644 --- a/public/scripts/TodoApp.js +++ b/public/scripts/TodoApp.js @@ -12,6 +12,7 @@ VT.TodoApp = function (el) { el.innerHTML = [ '
', '

VANILLA TODO

', + '

', '
', '
', '
', @@ -39,6 +40,7 @@ VT.TodoApp = function (el) { el.querySelectorAll('.app-collapsible').forEach(VT.AppCollapsible); el.querySelectorAll('.app-icon').forEach(VT.AppIcon); + el.querySelectorAll('.app-fps').forEach(VT.AppFps); VT.TodoFrameDays(el.querySelector('.todo-frame.-days')); VT.TodoFrameCustom(el.querySelector('.todo-frame.-custom')); diff --git a/public/scripts/TodoStore.js b/public/scripts/TodoStore.js index a0adba1..c81a275 100644 --- a/public/scripts/TodoStore.js +++ b/public/scripts/TodoStore.js @@ -168,6 +168,7 @@ VT.TodoStore = function (el) { function load() { if (!localStorage || !localStorage.todo) { + dispatch(state); return; } diff --git a/public/styles/app-header.css b/public/styles/app-header.css index b8d4189..001e0f9 100644 --- a/public/styles/app-header.css +++ b/public/styles/app-header.css @@ -1,9 +1,20 @@ .app-header { background: #249; - padding: 0.5em 1em; + padding: 10px 20px; } .app-header > .title { color: #fff; font-size: 1em; + margin: 0; +} + +.app-header > .app-fps { + position: absolute; + top: 10px; + right: 20px; + margin: 0; + font-size: 0.8em; + line-height: 1.5em; + color: #fff; }