# HG changeset patch # User Drew Perttula # Date 2018-05-14 02:48:20 # Node ID 82c6e4f75221283f25a5a1fddf7f96d61eb40060 # Parent f9593805e1099a4fe9ad02d4a71c58e90633a497 extract viewstate Ignore-this: cf7375f279f158b732c9ada75e19a457 diff --git a/light9/web/timeline/timeline-elements.html b/light9/web/timeline/timeline-elements.html --- a/light9/web/timeline/timeline-elements.html +++ b/light9/web/timeline/timeline-elements.html @@ -268,6 +268,7 @@ + diff --git a/light9/web/timeline/timeline.coffee b/light9/web/timeline/timeline.coffee --- a/light9/web/timeline/timeline.coffee +++ b/light9/web/timeline/timeline.coffee @@ -92,96 +92,6 @@ class Project if note in selection.selected() selection.selected(_.without(selection.selected(), note)) -class ViewState - constructor: () -> - # caller updates all these observables - @zoomSpec = - duration: ko.observable(100) # current song duration - t1: ko.observable(0) - t2: ko.observable(100) - @cursor = - t: ko.observable(20) # songTime - @mouse = - pos: ko.observable($V([0,0])) - @width = ko.observable(500) - @audioY = ko.observable(0) - @audioH = ko.observable(0) - @zoomedTimeY = ko.observable(0) - @zoomedTimeH = ko.observable(0) - - @fullZoomX = d3.scaleLinear() - @zoomInX = d3.scaleLinear() - - @zoomAnimSec = .1 - - ko.computed(@maintainZoomLimitsAndScales.bind(@)) - - setWidth: (w) -> - @width(w) - @maintainZoomLimitsAndScales() # before other handlers run - - maintainZoomLimitsAndScales: () -> - log('maintainZoomLimitsAndScales') - # not for cursor updates - - if @zoomSpec.t1() < 0 - @zoomSpec.t1(0) - if @zoomSpec.duration() and @zoomSpec.t2() > @zoomSpec.duration() - @zoomSpec.t2(@zoomSpec.duration()) - - @fullZoomX.domain([0, @zoomSpec.duration()]) - @fullZoomX.range([0, @width()]) - - @zoomInX.domain([@zoomSpec.t1(), @zoomSpec.t2()]) - @zoomInX.range([0, @width()]) - - latestMouseTime: -> - @zoomInX.invert(@mouse.pos().e(1)) - - onMouseWheel: (deltaY) -> - zs = @zoomSpec - - center = @latestMouseTime() - left = center - zs.t1() - right = zs.t2() - center - scale = Math.pow(1.005, deltaY) - - zs.t1(center - left * scale) - zs.t2(center + right * scale) - log('view to', ko.toJSON(@)) - - frameCursor: -> - zs = @zoomSpec - visSeconds = zs.t2() - zs.t1() - margin = visSeconds * .4 - # buggy: really needs t1/t2 to limit their ranges - if @cursor.t() < zs.t1() or @cursor.t() > zs.t2() - visSeconds * .6 - newCenter = @cursor.t() + margin - @animatedZoom(newCenter - visSeconds / 2, - newCenter + visSeconds / 2, @zoomAnimSec) - frameToEnd: -> - @animatedZoom(@cursor.t() - 2, @zoomSpec.duration(), @zoomAnimSec) - frameAll: -> - @animatedZoom(0, @zoomSpec.duration(), @zoomAnimSec) - animatedZoom: (newT1, newT2, secs) -> - fps = 30 - oldT1 = @zoomSpec.t1() - oldT2 = @zoomSpec.t2() - lastTime = 0 - for step in [0..secs * fps] - frac = step / (secs * fps) - do (frac) => - gotoStep = => - @zoomSpec.t1((1 - frac) * oldT1 + frac * newT1) - @zoomSpec.t2((1 - frac) * oldT2 + frac * newT2) - delay = frac * secs * 1000 - setTimeout(gotoStep, delay) - lastTime = delay - setTimeout(=> - @zoomSpec.t1(newT1) - @zoomSpec.t2(newT2) - , lastTime + 10) - coffeeElementSetup(class TimelineEditor extends Polymer.mixinBehaviors([Polymer.IronResizableBehavior], Polymer.Element) @is: 'light9-timeline-editor' diff --git a/light9/web/timeline/viewstate.coffee b/light9/web/timeline/viewstate.coffee new file mode 100644 --- /dev/null +++ b/light9/web/timeline/viewstate.coffee @@ -0,0 +1,89 @@ +class window.ViewState + constructor: () -> + # caller updates all these observables + @zoomSpec = + duration: ko.observable(100) # current song duration + t1: ko.observable(0) + t2: ko.observable(100) + @cursor = + t: ko.observable(20) # songTime + @mouse = + pos: ko.observable($V([0,0])) + @width = ko.observable(500) + @audioY = ko.observable(0) + @audioH = ko.observable(0) + @zoomedTimeY = ko.observable(0) + @zoomedTimeH = ko.observable(0) + + @fullZoomX = d3.scaleLinear() + @zoomInX = d3.scaleLinear() + + @zoomAnimSec = .1 + + ko.computed(@maintainZoomLimitsAndScales.bind(@)) + + setWidth: (w) -> + @width(w) + @maintainZoomLimitsAndScales() # before other handlers run + + maintainZoomLimitsAndScales: () -> + log('maintainZoomLimitsAndScales') + # not for cursor updates + + if @zoomSpec.t1() < 0 + @zoomSpec.t1(0) + if @zoomSpec.duration() and @zoomSpec.t2() > @zoomSpec.duration() + @zoomSpec.t2(@zoomSpec.duration()) + + @fullZoomX.domain([0, @zoomSpec.duration()]) + @fullZoomX.range([0, @width()]) + + @zoomInX.domain([@zoomSpec.t1(), @zoomSpec.t2()]) + @zoomInX.range([0, @width()]) + + latestMouseTime: -> + @zoomInX.invert(@mouse.pos().e(1)) + + onMouseWheel: (deltaY) -> + zs = @zoomSpec + + center = @latestMouseTime() + left = center - zs.t1() + right = zs.t2() - center + scale = Math.pow(1.005, deltaY) + + zs.t1(center - left * scale) + zs.t2(center + right * scale) + log('view to', ko.toJSON(@)) + + frameCursor: -> + zs = @zoomSpec + visSeconds = zs.t2() - zs.t1() + margin = visSeconds * .4 + # buggy: really needs t1/t2 to limit their ranges + if @cursor.t() < zs.t1() or @cursor.t() > zs.t2() - visSeconds * .6 + newCenter = @cursor.t() + margin + @animatedZoom(newCenter - visSeconds / 2, + newCenter + visSeconds / 2, @zoomAnimSec) + frameToEnd: -> + @animatedZoom(@cursor.t() - 2, @zoomSpec.duration(), @zoomAnimSec) + frameAll: -> + @animatedZoom(0, @zoomSpec.duration(), @zoomAnimSec) + animatedZoom: (newT1, newT2, secs) -> + fps = 30 + oldT1 = @zoomSpec.t1() + oldT2 = @zoomSpec.t2() + lastTime = 0 + for step in [0..secs * fps] + frac = step / (secs * fps) + do (frac) => + gotoStep = => + @zoomSpec.t1((1 - frac) * oldT1 + frac * newT1) + @zoomSpec.t2((1 - frac) * oldT2 + frac * newT2) + delay = frac * secs * 1000 + setTimeout(gotoStep, delay) + lastTime = delay + setTimeout(=> + @zoomSpec.t1(newT1) + @zoomSpec.t2(newT2) + , lastTime + 10)