M go.mod => go.mod +1 -0
@@ 13,6 13,7 @@ require (
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2 // indirect
gioui.org/shader v1.0.6 // indirect
github.com/benoitkugler/textlayout v0.1.1 // indirect
+ github.com/fogleman/ease v0.0.0-20170301025033-8da417bf1776 // indirect
github.com/gioui/uax v0.2.1-0.20220325163150-e3d987515a12 // indirect
github.com/go-text/typesetting v0.0.0-20220411150340-35994bc27a7b // indirect
golang.org/x/exp/shiny v0.0.0-20220516143420-24438e51023a // indirect
M go.sum => go.sum +2 -0
@@ 12,6 12,8 @@ github.com/benoitkugler/textlayout v0.1.1 h1:hizE/085xAeY8q7gwV00uHR2Q27KYB2g1HW
github.com/benoitkugler/textlayout v0.1.1/go.mod h1:o+1hFV+JSHBC9qNLIuwVoLedERU7sBPgEFcuSgfvi/w=
github.com/benoitkugler/textlayout-testdata v0.1.1 h1:AvFxBxpfrQd8v55qH59mZOJOQjtD6K2SFe9/HvnIbJk=
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21/go.mod h1:po7NpZ/QiTKzBKyrsEAxwnTamCoh8uDk/egRpQ7siIc=
+github.com/fogleman/ease v0.0.0-20170301025033-8da417bf1776 h1:VRIbnDWRmAh5yBdz+J6yFMF5vso1It6vn+WmM/5l7MA=
+github.com/fogleman/ease v0.0.0-20170301025033-8da417bf1776/go.mod h1:9wvnDu3YOfxzWM9Cst40msBF1C2UdQgDv962oTxSuMs=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/gioui/uax v0.2.1-0.20220325163150-e3d987515a12 h1:1bjaB/5IIicfKpP4k0s30T2WEw//Kh00zULa8DQ0cxA=
M main.go => main.go +25 -5
@@ 39,6 39,7 @@ import (
"gioui.org/op/paint"
"gioui.org/widget"
"gioui.org/widget/material"
+ "github.com/fogleman/ease"
"github.com/hajimehoshi/oto/v2"
"github.com/lucasb-eyer/go-colorful"
"golang.org/x/exp/maps"
@@ 274,20 275,22 @@ type Pipe struct {
player oto.Player
playing bool
since time.Time
+ paused time.Time
freq float64
col color.NRGBA
}
func (p *Pipe) Play(now time.Time) {
- if !p.playing {
+ if !p.playing && p.paused != now {
p.since = now
}
p.playing = true
p.player.Play()
}
-func (p *Pipe) Pause() {
+func (p *Pipe) Pause(now time.Time) {
p.playing = false
+ p.paused = now
p.player.Pause()
}
@@ 306,7 309,7 @@ func run(w *app.Window) error {
if event.State == key.Press {
players[idx].Play(now)
} else {
- players[idx].Pause()
+ players[idx].Pause(now)
}
}
@@ 372,12 375,29 @@ func run(w *app.Window) error {
lowestFreq := freqs[0]
for i, pipe := range players {
if pipe.playing {
+ op.InvalidateOp{}.Add(gtx.Ops)
offset := op.Offset(f32.Point{X: float32(math.Round(float64(width * float32(i))))}).Push(gtx.Ops)
rect := rect
proportion := 1 / (pipe.freq / lowestFreq)
- height := int(math.Round(float64(gtx.Constraints.Max.Y) * proportion))
+ heightF := float64(gtx.Constraints.Max.Y) * proportion
+ height := int(math.Round(heightF))
gap := gtx.Constraints.Max.Y - height
- rect.Min.Y += gap
+ rect.Min.Y = gap
+
+ lightFill := pipe.col
+ lightFill.A = 100
+ paint.FillShape(gtx.Ops, lightFill, rect.Op())
+
+ duration := float64(gtx.Now.Sub(pipe.since).Milliseconds()) / 2000
+ if duration > 1 {
+ duration = 1
+ } else {
+ duration = ease.OutQuint(duration)
+ }
+
+ height = int(math.Round(heightF * duration))
+ gap = gtx.Constraints.Max.Y - height
+ rect.Min.Y = gap
paint.FillShape(gtx.Ops, pipe.col, rect.Op())
offset.Pop()