Skip to content

Commit

Permalink
feat: add svgclock example
Browse files Browse the repository at this point in the history
  • Loading branch information
twpayne committed May 13, 2024
1 parent cd02e9e commit 34df65f
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 0 deletions.
11 changes: 11 additions & 0 deletions cmd/svgclock/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# svgclock

This example demonstrates dynamic generation of an SVG file.

Run it:

```console
$ go run github.com/twpayne/go-svg/cmd/svgclock
```

and visit http://localhost:8080 in your web browser.
9 changes: 9 additions & 0 deletions cmd/svgclock/index.html.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<html>
<head>
<title>Clock</title>
<meta http-equiv="refresh" content="1">
</head>
<body>
{{ now | svgClock }}
</body>
</html>
95 changes: 95 additions & 0 deletions cmd/svgclock/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package main

import (
_ "embed"
"flag"
"fmt"
"html/template"
"math"
"net/http"
"os"
"time"

"github.com/twpayne/go-svg"
"github.com/twpayne/go-svg/svgpath"
)

//go:embed index.html.tmpl
var indexHTML string

func rad(deg int) float64 {
return math.Pi * float64(deg) / 180
}

func svgClock(t time.Time) *svg.SVGElement {
width := 128.0
height := 128.0
buffer := 4.0
diameter := min(width-2*buffer, height-2*buffer)
radius := diameter / 2
hour, minute, second := t.Hour(), t.Minute(), t.Second()
handElements := make([]svg.Element, 0, 3)
for _, hand := range []struct {
angle float64
length float64
stroke svg.String
strokeWidth svg.Length
}{
{
length: 0.8,
angle: rad(360*second/60 - 90),
stroke: svg.String("red"),
strokeWidth: svg.Number(1),
},
{
length: 0.9,
angle: rad(360*(60*minute+second)/(60*60) - 90),
stroke: svg.String("black"),
strokeWidth: svg.Number(3),
},
{
length: 0.6,
angle: rad(360*((hour%12)*60*60+minute*60+second)/(12*60*60) - 90),
stroke: svg.String("black"),
strokeWidth: svg.Number(5),
},
} {
handElement := svg.Path().D(svgpath.New().
MoveToAbs([]float64{width / 2, height / 2}).
LineToRel([]float64{hand.length * radius * math.Cos(hand.angle), hand.length * radius * math.Sin(hand.angle)}).
ClosePath(),
).Stroke(hand.stroke).StrokeWidth(hand.strokeWidth)
handElements = append(handElements, handElement)
}
return svg.New().WidthHeight(width, height, svg.Number).ViewBox(0, 0, width, height).Children(
svg.Circle().CXCYR(width/2, height/2, radius, svg.Number).Fill("none").Stroke("black"),
).AppendChildren(handElements...)
}

func run() error {
addr := flag.String("addr", ":8080", "address")
flag.Parse()

indexTemplate, err := template.New("").Funcs(template.FuncMap{
"now": time.Now,
"svgClock": func(t time.Time) template.HTML {
return template.HTML(svgClock(t).String())
},
}).Parse(indexHTML)
if err != nil {
return err
}

http.HandleFunc("GET /", func(w http.ResponseWriter, r *http.Request) {
_ = indexTemplate.Execute(w, nil)
})

return http.ListenAndServe(*addr, nil)
}

func main() {
if err := run(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}

0 comments on commit 34df65f

Please sign in to comment.