gopherjs - progress/progress.go
1 // Package progress creates a simple progress bar in javascript
2 package progress // import "vimagination.zapto.org/gopherjs/progress"
3
4 import (
5 "image/color"
6 "io"
7 "strconv"
8
9 "vimagination.zapto.org/gopherjs/xdom"
10
11 "honnef.co/go/js/dom"
12 )
13
14 // Bar is a wrapper around a Canvas element to draw a simple progress
15 // bar.
16 //
17 // It also implements dom.Node, so it can be Appended to any other node.
18 type Bar struct {
19 *dom.HTMLCanvasElement
20 percent int
21 ctx *dom.CanvasRenderingContext2D
22 width, height int
23 foreground, background string
24 }
25
26 // Percent sets the current percentage shown
27 func (b *Bar) Percent(i int) {
28 if i != b.percent {
29 b.percent = i
30 b.draw()
31 }
32 }
33
34 func (b *Bar) draw() {
35 b.ctx.FillStyle = b.background
36 b.ctx.FillRect(0, 0, b.width, b.height)
37 b.ctx.FillStyle = b.foreground
38 b.ctx.FillRect(0, 0, b.width*b.percent/100, b.height)
39 }
40
41 // New returns a new Bar
42 func New(fore, back color.Color, width, height int) *Bar {
43 c := xdom.Canvas()
44 c.Width = width
45 c.Height = height
46 r, g, b, _ := fore.RGBA()
47 foreground := "rgb(" + strconv.Itoa(int(r>>8)) + ", " + strconv.Itoa(int(g>>8)) + ", " + strconv.Itoa(int(b>>8)) + ")"
48 r, g, b, _ = back.RGBA()
49 background := "rgb(" + strconv.Itoa(int(r>>8)) + ", " + strconv.Itoa(int(g>>8)) + ", " + strconv.Itoa(int(b>>8)) + ")"
50 bar := &Bar{
51 HTMLCanvasElement: c,
52 ctx: c.GetContext2d(),
53 width: width,
54 height: height,
55 foreground: foreground,
56 background: background,
57 }
58 bar.draw()
59 return bar
60 }
61
62 // Reader wraps a ProgressBar to automatically update when an io.Reader
63 // is read
64 type Reader struct {
65 *Bar
66 io.Reader
67 offset, size int
68 }
69
70 // Reader returns a Reader type
71 func (b *Bar) Reader(r io.Reader, size int) *Reader {
72 return &Reader{b, r, 0, size}
73 }
74
75 // Read implements io.Reader
76 func (r *Reader) Read(p []byte) (int, error) {
77 n, err := r.Reader.Read(p)
78 r.offset += n
79 r.Percent(100 * r.offset / r.size)
80 return n, err
81 }
82
83 // Len returns the total length of the data
84 func (r *Reader) Len() int {
85 return int(r.size)
86 }