From 149174ebc3d28fd64e2d7dc5f64f6fb619f31308 Mon Sep 17 00:00:00 2001 From: Rico van Zelst Date: Wed, 8 Nov 2023 14:12:51 +0100 Subject: [PATCH] feat: champ information, style improvement --- app/Helpers/HelperFunctions.php | 45 +++++++++ app/Http/Controllers/ChampionController.php | 6 ++ app/Models/Champion.php | 34 +++++++ app/Models/ChampionRoles.php | 2 + composer.json | 1 + composer.lock | 88 ++++++++++++++++- package-lock.json | 18 +++- package.json | 4 +- resources/css/app.css | 21 ++-- .../components/champions/grid_info.blade.php | 99 ++++++++++++++++--- tailwind.config.js | 5 +- 11 files changed, 299 insertions(+), 24 deletions(-) diff --git a/app/Helpers/HelperFunctions.php b/app/Helpers/HelperFunctions.php index 158653b..7ef1569 100644 --- a/app/Helpers/HelperFunctions.php +++ b/app/Helpers/HelperFunctions.php @@ -1,5 +1,7 @@ resize(24, 24); + + $totalR = 0; + $totalG = 0; + $totalB = 0; + + $width = $img->width(); + $height = $img->height(); + + for ($x = 0; $x < $width; $x++) { + for ($y = 0; $y < $height; $y++) { + $color = $img->pickColor($x, $y); + $totalR += $color[0]; + $totalG += $color[1]; + $totalB += $color[2]; + } + } + + $pixelCount = $width * $height; + $avgR = $totalR / $pixelCount; + $avgG = $totalG / $pixelCount; + $avgB = $totalB / $pixelCount; + + return sprintf("#%02x%02x%02x", $avgR, $avgG, $avgB); +} + +function getRoleIconSvg($roleName): string +{ + $roleIcons = [ + 'Toplane' => 'icon-position-top', + 'Jungle' => 'icon-position-jungle', + 'Midlane' => 'icon-position-middle', + 'Botlane' => 'icon-position-bottom', + 'Support' => 'icon-position-utility', + ]; + + return $roleIcons[$roleName]; +} diff --git a/app/Http/Controllers/ChampionController.php b/app/Http/Controllers/ChampionController.php index 0a8c14c..9ba40df 100644 --- a/app/Http/Controllers/ChampionController.php +++ b/app/Http/Controllers/ChampionController.php @@ -51,6 +51,12 @@ class ChampionController extends Controller return $champion->load('skins', 'lanes'); }); + $splashColor = Cache::remember('championSplashColorCache' . $champion->slug, 60 * 60 * 24, function () use ($champion) { + return getAverageColorFromImageUrl($champion->getChampionImageAttribute()); + }); + + $champion->splash_color = $splashColor; + return view('champions.show', compact('champion')); } diff --git a/app/Models/Champion.php b/app/Models/Champion.php index 2c198aa..e9bd2c3 100644 --- a/app/Models/Champion.php +++ b/app/Models/Champion.php @@ -33,6 +33,40 @@ class Champion extends Model 'roles' => 'array', ]; + public function getResourceTypeAttribute($value): string + { + $resourceTypes = [ + 'BLOOD_WELL' => "Blood", + "MANA" => "Mana", + "ENERGY" => "Energy", + "NONE" => "None", + "HEALTH" => "Health", + "RAGE" => "Rage", + "COURAGE" => "Courage", + "SHIELD" => "Shield", + "FURY" => "Fury", + "FEROCITY" => "Ferocity", + "HEAT" => "Heat", + "GRIT" => "Grit", + "BLOODTHIRST" => "Bloodthirst", + "FLOW" => "Flow", + "SOUL_UNBOUND" => "Soul Unbound", + ]; + + return $resourceTypes[$value]; + } + + public function getAdaptiveTypeAttribute($value): string + { + $adaptiveTypes = [ + 'ADAPTIVE_DAMAGE' => 'Adaptive', + 'MAGIC_DAMAGE' => 'Magical', + 'PHYSICAL_DAMAGE' => 'Physical', + ]; + + return $adaptiveTypes[$value]; + } + public function sluggable(): array { return [ diff --git a/app/Models/ChampionRoles.php b/app/Models/ChampionRoles.php index db2bef9..03458c6 100644 --- a/app/Models/ChampionRoles.php +++ b/app/Models/ChampionRoles.php @@ -47,4 +47,6 @@ class ChampionRoles extends Model return $transformedRoles; } + + } diff --git a/composer.json b/composer.json index 41996f4..c30e54e 100644 --- a/composer.json +++ b/composer.json @@ -14,6 +14,7 @@ "cviebrock/eloquent-sluggable": "^10.0", "dolejska-daniel/riot-api": "^5", "guzzlehttp/guzzle": "^7.2", + "intervention/image": "^2.7", "laravel/framework": "^10.10", "laravel/sanctum": "^3.2", "laravel/tinker": "^2.8", diff --git a/composer.lock b/composer.lock index ebb407f..c7768c5 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3cf6f4de24fb85d3c45a641a3d4e7b73", + "content-hash": "dec98fa5ff307071427749b99398cf7e", "packages": [ { "name": "anhskohbo/no-captcha", @@ -1512,6 +1512,90 @@ ], "time": "2023-08-27T10:19:19+00:00" }, + { + "name": "intervention/image", + "version": "2.7.2", + "source": { + "type": "git", + "url": "https://github.com/Intervention/image.git", + "reference": "04be355f8d6734c826045d02a1079ad658322dad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Intervention/image/zipball/04be355f8d6734c826045d02a1079ad658322dad", + "reference": "04be355f8d6734c826045d02a1079ad658322dad", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "guzzlehttp/psr7": "~1.1 || ^2.0", + "php": ">=5.4.0" + }, + "require-dev": { + "mockery/mockery": "~0.9.2", + "phpunit/phpunit": "^4.8 || ^5.7 || ^7.5.15" + }, + "suggest": { + "ext-gd": "to use GD library based image processing.", + "ext-imagick": "to use Imagick based image processing.", + "intervention/imagecache": "Caching extension for the Intervention Image library" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.4-dev" + }, + "laravel": { + "providers": [ + "Intervention\\Image\\ImageServiceProvider" + ], + "aliases": { + "Image": "Intervention\\Image\\Facades\\Image" + } + } + }, + "autoload": { + "psr-4": { + "Intervention\\Image\\": "src/Intervention/Image" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oliver Vogel", + "email": "oliver@intervention.io", + "homepage": "https://intervention.io/" + } + ], + "description": "Image handling and manipulation library with support for Laravel integration", + "homepage": "http://image.intervention.io/", + "keywords": [ + "gd", + "image", + "imagick", + "laravel", + "thumbnail", + "watermark" + ], + "support": { + "issues": "https://github.com/Intervention/image/issues", + "source": "https://github.com/Intervention/image/tree/2.7.2" + }, + "funding": [ + { + "url": "https://paypal.me/interventionio", + "type": "custom" + }, + { + "url": "https://github.com/Intervention", + "type": "github" + } + ], + "time": "2022-05-21T17:30:32+00:00" + }, { "name": "laravel/framework", "version": "v10.30.1", @@ -10272,5 +10356,5 @@ "php": "^8.1" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/package-lock.json b/package-lock.json index f989f5a..d7c2d6f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,9 +6,11 @@ "": { "dependencies": { "flowbite": "^2.0.0", - "npm-run-all": "^4.1.5" + "npm-run-all": "^4.1.5", + "tailwind-capitalize-first-letter": "^1.0.4" }, "devDependencies": { + "@tailwindcss/aspect-ratio": "^0.4.2", "autoprefixer": "^10.4.16", "axios": "^1.1.2", "laravel-vite-plugin": "^0.8.0", @@ -473,6 +475,15 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@tailwindcss/aspect-ratio": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/aspect-ratio/-/aspect-ratio-0.4.2.tgz", + "integrity": "sha512-8QPrypskfBa7QIMuKHg2TA7BqES6vhBrDLOv8Unb6FcFyd3TjKbc6lcmb9UPQHxfl24sXoJ41ux/H7qQQvfaSQ==", + "dev": true, + "peerDependencies": { + "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" + } + }, "node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -2547,6 +2558,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tailwind-capitalize-first-letter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tailwind-capitalize-first-letter/-/tailwind-capitalize-first-letter-1.0.4.tgz", + "integrity": "sha512-ZB8hBi68JI4aQ1cDUxuFWfMYTxgBvlzIdPPHSkFkMUlo7p2QlbMy0hVv/vAREAFmkUh9QfjuKQnOSbe4Gnqljg==" + }, "node_modules/tailwindcss": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.5.tgz", diff --git a/package.json b/package.json index 4fd1d66..8ab502b 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "laravel-pint": "./vendor/bin/pint" }, "devDependencies": { + "@tailwindcss/aspect-ratio": "^0.4.2", "autoprefixer": "^10.4.16", "axios": "^1.1.2", "laravel-vite-plugin": "^0.8.0", @@ -19,6 +20,7 @@ }, "dependencies": { "flowbite": "^2.0.0", - "npm-run-all": "^4.1.5" + "npm-run-all": "^4.1.5", + "tailwind-capitalize-first-letter": "^1.0.4" } } diff --git a/resources/css/app.css b/resources/css/app.css index 18258ec..e249b2d 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -7,23 +7,32 @@ position: absolute; inset: 0; border-radius: 1rem; - background: linear-gradient(90deg, rgba(239, 148, 61, 0.7), rgba(245, 101, 35, 0.7)); + background: var(--splash-color); opacity: 0; - filter: blur(5px); + filter: blur(8px); animation: glow 4s infinite; + --tw-scale-x: 1.02; + --tw-scale-y: 1.02; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.shadow-md-splash { + --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 4px 6px -1px var(--splash-color), 0 2px 4px -2px var(--splash-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } @keyframes glow { 0% { - opacity: 0.5; + opacity: 0.8; filter: blur(8px); } 50% { - opacity: 0.2; - filter: blur(13px); + opacity: 0.45; + filter: blur(11px); } 100% { - opacity: 0.5; + opacity: 0.8; filter: blur(8px); } } diff --git a/resources/views/components/champions/grid_info.blade.php b/resources/views/components/champions/grid_info.blade.php index 3dd437b..74768df 100644 --- a/resources/views/components/champions/grid_info.blade.php +++ b/resources/views/components/champions/grid_info.blade.php @@ -14,10 +14,12 @@ {{$champion->title}}
-
-
-
-
+
+
+
+
{{$champion->name}} Splash Art
-
- 5
-
8 + class="rounded-2xl border border-3 border-white/10 + lg:col-start-3 shadow-md transition-all duration-700" + style="--tw-shadow-color:{{$champion->splash_color}}; --tw-shadow: var(--tw-shadow-colored); background-color: {{$champion->splash_color}};"> + +

