mirror of
https://github.com/vkaelin/LeagueStats.git
synced 2026-03-25 12:57:28 +00:00
feat: first "working" version of detailed runes
This commit is contained in:
parent
69373c42ea
commit
bf05f12829
16 changed files with 581 additions and 160 deletions
|
|
@ -2,6 +2,7 @@
|
|||
<div id="app" class="min-h-screen font-sans antialiased bg-blue-900">
|
||||
<SVGContainer />
|
||||
<NotificationsContainer />
|
||||
<RunesContainer />
|
||||
<component :is="layout">
|
||||
<router-view />
|
||||
</component>
|
||||
|
|
@ -13,6 +14,7 @@ import { mapActions } from 'vuex'
|
|||
import Default from '@/layouts/Default.vue'
|
||||
import Home from '@/layouts/Home.vue'
|
||||
import NotificationsContainer from '@/components/Global/NotificationsContainer.vue'
|
||||
import RunesContainer from '@/components/Match/Runes/RunesContainer.vue'
|
||||
import SVGContainer from '@/components/Global/SVGContainer.vue'
|
||||
|
||||
export default {
|
||||
|
|
@ -20,13 +22,14 @@ export default {
|
|||
Default,
|
||||
Home,
|
||||
NotificationsContainer,
|
||||
SVGContainer
|
||||
RunesContainer,
|
||||
SVGContainer,
|
||||
},
|
||||
|
||||
computed: {
|
||||
layout() {
|
||||
return (this.$route.meta.layout || 'Default')
|
||||
}
|
||||
return this.$route.meta.layout || 'Default'
|
||||
},
|
||||
},
|
||||
|
||||
created() {
|
||||
|
|
@ -38,6 +41,6 @@ export default {
|
|||
|
||||
methods: {
|
||||
...mapActions('settings', ['updatePercent', 'updateSettings']),
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -40,6 +40,11 @@
|
|||
transition: opacity 2s;
|
||||
}
|
||||
|
||||
.fade-fast-enter-active, .fade-fast-leave-active {
|
||||
transition: opacity .5s;
|
||||
}
|
||||
|
||||
.fade-fast-enter, .fade-fast-leave-to,
|
||||
.fade-enter, .fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
|
|
|||
BIN
client/src/assets/img/runes/domination.jpg
Normal file
BIN
client/src/assets/img/runes/domination.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 84 KiB |
BIN
client/src/assets/img/runes/inspiration.jpg
Normal file
BIN
client/src/assets/img/runes/inspiration.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 94 KiB |
BIN
client/src/assets/img/runes/precision.jpg
Normal file
BIN
client/src/assets/img/runes/precision.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
BIN
client/src/assets/img/runes/resolve.jpg
Normal file
BIN
client/src/assets/img/runes/resolve.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 77 KiB |
BIN
client/src/assets/img/runes/sorcery.jpg
Normal file
BIN
client/src/assets/img/runes/sorcery.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
|
|
@ -13,7 +13,7 @@
|
|||
<span
|
||||
:class="allyTeam ? 'text-teal-400' : 'text-red-400'"
|
||||
class="pl-2"
|
||||
>{{ allyTeam ? 'Ally' : 'Enemy' }} Team</span>
|
||||
>{{ allyTeam ? "Ally" : "Enemy" }} Team</span>
|
||||
<div
|
||||
v-if="data.result === 'Win'"
|
||||
:class="allyTeam ? 'text-teal-400' : 'text-red-400'"
|
||||
|
|
@ -29,12 +29,12 @@
|
|||
<th class="px-2 py-5 text-sm font-medium w-kda">K</th>
|
||||
<th class="px-2 py-5 text-sm font-medium w-kda">D</th>
|
||||
<th class="px-2 py-5 text-sm font-medium w-kda">A</th>
|
||||
<th
|
||||
class="px-2 py-5 text-sm font-medium w-minions"
|
||||
>{{ statsFormat === 'stats' ? 'Cs' : 'Cs/m' }}</th>
|
||||
<th
|
||||
class="px-2 py-5 text-sm font-medium w-vision"
|
||||
>{{ statsFormat === 'stats' ? 'Vs' : 'Vs/m' }}</th>
|
||||
<th class="px-2 py-5 text-sm font-medium w-minions">
|
||||
{{ statsFormat === "stats" ? "Cs" : "Cs/m" }}
|
||||
</th>
|
||||
<th class="px-2 py-5 text-sm font-medium w-vision">
|
||||
{{ statsFormat === "stats" ? "Vs" : "Vs/m" }}
|
||||
</th>
|
||||
<th class="px-2 py-5 text-sm font-medium w-gold-dmg-kp">Gold</th>
|
||||
<th class="px-2 py-5 text-sm font-medium w-gold-dmg-kp">
|
||||
Dmg
|
||||
|
|
@ -51,7 +51,10 @@
|
|||
<th class="px-2 py-5 text-sm font-medium w-gold-dmg-kp">KP</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody :class="{'border-b border-blue-700': allyTeam}" class="leading-none">
|
||||
<tbody
|
||||
:class="{ 'border-b border-blue-700': allyTeam }"
|
||||
class="leading-none"
|
||||
>
|
||||
<tr v-for="(player, index) in data.players" :key="player.name + index">
|
||||
<td class="py-2 border-r border-blue-700">
|
||||
<div class="flex justify-between px-1">
|
||||
|
|
@ -59,7 +62,11 @@
|
|||
<div class="flex items-center">
|
||||
<div
|
||||
v-if="player.role !== 'NONE'"
|
||||
:style="{backgroundImage: `url(${require('@/assets/img/roles/' + player.role + '.png')})`}"
|
||||
:style="{
|
||||
backgroundImage: `url(${require('@/assets/img/roles/' +
|
||||
player.role +
|
||||
'.png')})`,
|
||||
}"
|
||||
class="w-4 h-4 bg-center bg-cover"
|
||||
></div>
|
||||
</div>
|
||||
|
|
@ -68,7 +75,11 @@
|
|||
class="relative w-8 h-8 ml-2 bg-center bg-cover rounded-full bg-blue-1000"
|
||||
>
|
||||
<div
|
||||
:class="allyTeam ? 'bg-teal-500 text-teal-100' : 'bg-red-500 text-red-100'"
|
||||
:class="
|
||||
allyTeam
|
||||
? 'bg-teal-500 text-teal-100'
|
||||
: 'bg-red-500 text-red-100'
|
||||
"
|
||||
class="absolute bottom-0 flex items-center justify-center w-4 h-4 rounded-full level-position text-xxs"
|
||||
>
|
||||
<span>{{ player.level }}</span>
|
||||
|
|
@ -78,20 +89,32 @@
|
|||
<Tooltip>
|
||||
<template v-slot:trigger>
|
||||
<div
|
||||
:style="{backgroundImage: `url(${player.firstSum ? player.firstSum.icon : null})`}"
|
||||
:style="{
|
||||
backgroundImage: `url(${
|
||||
player.firstSum ? player.firstSum.icon : null
|
||||
})`,
|
||||
}"
|
||||
:class="{ 'cursor-pointer': player.firstSum }"
|
||||
class="w-4 h-4 bg-center bg-cover rounded-md bg-blue-1000"
|
||||
></div>
|
||||
</template>
|
||||
<template v-if="player.firstSum" v-slot:default>
|
||||
<div class="flex max-w-sm p-2 text-xs text-left text-white select-none">
|
||||
<div
|
||||
:style="{backgroundImage: `url('${player.firstSum.icon}')`}"
|
||||
class="flex max-w-sm p-2 text-xs text-left text-white select-none"
|
||||
>
|
||||
<div
|
||||
:style="{
|
||||
backgroundImage: `url('${player.firstSum.icon}')`,
|
||||
}"
|
||||
class="flex-shrink-0 w-12 h-12 ml-1 bg-center bg-cover rounded-md bg-blue-1000"
|
||||
></div>
|
||||
<div class="ml-2 leading-tight">
|
||||
<div class="text-base leading-none">{{ player.firstSum.name }}</div>
|
||||
<div class="mt-1 font-light text-blue-200">{{ player.firstSum.description }}</div>
|
||||
<div class="text-base leading-none">
|
||||
{{ player.firstSum.name }}
|
||||
</div>
|
||||
<div class="mt-1 font-light text-blue-200">
|
||||
{{ player.firstSum.description }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -99,57 +122,111 @@
|
|||
<Tooltip>
|
||||
<template v-slot:trigger>
|
||||
<div
|
||||
:style="{backgroundImage: `url(${player.secondSum ? player.secondSum.icon : null})`}"
|
||||
:style="{
|
||||
backgroundImage: `url(${
|
||||
player.secondSum ? player.secondSum.icon : null
|
||||
})`,
|
||||
}"
|
||||
:class="{ 'cursor-pointer': player.secondSum }"
|
||||
class="w-4 h-4 bg-center bg-cover rounded-md bg-blue-1000"
|
||||
></div>
|
||||
</template>
|
||||
<template v-if="player.secondSum" v-slot:default>
|
||||
<div class="flex max-w-sm p-2 text-xs text-left text-white select-none">
|
||||
<div
|
||||
:style="{backgroundImage: `url('${player.secondSum.icon}')`}"
|
||||
class="flex max-w-sm p-2 text-xs text-left text-white select-none"
|
||||
>
|
||||
<div
|
||||
:style="{
|
||||
backgroundImage: `url('${player.secondSum.icon}')`,
|
||||
}"
|
||||
class="flex-shrink-0 w-12 h-12 ml-1 bg-center bg-cover rounded-md bg-blue-1000"
|
||||
></div>
|
||||
<div class="ml-2 leading-tight">
|
||||
<div class="text-base leading-none">{{ player.secondSum.name }}</div>
|
||||
<div
|
||||
class="mt-1 font-light text-blue-200"
|
||||
>{{ player.secondSum.description }}</div>
|
||||
<div class="text-base leading-none">
|
||||
{{ player.secondSum.name }}
|
||||
</div>
|
||||
<div class="mt-1 font-light text-blue-200">
|
||||
{{ player.secondSum.description }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div class="flex flex-col justify-around ml-2px">
|
||||
<Tooltip>
|
||||
<template v-slot:trigger>
|
||||
<div
|
||||
:style="[player.primaryRune ? {background: `url(${player.primaryRune}) center/cover`} : '']"
|
||||
@click="selectRunes(player)"
|
||||
:class="{ 'cursor-pointer': player.perks }"
|
||||
class="flex flex-col justify-around cursor-pointer ml-2px"
|
||||
>
|
||||
<div
|
||||
:style="[
|
||||
player.primaryRune
|
||||
? {
|
||||
background: `url(${player.primaryRune}) center/cover`,
|
||||
}
|
||||
: '',
|
||||
]"
|
||||
class="w-4 h-4 rounded-md bg-blue-1000"
|
||||
></div>
|
||||
<div
|
||||
:style="[player.secondaryRune ? {background: `url(${player.secondaryRune}) center/cover`} : '']"
|
||||
:style="[
|
||||
player.secondaryRune
|
||||
? {
|
||||
background: `url(${player.secondaryRune}) center/cover`,
|
||||
}
|
||||
: '',
|
||||
]"
|
||||
class="w-4 h-4 rounded-md bg-blue-1000"
|
||||
></div>
|
||||
</div>
|
||||
<div class="flex flex-col items-start justify-center ml-1 leading-none">
|
||||
</template>
|
||||
<template v-if="player.perks" v-slot:default>
|
||||
<div
|
||||
class="px-2 text-sm leading-relaxed text-center text-white select-none"
|
||||
>
|
||||
<p>Click to display</p>
|
||||
<p class="font-bold text-teal-400">full runes</p>
|
||||
</div>
|
||||
</template>
|
||||
</Tooltip>
|
||||
<div
|
||||
class="flex flex-col items-start justify-center ml-1 leading-none"
|
||||
>
|
||||
<router-link
|
||||
v-if="player.firstSum"
|
||||
:to="{ name: 'summoner', params: { region: $route.params.region, name: player.name }}"
|
||||
:class="{'font-semibold text-yellow-400': account.id === player.summonerId}"
|
||||
:to="{
|
||||
name: 'summoner',
|
||||
params: { region: $route.params.region, name: player.name },
|
||||
}"
|
||||
:class="{
|
||||
'font-semibold text-yellow-400':
|
||||
account.id === player.summonerId,
|
||||
}"
|
||||
class="overflow-hidden text-xs text-left text-white whitespace-no-wrap w-22 text-overflow hover:text-blue-200"
|
||||
>{{ player.name }}</router-link>
|
||||
<div
|
||||
v-else
|
||||
class="overflow-hidden text-xs text-left text-white whitespace-no-wrap w-22 text-overflow"
|
||||
>{{ player.name }}</div>
|
||||
<div class="text-teal-500 text-xxs">{{ player.champion.name }}</div>
|
||||
>
|
||||
{{ player.name }}
|
||||
</div>
|
||||
<div class="text-teal-500 text-xxs">
|
||||
{{ player.champion.name }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div v-if="player.rank">
|
||||
<svg class="w-5 h-5 ml-auto">
|
||||
<use :xlink:href="`#rank-${player.rank.tier.toLowerCase()}`" />
|
||||
<use
|
||||
:xlink:href="`#rank-${player.rank.tier.toLowerCase()}`"
|
||||
/>
|
||||
</svg>
|
||||
<div class="text-blue-300 text-xxs">{{ player.rank.shortName }}</div>
|
||||
<div class="text-blue-300 text-xxs">
|
||||
{{ player.rank.shortName }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="player.rank === undefined">
|
||||
<DotsLoader width="30px" dot-width="10px" />
|
||||
|
|
@ -165,61 +242,81 @@
|
|||
<div
|
||||
:style="bgColor(player, 'kills')"
|
||||
class="absolute inset-0 flex items-center justify-center p-2 text-sm text-white"
|
||||
>{{ player.stats.kills }}</div>
|
||||
>
|
||||
{{ player.stats.kills }}
|
||||
</div>
|
||||
</td>
|
||||
<td class="relative">
|
||||
<div
|
||||
:style="bgColor(player, 'deaths')"
|
||||
class="absolute inset-0 flex items-center justify-center p-2 text-sm text-white"
|
||||
>{{ player.stats.deaths }}</div>
|
||||
>
|
||||
{{ player.stats.deaths }}
|
||||
</div>
|
||||
</td>
|
||||
<td class="relative">
|
||||
<div
|
||||
:style="bgColor(player, 'assists')"
|
||||
class="absolute inset-0 flex items-center justify-center p-2 text-sm text-white"
|
||||
>{{ player.stats.assists }}</div>
|
||||
>
|
||||
{{ player.stats.assists }}
|
||||
</div>
|
||||
</td>
|
||||
<td class="relative">
|
||||
<div
|
||||
:style="bgColor(player, 'minions')"
|
||||
class="absolute inset-0 flex items-center justify-center p-2 text-sm text-white"
|
||||
>{{ player[statsFormat].minions }}</div>
|
||||
>
|
||||
{{ player[statsFormat].minions }}
|
||||
</div>
|
||||
</td>
|
||||
<td class="relative">
|
||||
<div
|
||||
:style="bgColor(player, 'vision')"
|
||||
class="absolute inset-0 flex items-center justify-center p-2 text-sm text-white"
|
||||
>{{ player[statsFormat].vision }}</div>
|
||||
>
|
||||
{{ player[statsFormat].vision }}
|
||||
</div>
|
||||
</td>
|
||||
<td class="relative">
|
||||
<div
|
||||
:style="bgColor(player, 'gold')"
|
||||
class="absolute inset-0 flex items-center justify-center p-2 text-sm text-white"
|
||||
>{{ roundStats(player[statsFormat].gold) }}</div>
|
||||
>
|
||||
{{ roundStats(player[statsFormat].gold) }}
|
||||
</div>
|
||||
</td>
|
||||
<td class="relative">
|
||||
<div
|
||||
:style="bgColor(player, 'dmgChamp')"
|
||||
class="absolute inset-0 flex items-center justify-center p-2 text-sm text-white"
|
||||
>{{ roundStats(player[statsFormat].dmgChamp) }}</div>
|
||||
>
|
||||
{{ roundStats(player[statsFormat].dmgChamp) }}
|
||||
</div>
|
||||
</td>
|
||||
<td class="relative">
|
||||
<div
|
||||
:style="bgColor(player, 'dmgObj')"
|
||||
class="absolute inset-0 flex items-center justify-center p-2 text-sm text-white"
|
||||
>{{ roundStats(player[statsFormat].dmgObj) }}</div>
|
||||
>
|
||||
{{ roundStats(player[statsFormat].dmgObj) }}
|
||||
</div>
|
||||
</td>
|
||||
<td class="relative">
|
||||
<div
|
||||
:style="bgColor(player, 'dmgTaken')"
|
||||
class="absolute inset-0 flex items-center justify-center p-2 text-sm text-white"
|
||||
>{{ roundStats(player[statsFormat].dmgTaken) }}</div>
|
||||
>
|
||||
{{ roundStats(player[statsFormat].dmgTaken) }}
|
||||
</div>
|
||||
</td>
|
||||
<td class="relative">
|
||||
<div
|
||||
:style="bgColor(player, 'kp')"
|
||||
class="absolute inset-0 flex items-center justify-center p-2 text-sm text-white"
|
||||
>{{ player.stats.kp }}</div>
|
||||
>
|
||||
{{ player.stats.kp }}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
@ -243,15 +340,15 @@ export default {
|
|||
props: {
|
||||
allPlayers: {
|
||||
type: Array,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
allyTeam: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
|
|
@ -260,28 +357,32 @@ export default {
|
|||
return this.percentSettings ? 'percentStats' : 'stats'
|
||||
},
|
||||
...mapState({
|
||||
account: state => state.summoner.basic.account,
|
||||
percentSettings: state => state.settings.percent
|
||||
account: (state) => state.summoner.basic.account,
|
||||
percentSettings: (state) => state.settings.percent,
|
||||
}),
|
||||
},
|
||||
|
||||
methods: {
|
||||
bgColor(player, stats) {
|
||||
const value = parseFloat(player.stats[stats])
|
||||
const biggestValue = Math.max(...this.allPlayers.map(p => parseFloat(p.stats[stats])), 0)
|
||||
const biggestValue = Math.max(
|
||||
...this.allPlayers.map((p) => parseFloat(p.stats[stats])),
|
||||
0
|
||||
)
|
||||
const opacity = (value / biggestValue).toFixed(2)
|
||||
const biggestValueStyle = {}
|
||||
if (value === biggestValue && value !== 0) {
|
||||
biggestValueStyle.boxShadow = 'rgba(181, 160, 122, 0.5) 0px 0px 10px'
|
||||
biggestValueStyle.border = '2px solid'
|
||||
biggestValueStyle.borderImageSlice = '1'
|
||||
biggestValueStyle.borderImageSource = 'linear-gradient(to top, #edb457, #f9e9ce)'
|
||||
biggestValueStyle.borderImageSource =
|
||||
'linear-gradient(to top, #edb457, #f9e9ce)'
|
||||
biggestValueStyle.borderCollapse = 'separate'
|
||||
}
|
||||
|
||||
return {
|
||||
backgroundColor: `rgba(${colors[stats]}, ${opacity})`,
|
||||
...biggestValueStyle
|
||||
...biggestValueStyle,
|
||||
}
|
||||
},
|
||||
displayBorderbottom(index) {
|
||||
|
|
@ -290,25 +391,34 @@ export default {
|
|||
getHeadingColor(result) {
|
||||
switch (result) {
|
||||
case 'Win':
|
||||
return { '--bg-img': 'linear-gradient(90deg, rgba(1, 97, 28, 0.3) 0%, rgba(44, 82, 130, 0) 45% )' }
|
||||
return {
|
||||
'--bg-img':
|
||||
'linear-gradient(90deg, rgba(1, 97, 28, 0.3) 0%, rgba(44, 82, 130, 0) 45% )',
|
||||
}
|
||||
case 'Fail':
|
||||
return { '--bg-img': 'linear-gradient(90deg, rgba(140, 0, 0, 0.3) 0%, rgba(44, 82, 130, 0) 45% )' }
|
||||
return {
|
||||
'--bg-img':
|
||||
'linear-gradient(90deg, rgba(140, 0, 0, 0.3) 0%, rgba(44, 82, 130, 0) 45% )',
|
||||
}
|
||||
default:
|
||||
return { '--bg-img': 'linear-gradient(90deg, rgba(233, 169, 75, 0.3) 0%, rgba(44, 82, 130, 0) 45% )' }
|
||||
return {
|
||||
'--bg-img':
|
||||
'linear-gradient(90deg, rgba(233, 169, 75, 0.3) 0%, rgba(44, 82, 130, 0) 45% )',
|
||||
}
|
||||
}
|
||||
},
|
||||
roundStats(value) {
|
||||
return this.percentSettings ? value : this.$options.filters.kilo(value)
|
||||
},
|
||||
selectRunes(player) {
|
||||
const runes = {
|
||||
primary: player.primaryRune,
|
||||
secondary: player.secondaryRune
|
||||
if (!player.perks) {
|
||||
return
|
||||
}
|
||||
this.displayOrHideRunes(runes)
|
||||
|
||||
this.displayOrHideRunes(player.perks)
|
||||
},
|
||||
...mapActions('cdragon', ['displayOrHideRunes']),
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
|||
195
client/src/components/Match/Runes/RuneStyle.vue
Normal file
195
client/src/components/Match/Runes/RuneStyle.vue
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
<template>
|
||||
<div class="flex">
|
||||
<div
|
||||
:style="{
|
||||
backgroundImage: `url('${createCategoryBorderUrl(runeStyle.name)}')`,
|
||||
}"
|
||||
class="flex items-center justify-center w-24 h-24 bg-cover"
|
||||
>
|
||||
<div
|
||||
:style="{
|
||||
backgroundImage: `url('${createCategoryUrl(runeStyle.name)}')`,
|
||||
}"
|
||||
style="filter: brightness(1.2)"
|
||||
class="w-56 h-56 mt-4 bg-center bg-no-repeat bg-contain"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<div class="mt-24 space-y-4">
|
||||
<div
|
||||
v-for="(category, index) in slots"
|
||||
:key="`secondary-category-${index}`"
|
||||
class=""
|
||||
>
|
||||
<div class="flex space-x-4">
|
||||
<ul v-for="runeId in category" :key="`slot-${runeId}`">
|
||||
<Tooltip>
|
||||
<template v-slot:trigger>
|
||||
<li
|
||||
:style="{
|
||||
backgroundImage: `url('${createCDragonAssetUrl(
|
||||
runes.perks[runeId].icon
|
||||
)}')`,
|
||||
}"
|
||||
:class="
|
||||
selectedRunes.selected.includes(runeId)
|
||||
? 'used-rune'
|
||||
: 'not-used-rune'
|
||||
"
|
||||
class="w-12 h-12 bg-center bg-cover border-2 border-gray-700 rounded-full cursor-pointer"
|
||||
></li>
|
||||
</template>
|
||||
<template v-slot:default>
|
||||
<div
|
||||
class="flex max-w-md p-2 text-sm text-left text-white select-none"
|
||||
>
|
||||
<div
|
||||
:style="{
|
||||
backgroundImage: `url('${createCDragonAssetUrl(
|
||||
runes.perks[runeId].icon
|
||||
)}')`,
|
||||
}"
|
||||
class="flex-shrink-0 w-12 h-12 ml-1 bg-center bg-cover rounded-md bg-blue-1000"
|
||||
></div>
|
||||
<div class="ml-2 leading-none">
|
||||
<div class="text-base">{{ runes.perks[runeId].name }}</div>
|
||||
<div
|
||||
v-html="runes.perks[runeId].desc"
|
||||
class="mt-3 font-light leading-tight text-blue-200 rune-description"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Tooltip>
|
||||
</ul>
|
||||
</div>
|
||||
<div
|
||||
v-if="primary && index == 0"
|
||||
class="w-full mt-4 bg-gray-500 bg-opacity-25 h-2px"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<div v-if="!primary">
|
||||
<div class="mt-8 space-y-4">
|
||||
<div
|
||||
v-for="(row, index) in kStats"
|
||||
:key="`row-${index}`"
|
||||
class="flex px-3 space-x-8"
|
||||
>
|
||||
<ul v-for="(kStat, i) in row" :key="`${kStat}-${i}`">
|
||||
<Tooltip>
|
||||
<template v-slot:trigger>
|
||||
<li
|
||||
:style="{
|
||||
backgroundImage: `url('${createCDragonAssetUrl(
|
||||
runes.perks[kStat].icon
|
||||
)}')`,
|
||||
}"
|
||||
:class="
|
||||
selectedRunes.selected[index + 6] === kStat
|
||||
? 'used-rune'
|
||||
: 'not-used-rune'
|
||||
"
|
||||
class="w-8 h-8 bg-gray-900 bg-center bg-cover border-2 border-gray-700 rounded-full cursor-pointer"
|
||||
></li>
|
||||
</template>
|
||||
<template v-slot:default>
|
||||
<div
|
||||
class="flex max-w-md p-2 text-sm text-left text-white select-none"
|
||||
>
|
||||
<div
|
||||
:style="{
|
||||
backgroundImage: `url('${createCDragonAssetUrl(
|
||||
runes.perks[kStat].icon
|
||||
)}')`,
|
||||
}"
|
||||
class="flex-shrink-0 w-8 h-8 ml-1 bg-center bg-cover rounded-md bg-blue-1000"
|
||||
></div>
|
||||
<div class="ml-2 leading-none">
|
||||
<div class="text-base">{{ runes.perks[kStat].name }}</div>
|
||||
<div
|
||||
v-html="runes.perks[kStat].desc"
|
||||
class="mt-3 font-light leading-tight text-blue-200 rune-description"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Tooltip>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
import { createCDragonAssetUrl } from '@/helpers/functions'
|
||||
import Tooltip from '@/components/Common/Tooltip.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Tooltip,
|
||||
},
|
||||
|
||||
props: {
|
||||
primary: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
runeStyle: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
slots() {
|
||||
return this.primary ? this.runeStyle.slots : this.runeStyle.slots.slice(1)
|
||||
},
|
||||
...mapState({
|
||||
kStats: state => state.cdragon.kStats,
|
||||
runes: state => state.cdragon.runes,
|
||||
runesOpen: state => state.cdragon.runesOpen,
|
||||
selectedRunes: state => state.cdragon.selectedRunes
|
||||
}),
|
||||
},
|
||||
|
||||
methods: {
|
||||
createCategoryBorderUrl(name) {
|
||||
const lower = name.toLowerCase()
|
||||
return `http://raw.communitydragon.org/pbe/plugins/rcp-fe-lol-collections/global/default/perks/images/${lower}/vfx-${lower[0]}.png`
|
||||
},
|
||||
createCategoryUrl(name) {
|
||||
const lower = name.toLowerCase()
|
||||
return `http://raw.communitydragon.org/latest/plugins/rcp-fe-lol-collections/global/default/perks/images/${lower}/icon-${lower[0]}.png`
|
||||
},
|
||||
createCDragonAssetUrl,
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.not-used-rune {
|
||||
@apply opacity-50 transition-all duration-150 ease-in-out;
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
|
||||
.not-used-rune:hover {
|
||||
@apply opacity-100;
|
||||
filter: none;
|
||||
}
|
||||
|
||||
.used-rune {
|
||||
@apply transition-all duration-75 ease-in-out;
|
||||
}
|
||||
|
||||
.used-rune:hover {
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
|
||||
.rune-description >>> hr {
|
||||
@apply border-blue-800;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,43 +1,105 @@
|
|||
<template>
|
||||
<transition leave-active-class="duration-300">
|
||||
<div
|
||||
v-if="isOpen"
|
||||
@click="close"
|
||||
class="fixed inset-0 z-40 flex items-center justify-center bg-gray-900"
|
||||
v-show="runesOpen"
|
||||
class="fixed inset-0 z-50 flex items-center justify-center"
|
||||
>
|
||||
<div class="text-3xl text-white bg-red-500">RUNES {{ runes.primary }}</div>
|
||||
<transition
|
||||
enter-active-class="transition duration-300 ease-out"
|
||||
enter-class="transform opacity-0"
|
||||
enter-to-class="transform opacity-100"
|
||||
leave-active-class="transition duration-200 ease-in"
|
||||
leave-class="transform opacity-100"
|
||||
leave-to-class="transform opacity-0"
|
||||
>
|
||||
<div
|
||||
v-if="runesOpen"
|
||||
@click="close"
|
||||
class="fixed inset-0 bg-gray-900 bg-opacity-75"
|
||||
></div>
|
||||
</transition>
|
||||
|
||||
<transition
|
||||
enter-active-class="transition duration-300 ease-out"
|
||||
enter-class="transform scale-95 opacity-0"
|
||||
enter-to-class="transform scale-100 opacity-100"
|
||||
leave-active-class="transition duration-200 ease-in"
|
||||
leave-class="transform scale-100 opacity-100"
|
||||
leave-to-class="transform scale-95 opacity-0"
|
||||
>
|
||||
<div
|
||||
v-if="runesOpen"
|
||||
class="relative overflow-hidden rounded-md shadow-lg"
|
||||
style="width: 800px; height: 500px"
|
||||
>
|
||||
<LazyBackground
|
||||
:image-source="
|
||||
require(`@/assets/img/runes/${primaryStyle.name.toLowerCase()}.jpg`)
|
||||
"
|
||||
image-class="absolute inset-0"
|
||||
more-backgrounds="linear-gradient(rgba(26, 32, 44, 0.6), rgba(26, 32, 44, 0.8)),"
|
||||
style="filter: blur(2px)"
|
||||
transition-name="fade-fast"
|
||||
>
|
||||
</LazyBackground>
|
||||
<div class="relative flex items-start h-full px-4 py-2">
|
||||
<div class="w-1/2">
|
||||
<RuneStyle :primary="true" :rune-style="primaryStyle" />
|
||||
</div>
|
||||
<div class="w-1/2">
|
||||
<RuneStyle :primary="false" :rune-style="secondaryStyle" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex'
|
||||
import { mapActions, mapState } from 'vuex'
|
||||
import { createCDragonAssetUrl } from '@/helpers/functions'
|
||||
import LazyBackground from '@/components/Common/LazyBackgroundImage.vue'
|
||||
import RuneStyle from '@/components/Match/Runes/RuneStyle.vue'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
open: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
runes: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
components: {
|
||||
LazyBackground,
|
||||
RuneStyle,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
isOpen: this.open,
|
||||
}
|
||||
computed: {
|
||||
primaryStyle() {
|
||||
return this.runes.perkstyles[this.selectedRunes.primaryStyle]
|
||||
},
|
||||
secondaryStyle() {
|
||||
return this.runes.perkstyles[this.selectedRunes.secondaryStyle]
|
||||
},
|
||||
...mapState({
|
||||
runes: state => state.cdragon.runes,
|
||||
runesOpen: state => state.cdragon.runesOpen,
|
||||
selectedRunes: state => state.cdragon.selectedRunes
|
||||
}),
|
||||
},
|
||||
|
||||
watch: {
|
||||
open () {
|
||||
this.isOpen = this.open
|
||||
}
|
||||
created() {
|
||||
document.addEventListener('keydown', this.handleEscape)
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
document.removeEventListener('keydown', this.handleEscape)
|
||||
},
|
||||
|
||||
methods: {
|
||||
close() {
|
||||
this.displayOrHideRunes({})
|
||||
},
|
||||
handleEscape(e) {
|
||||
if (e.key === 'Esc' || e.key === 'Escape') {
|
||||
this.displayOrHideRunes({})
|
||||
}
|
||||
},
|
||||
createCDragonAssetUrl,
|
||||
...mapActions('cdragon', ['displayOrHideRunes'])
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,3 +43,12 @@ export function sortTeamByRole(a, b) {
|
|||
const sortingArr = ['TOP', 'JUNGLE', 'MIDDLE', 'BOTTOM', 'SUPPORT']
|
||||
return sortingArr.indexOf(a.role) - sortingArr.indexOf(b.role)
|
||||
}
|
||||
|
||||
/**
|
||||
* Give the full CDragon image path from the iconPath field
|
||||
* @param {String} iconPath
|
||||
*/
|
||||
export function createCDragonAssetUrl(iconPath) {
|
||||
const name = iconPath.split('/assets/')[1].toLowerCase()
|
||||
return `https://raw.communitydragon.org/latest/plugins/rcp-be-lol-game-data/global/default/${name}`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,11 @@ import { axios } from '@/plugins/axios'
|
|||
export const namespaced = true
|
||||
|
||||
export const state = {
|
||||
kStats: [
|
||||
[5008, 5005, 5007],
|
||||
[5008, 5002, 5003],
|
||||
[5001, 5002, 5003],
|
||||
],
|
||||
runes: null,
|
||||
runesOpen: false,
|
||||
selectedRunes: {},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
<template>
|
||||
<div>
|
||||
<div
|
||||
v-if="overviewLoaded"
|
||||
key="overview"
|
||||
|
|
@ -48,8 +47,6 @@
|
|||
<div v-else>
|
||||
<OverviewLoader />
|
||||
</div>
|
||||
<RunesContainer :open="runesOpen" :runes="selectedRunes" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
|
|
@ -59,7 +56,6 @@ import LiveMatch from '@/components/Match/LiveMatch.vue'
|
|||
import LoadingButton from '@/components/Form/LoadingButton.vue'
|
||||
import Match from '@/components/Match/Match.vue'
|
||||
import OverviewLoader from '@/components/Summoner/Overview/OverviewLoader.vue'
|
||||
import RunesContainer from '@/components/Match/Runes/RunesContainer.vue'
|
||||
import SummonerChampions from '@/components/Summoner/Overview/SummonerChampions.vue'
|
||||
import SummonerMates from '@/components/Summoner/Overview/SummonerMates.vue'
|
||||
import SummonerStats from '@/components/Summoner/Overview/SummonerStats.vue'
|
||||
|
|
@ -71,7 +67,6 @@ export default {
|
|||
LoadingButton,
|
||||
Match,
|
||||
OverviewLoader,
|
||||
RunesContainer,
|
||||
SummonerChampions,
|
||||
SummonerMates,
|
||||
SummonerStats,
|
||||
|
|
@ -82,8 +77,6 @@ export default {
|
|||
...mapState({
|
||||
current: state => state.summoner.live.match,
|
||||
overview: state => state.summoner.overview,
|
||||
runesOpen: state => state.cdragon.runesOpen,
|
||||
selectedRunes: state => state.cdragon.selectedRunes
|
||||
}),
|
||||
...mapGetters('summoner', ['matchesLoading', 'moreMatchesToFetch', 'overviewLoaded', 'summonerFound'])
|
||||
},
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ export interface ParticipantDetails {
|
|||
secondSum: SummonerSpell | number | null,
|
||||
stats: Stats,
|
||||
percentStats?: PercentStats
|
||||
rank?: Rank | null
|
||||
rank?: Rank | null,
|
||||
perks?: Perks
|
||||
}
|
||||
|
||||
export interface Champion<T = number, U = string> {
|
||||
|
|
@ -51,6 +52,12 @@ export interface Rank {
|
|||
shortName: string | number
|
||||
}
|
||||
|
||||
export interface Perks {
|
||||
primaryStyle: number;
|
||||
secondaryStyle: number;
|
||||
selected: number[];
|
||||
}
|
||||
|
||||
export interface ParticipantBasic {
|
||||
account_id: string,
|
||||
name: string,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,15 @@
|
|||
import { getSeasonNumber, queuesWithRole, sortTeamByRole, supportItems } from 'App/helpers'
|
||||
import Jax from 'App/Services/Jax'
|
||||
import { MatchDto, ParticipantDto, ParticipantTimelineDto } from 'App/Services/Jax/src/Endpoints/MatchEndpoint'
|
||||
import { Champion, Item, ParticipantBasic, ParticipantDetails, PercentStats, Stats, SummonerSpell } from 'App/Models/Match'
|
||||
import { Champion, Item, ParticipantBasic, ParticipantDetails, PercentStats, Perks, Stats, SummonerSpell } from 'App/Models/Match'
|
||||
import RoleIdentificationService, { ChampionsPlayRate } from 'App/Services/RoleIdentiticationService'
|
||||
import { ChampionDTO, ItemDTO, PerkDTO, PerkStyleDTO, SummonerSpellDTO } from 'App/Services/Jax/src/Endpoints/CDragonEndpoint'
|
||||
import { TeamStats } from 'App/Models/DetailedMatch'
|
||||
import {
|
||||
MatchDto,
|
||||
ParticipantDto,
|
||||
ParticipantStatsDto,
|
||||
ParticipantTimelineDto,
|
||||
} from 'App/Services/Jax/src/Endpoints/MatchEndpoint'
|
||||
|
||||
export interface PlayerRole {
|
||||
champion: number,
|
||||
|
|
@ -194,9 +199,29 @@ export default abstract class MatchTransformer {
|
|||
playerData.percentStats = percentStats!
|
||||
}
|
||||
|
||||
playerData.perks = this.getFullPerks(player.stats)
|
||||
|
||||
return playerData
|
||||
}
|
||||
|
||||
public getFullPerks (stats: ParticipantStatsDto) {
|
||||
const perks: Perks = {
|
||||
primaryStyle: stats.perkPrimaryStyle,
|
||||
secondaryStyle: stats.perkSubStyle,
|
||||
selected: [],
|
||||
}
|
||||
|
||||
for (let i = 0; i < 6; i++) {
|
||||
perks.selected.push(stats[`perk${i}`])
|
||||
}
|
||||
|
||||
for (let i = 0; i < 3; i++) {
|
||||
perks.selected.push(stats[`statPerk${i}`])
|
||||
}
|
||||
|
||||
return perks
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the icons of the primary rune and secondary category
|
||||
* @param perk0 primary perks id
|
||||
|
|
|
|||
|
|
@ -2,20 +2,27 @@ import { PerkDTO, PerkStyleDTO } from 'App/Services/Jax/src/Endpoints/CDragonEnd
|
|||
|
||||
class RuneTransformer {
|
||||
public transformPerks (perks: PerkDTO[]) {
|
||||
return perks.map((perk) => ({
|
||||
id: perk.id,
|
||||
return perks.reduce((acc, perk) => {
|
||||
acc[perk.id] = {
|
||||
name: perk.name,
|
||||
desc: perk.longDesc,
|
||||
icon: perk.iconPath,
|
||||
}))
|
||||
}
|
||||
return acc
|
||||
}, {})
|
||||
}
|
||||
|
||||
public transformStyles (styles: PerkStyleDTO[]) {
|
||||
return styles.map(style => ({
|
||||
id: style.id,
|
||||
return styles.reduce((acc, style) => {
|
||||
acc[style.id] = {
|
||||
name: style.name,
|
||||
icon: style.iconPath,
|
||||
}))
|
||||
slots: style.slots
|
||||
.filter(s => s.type !== 'kStatMod')
|
||||
.map(s => s.perks),
|
||||
}
|
||||
return acc
|
||||
}, {})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue