From aa6ba4c5667da64dc64ecd54ba1e17aa72005307 Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Wed, 21 Mar 2018 22:57:06 +0100 Subject: [PATCH] Added anime image search by color --- pages/explore/explore.pixy | 3 + pages/explore/explorecolor/explorecolor.go | 69 +++++++++++++++++++ pages/explore/explorecolor/explorecolor.pixy | 18 +++++ .../explore/explorecolor/explorecolor.scarlet | 13 ++++ pages/index.go | 2 + scripts/AnimeNotifier.ts | 13 ++++ 6 files changed, 118 insertions(+) create mode 100644 pages/explore/explorecolor/explorecolor.go create mode 100644 pages/explore/explorecolor/explorecolor.pixy create mode 100644 pages/explore/explorecolor/explorecolor.scarlet diff --git a/pages/explore/explore.pixy b/pages/explore/explore.pixy index 9a14ee17..390c90cd 100644 --- a/pages/explore/explore.pixy +++ b/pages/explore/explore.pixy @@ -6,6 +6,9 @@ component ExploreAnime(animeList []*arn.Anime, year string, status string, typ s button.action(data-trigger="click", data-action="hideAddedAnime", title="Hide anime in my collection") RawIcon("eye-slash") + a.button.ajax(href="/explore/color/any/anime", title="View colors") + RawIcon("paint-brush") + a.button.ajax(href="/genres", title="View genres") RawIcon("clone") diff --git a/pages/explore/explorecolor/explorecolor.go b/pages/explore/explorecolor/explorecolor.go new file mode 100644 index 00000000..ca2b7a70 --- /dev/null +++ b/pages/explore/explorecolor/explorecolor.go @@ -0,0 +1,69 @@ +package explorecolor + +import ( + "math" + "strconv" + "strings" + + "github.com/aerogo/aero" + "github.com/animenotifier/arn" + "github.com/animenotifier/notify.moe/components" + "github.com/animenotifier/notify.moe/utils" +) + +// AnimeByAverageColor returns all anime with an image in the given color. +func AnimeByAverageColor(ctx *aero.Context) string { + user := utils.GetUser(ctx) + color := ctx.Get("color") + animes := filterAnimeByColor(color) + + arn.SortAnimeByQuality(animes) + + return ctx.HTML(components.ExploreColor(animes, color, user)) +} + +func filterAnimeByColor(colorText string) []*arn.Anime { + if !strings.HasPrefix(colorText, "hsl:") { + return nil + } + + colorText = colorText[len("hsl:"):] + parts := strings.Split(colorText, ",") + + if len(parts) != 3 { + return nil + } + + hue, err := strconv.ParseFloat(parts[0], 64) + + if err != nil { + return nil + } + + saturation, err := strconv.ParseFloat(parts[1], 64) + + if err != nil { + return nil + } + + lightness, err := strconv.ParseFloat(parts[2], 64) + + if err != nil { + return nil + } + + color := arn.HSLColor{ + Hue: hue, + Saturation: saturation, + Lightness: lightness, + } + + return arn.FilterAnime(func(anime *arn.Anime) bool { + animeColor := anime.Image.AverageColor + hueDifference := color.Hue - animeColor.Hue + saturationDifference := color.Saturation - animeColor.Saturation + lightnessDifference := color.Lightness - animeColor.Lightness + + return math.Abs(hueDifference) < 0.05 && math.Abs(saturationDifference) < 0.125 && math.Abs(lightnessDifference) < 0.25 + }) +} diff --git a/pages/explore/explorecolor/explorecolor.pixy b/pages/explore/explorecolor/explorecolor.pixy new file mode 100644 index 00000000..9c50b19d --- /dev/null +++ b/pages/explore/explorecolor/explorecolor.pixy @@ -0,0 +1,18 @@ +component ExploreColor(animes []*arn.Anime, color string, user *arn.User) + h1.page-title Explore anime by color + + for saturation := 0.75; saturation >= 0.25; saturation -= 0.25 + .tabs.color-stripes + for hue := 0.0; hue < 1.0; hue += 0.05 + a.tab.color-stripe.action(href=fmt.Sprintf("/explore/color/hsl:%.3f,%.2f,0.5/anime", hue, saturation), data-action="diff", data-trigger="click", data-color=fmt.Sprintf("hsl(%.0f, %.0f%%, 50%%)", hue * 360, saturation * 100)) + + .explore-anime + if len(animes) == 0 + if color == "any" + p.no-data.mountable Please choose a color. + else + p.no-data.mountable No anime found for the given color. + else + p.text-center.mountable= strconv.Itoa(len(animes)) + " anime." + + AnimeGrid(animes, user) \ No newline at end of file diff --git a/pages/explore/explorecolor/explorecolor.scarlet b/pages/explore/explorecolor/explorecolor.scarlet new file mode 100644 index 00000000..a40e320e --- /dev/null +++ b/pages/explore/explorecolor/explorecolor.scarlet @@ -0,0 +1,13 @@ +.color-stripes + horizontal + justify-content center + margin-bottom 0 + +.color-stripe + width 2% + height 2rem + padding 0 + border 1px solid transparent + + &.active + border 1px solid theme-black \ No newline at end of file diff --git a/pages/index.go b/pages/index.go index da8b39ff..59340a6e 100644 --- a/pages/index.go +++ b/pages/index.go @@ -26,6 +26,7 @@ import ( "github.com/animenotifier/notify.moe/pages/embed" "github.com/animenotifier/notify.moe/pages/episode" "github.com/animenotifier/notify.moe/pages/explore" + "github.com/animenotifier/notify.moe/pages/explore/explorecolor" "github.com/animenotifier/notify.moe/pages/forum" "github.com/animenotifier/notify.moe/pages/genre" "github.com/animenotifier/notify.moe/pages/genres" @@ -75,6 +76,7 @@ func Configure(app *aero.Application) { l.Page("/", home.Get) l.Page("/explore", explore.Get) l.Page("/explore/anime/:year/:status/:type", explore.Filter) + l.Page("/explore/color/:color/anime", explorecolor.AnimeByAverageColor) l.Page("/login", login.Get) l.Page("/api", apiview.Get) // l.Ajax("/dashboard", dashboard.Get) diff --git a/scripts/AnimeNotifier.ts b/scripts/AnimeNotifier.ts index 53ca8d74..d59f5309 100644 --- a/scripts/AnimeNotifier.ts +++ b/scripts/AnimeNotifier.ts @@ -163,6 +163,7 @@ export class AnimeNotifier { Promise.resolve().then(() => this.assignActions()), Promise.resolve().then(() => this.updatePushUI()), Promise.resolve().then(() => this.dragAndDrop()), + Promise.resolve().then(() => this.colorStripes()), Promise.resolve().then(() => this.countUp()) ]) @@ -346,6 +347,18 @@ export class AnimeNotifier { } } + colorStripes() { + if(!this.app.currentPath.includes("/explore/color/")) { + return + } + + for(let element of findAll("color-stripe")) { + Diff.mutations.queue(() => { + element.style.backgroundColor = element.dataset.color + }) + } + } + countUp() { if(!this.app.currentPath.includes("/paypal/success")) { return