+ {{$champion->name}} Information

+ +
    + +
  • + Full Title: {{$champion->name}}, {{$champion->title}}. +
  • +
  • + Popular Positions: @foreach($champion->lanes->roles as $lane) + {{$lane}} @svg(getRoleIconSvg($lane), 'w-5 h-5 inline-block') + @if(!$loop->last) + - + @endif + @endforeach +
  • +
  • + Blue Essence Cost: + {{$champion->price_be}} BE +
  • +
  • + Riot Points Cost: + {{$champion->price_rp}} RP +
  • +
  • + Roles: @foreach($champion->roles as $role) + {{$role}} + @if(!$loop->last) + - + @endif + @endforeach +
  • +
  • + Attack Type: {{$champion->attack_type}} +
  • +
  • + Damage Type: {{$champion->adaptive_type}} +
  • +
  • + Resource Type: {{$champion->resource_type}} +
  • +
  • + Champion ID: {{$champion->champion_id}} +
  • +
  • + Release Date: {{$champion->release_date}} +
  • +
  • + Release Patch: Patch {{$champion->release_patch}} +
  • +
+
+ + +
+
+

+ {{$champion->name}} Lore

+

+ {{$champion->lore}} +

+
+
- 9
+ class="rounded-2xl border border-3 border-white/10 shadow-md + shadow-stone-800/80 lg:col-span-2 hover:shadow-orange-500/20 transition-all duration-700" + style="--tw-shadow-color:{{$champion->splash_color}}; --tw-shadow: var(--tw-shadow-colored); background-color: {{$champion->splash_color}};"> + 3 +
diff --git a/tailwind.config.js b/tailwind.config.js index c85e45b..2a06ff0 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -23,5 +23,8 @@ module.exports = { }, }, }, - plugins: [require("flowbite/plugin")], + corePlugins: { + aspectRatio: false, + }, + plugins: [require("flowbite/plugin"), require("@tailwindcss/aspect-ratio"), require('tailwind-capitalize-first-letter'),], };