loader.go 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. // SPDX-License-Identifier: Unlicense OR MIT
  2. package material
  3. import (
  4. "image"
  5. "image/color"
  6. "math"
  7. "time"
  8. "gioui.org/f32"
  9. "gioui.org/layout"
  10. "gioui.org/op"
  11. "gioui.org/op/clip"
  12. "gioui.org/op/paint"
  13. )
  14. type LoaderStyle struct {
  15. Color color.NRGBA
  16. }
  17. func Loader(th *Theme) LoaderStyle {
  18. return LoaderStyle{
  19. Color: th.Palette.ContrastBg,
  20. }
  21. }
  22. func (l LoaderStyle) Layout(gtx layout.Context) layout.Dimensions {
  23. diam := gtx.Constraints.Min.X
  24. if minY := gtx.Constraints.Min.Y; minY > diam {
  25. diam = minY
  26. }
  27. if diam == 0 {
  28. diam = gtx.Dp(24)
  29. }
  30. sz := gtx.Constraints.Constrain(image.Pt(diam, diam))
  31. radius := sz.X / 2
  32. defer op.Offset(image.Pt(radius, radius)).Push(gtx.Ops).Pop()
  33. dt := float32((time.Duration(gtx.Now.UnixNano()) % (time.Second)).Seconds())
  34. startAngle := dt * math.Pi * 2
  35. endAngle := startAngle + math.Pi*1.5
  36. defer clipLoader(gtx.Ops, startAngle, endAngle, float32(radius)).Push(gtx.Ops).Pop()
  37. paint.ColorOp{
  38. Color: l.Color,
  39. }.Add(gtx.Ops)
  40. defer op.Offset(image.Pt(-radius, -radius)).Push(gtx.Ops).Pop()
  41. paint.PaintOp{}.Add(gtx.Ops)
  42. gtx.Execute(op.InvalidateCmd{})
  43. return layout.Dimensions{
  44. Size: sz,
  45. }
  46. }
  47. func clipLoader(ops *op.Ops, startAngle, endAngle, radius float32) clip.Op {
  48. const thickness = .25
  49. var (
  50. width = radius * thickness
  51. delta = endAngle - startAngle
  52. vy, vx = math.Sincos(float64(startAngle))
  53. inner = radius * (1. - thickness*.5)
  54. pen = f32.Pt(float32(vx), float32(vy)).Mul(inner)
  55. center = f32.Pt(0, 0).Sub(pen)
  56. p clip.Path
  57. )
  58. p.Begin(ops)
  59. p.Move(pen)
  60. p.Arc(center, center, delta)
  61. return clip.Stroke{
  62. Path: p.End(),
  63. Width: width,
  64. }.Op()
  65. }