Playing around with SVG

This commit is contained in:
Eduard Urbach 2017-07-07 02:07:34 +02:00
parent 137a2270df
commit 567e8e63d1
7 changed files with 153 additions and 0 deletions

View File

@ -31,6 +31,7 @@ import (
"github.com/animenotifier/notify.moe/pages/profile" "github.com/animenotifier/notify.moe/pages/profile"
"github.com/animenotifier/notify.moe/pages/search" "github.com/animenotifier/notify.moe/pages/search"
"github.com/animenotifier/notify.moe/pages/settings" "github.com/animenotifier/notify.moe/pages/settings"
"github.com/animenotifier/notify.moe/pages/statistics"
"github.com/animenotifier/notify.moe/pages/threads" "github.com/animenotifier/notify.moe/pages/threads"
"github.com/animenotifier/notify.moe/pages/tracks" "github.com/animenotifier/notify.moe/pages/tracks"
"github.com/animenotifier/notify.moe/pages/user" "github.com/animenotifier/notify.moe/pages/user"
@ -91,6 +92,7 @@ func configure(app *aero.Application) *aero.Application {
app.Ajax("/import/anilist/animelist", listimportanilist.Preview) app.Ajax("/import/anilist/animelist", listimportanilist.Preview)
app.Ajax("/import/anilist/animelist/finish", listimportanilist.Finish) app.Ajax("/import/anilist/animelist/finish", listimportanilist.Finish)
app.Ajax("/admin", admin.Get) app.Ajax("/admin", admin.Get)
app.Ajax("/statistics", statistics.Get)
app.Ajax("/search", search.Get) app.Ajax("/search", search.Get)
app.Ajax("/search/:term", search.Get) app.Ajax("/search/:term", search.Get)
app.Ajax("/users", users.Get) app.Ajax("/users", users.Get)

View File

@ -0,0 +1,71 @@
package statistics
import (
"net/http"
"github.com/aerogo/aero"
"github.com/animenotifier/arn"
"github.com/animenotifier/notify.moe/components"
"github.com/animenotifier/notify.moe/utils"
)
// Get ...
func Get(ctx *aero.Context) string {
analytics, err := arn.AllAnalytics()
if err != nil {
return ctx.Error(http.StatusInternalServerError, "Couldn't retrieve analytics", err)
}
screenSizes := map[string]int{}
for _, info := range analytics {
size := arn.ToString(info.Screen.Width) + " x " + arn.ToString(info.Screen.Height)
screenSizes[size]++
}
screenSizesSorted := []*utils.AnalyticsItem{}
for size, count := range screenSizes {
item := &utils.AnalyticsItem{
Key: size,
Value: count,
}
if len(screenSizesSorted) == 0 {
screenSizesSorted = append(screenSizesSorted, item)
continue
}
found := false
for i := 0; i < len(screenSizesSorted); i++ {
if count >= screenSizesSorted[i].Value {
// Append empty element
screenSizesSorted = append(screenSizesSorted, nil)
// Move all elements after index "i" 1 position up
copy(screenSizesSorted[i+1:], screenSizesSorted[i:])
// Set value for index "i"
screenSizesSorted[i] = item
// Set flag
found = true
// Leave loop
break
}
}
if !found {
screenSizesSorted = append(screenSizesSorted, item)
}
}
if len(screenSizesSorted) > 5 {
screenSizesSorted = screenSizesSorted[:5]
}
return ctx.HTML(components.Statistics(screenSizesSorted))
}

View File

@ -0,0 +1,13 @@
component Statistics(screenSizes []*utils.AnalyticsItem)
h1 Statistics
.statistics
h3 Screen size
PieChart
//- canvas#screen-sizes.graph(data-values=utils.ToJSON(screenSizes))
component PieChart
svg.graph(viewBox="-1.05 -1.05 2.1 2.1")
path.slice.slice-1(d=utils.SVGSlicePath(0, 0.5))
path.slice.slice-2(d=utils.SVGSlicePath(0.5, 0.8))
path.slice.slice-3(d=utils.SVGSlicePath(0.8, 1.0))

View File

@ -0,0 +1,24 @@
.statistics
vertical
align-items center
.graph
transform rotate(-90deg)
width 250px
height 250px
.slice
color black
default-transition
transform scale(1)
:hover
transform scale(1.05)
.slice-1
opacity 0.8
.slice-2
opacity 0.6
.slice-3
opacity 0.4

7
utils/AnalyticsItem.go Normal file
View File

@ -0,0 +1,7 @@
package utils
// AnalyticsItem ...
type AnalyticsItem struct {
Key string
Value int
}

27
utils/SVGPieChartPath.go Normal file
View File

@ -0,0 +1,27 @@
package utils
import (
"fmt"
"math"
)
// coords returns the coordinates for the given percentage.
func coords(percent float64) (float64, float64) {
x := math.Cos(2 * math.Pi * percent)
y := math.Sin(2 * math.Pi * percent)
return x, y
}
// SVGSlicePath creates a path string for a slice in a pie chart.
func SVGSlicePath(from float64, to float64) string {
x1, y1 := coords(from)
x2, y2 := coords(to)
largeArc := "0"
if to-from > 0.5 {
largeArc = "1"
}
return fmt.Sprintf("M %.2f %.2f A 1 1 0 %s 1 %.2f %.2f L 0 0", x1, y1, largeArc, x2, y2)
}

9
utils/ToJSON.go Normal file
View File

@ -0,0 +1,9 @@
package utils
import "encoding/json"
// ToJSON converts an object to a JSON string, ignoring errors.
func ToJSON(v interface{}) string {
str, _ := json.Marshal(v)
return string(str)
}