added circular progress bar
This commit is contained in:
parent
464cf60153
commit
ea80c8b95d
|
|
@ -0,0 +1,183 @@
|
||||||
|
:root {
|
||||||
|
--cpb-color: #53077A;
|
||||||
|
--cpb-bg-color: #F2E9E1;
|
||||||
|
--cpb-outer: 4em;
|
||||||
|
--cpb-thickness: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-circle {
|
||||||
|
font-size: 20px;
|
||||||
|
margin: 0;
|
||||||
|
position: relative; /* so that children can be absolutely positioned */
|
||||||
|
padding: 0;
|
||||||
|
width: var(--cpb-outer);
|
||||||
|
height: var(--cpb-outer);
|
||||||
|
background-color: var(--cpb-bg-color);
|
||||||
|
border-radius: 50%;
|
||||||
|
line-height: var(--cpb-outer);
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-circle:after{
|
||||||
|
border: none;
|
||||||
|
position: absolute;
|
||||||
|
top: var(--cpb-thickness);
|
||||||
|
left: var(--cpb-thickness);
|
||||||
|
text-align: center;
|
||||||
|
display: block;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: calc(var(--cpb-outer) - var(--cpb-thickness) * 2);
|
||||||
|
height: calc(var(--cpb-outer) - var(--cpb-thickness) * 2);
|
||||||
|
background-color: white;
|
||||||
|
content: " ";
|
||||||
|
}
|
||||||
|
/* Text inside the control */
|
||||||
|
.progress-circle span {
|
||||||
|
position: absolute;
|
||||||
|
line-height: var(--cpb-outer);
|
||||||
|
width: var(--cpb-outer);
|
||||||
|
text-align: center;
|
||||||
|
display: block;
|
||||||
|
color: var(--cpb-color);
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
.left-half-clipper {
|
||||||
|
/* a round circle */
|
||||||
|
border-radius: 50%;
|
||||||
|
width: var(--cpb-outer);
|
||||||
|
height: var(--cpb-outer);
|
||||||
|
position: absolute; /* needed for clipping */
|
||||||
|
clip: rect(0, var(--cpb-outer), var(--cpb-outer), calc(var(--cpb-outer) / 2)); /* clips the whole left half*/
|
||||||
|
}
|
||||||
|
/* when p>50, don't clip left half*/
|
||||||
|
.progress-circle.over50 .left-half-clipper {
|
||||||
|
clip: rect(auto,auto,auto,auto);
|
||||||
|
}
|
||||||
|
.value-bar {
|
||||||
|
/*This is an overlayed square, that is made round with the border radius,
|
||||||
|
then it is cut to display only the left half, then rotated clockwise
|
||||||
|
to escape the outer clipping path.*/
|
||||||
|
position: absolute; /*needed for clipping*/
|
||||||
|
clip: rect(0, calc(var(--cpb-outer) / 2), var(--cpb-outer), 0);
|
||||||
|
width: var(--cpb-outer);
|
||||||
|
height: var(--cpb-outer);
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 0.45em solid var(--cpb-color); /*The border is 0.35 but making it larger removes visual artifacts */
|
||||||
|
/*background-color: #4D642D;*/ /* for debug */
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
}
|
||||||
|
/* Progress bar filling the whole right half for values above 50% */
|
||||||
|
.progress-circle.over50 .first50-bar {
|
||||||
|
/*Progress bar for the first 50%, filling the whole right half*/
|
||||||
|
position: absolute; /*needed for clipping*/
|
||||||
|
clip: rect(0, var(--cpb-outer), var(--cpb-outer), calc(var(--cpb-outer) / 2));
|
||||||
|
background-color: var(--cpb-color);
|
||||||
|
border-radius: 50%;
|
||||||
|
width: var(--cpb-outer);
|
||||||
|
height: var(--cpb-outer);
|
||||||
|
}
|
||||||
|
.progress-circle:not(.over50) .first50-bar{ display: none; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Progress bar rotation position */
|
||||||
|
.progress-circle.p0 .value-bar { display: none; }
|
||||||
|
.progress-circle.p1 .value-bar { transform: rotate(4deg); }
|
||||||
|
.progress-circle.p2 .value-bar { transform: rotate(7deg); }
|
||||||
|
.progress-circle.p3 .value-bar { transform: rotate(11deg); }
|
||||||
|
.progress-circle.p4 .value-bar { transform: rotate(14deg); }
|
||||||
|
.progress-circle.p5 .value-bar { transform: rotate(18deg); }
|
||||||
|
.progress-circle.p6 .value-bar { transform: rotate(22deg); }
|
||||||
|
.progress-circle.p7 .value-bar { transform: rotate(25deg); }
|
||||||
|
.progress-circle.p8 .value-bar { transform: rotate(29deg); }
|
||||||
|
.progress-circle.p9 .value-bar { transform: rotate(32deg); }
|
||||||
|
.progress-circle.p10 .value-bar { transform: rotate(36deg); }
|
||||||
|
.progress-circle.p11 .value-bar { transform: rotate(40deg); }
|
||||||
|
.progress-circle.p12 .value-bar { transform: rotate(43deg); }
|
||||||
|
.progress-circle.p13 .value-bar { transform: rotate(47deg); }
|
||||||
|
.progress-circle.p14 .value-bar { transform: rotate(50deg); }
|
||||||
|
.progress-circle.p15 .value-bar { transform: rotate(54deg); }
|
||||||
|
.progress-circle.p16 .value-bar { transform: rotate(58deg); }
|
||||||
|
.progress-circle.p17 .value-bar { transform: rotate(61deg); }
|
||||||
|
.progress-circle.p18 .value-bar { transform: rotate(65deg); }
|
||||||
|
.progress-circle.p19 .value-bar { transform: rotate(68deg); }
|
||||||
|
.progress-circle.p20 .value-bar { transform: rotate(72deg); }
|
||||||
|
.progress-circle.p21 .value-bar { transform: rotate(76deg); }
|
||||||
|
.progress-circle.p22 .value-bar { transform: rotate(79deg); }
|
||||||
|
.progress-circle.p23 .value-bar { transform: rotate(83deg); }
|
||||||
|
.progress-circle.p24 .value-bar { transform: rotate(86deg); }
|
||||||
|
.progress-circle.p25 .value-bar { transform: rotate(90deg); }
|
||||||
|
.progress-circle.p26 .value-bar { transform: rotate(94deg); }
|
||||||
|
.progress-circle.p27 .value-bar { transform: rotate(97deg); }
|
||||||
|
.progress-circle.p28 .value-bar { transform: rotate(101deg); }
|
||||||
|
.progress-circle.p29 .value-bar { transform: rotate(104deg); }
|
||||||
|
.progress-circle.p30 .value-bar { transform: rotate(108deg); }
|
||||||
|
.progress-circle.p31 .value-bar { transform: rotate(112deg); }
|
||||||
|
.progress-circle.p32 .value-bar { transform: rotate(115deg); }
|
||||||
|
.progress-circle.p33 .value-bar { transform: rotate(119deg); }
|
||||||
|
.progress-circle.p34 .value-bar { transform: rotate(122deg); }
|
||||||
|
.progress-circle.p35 .value-bar { transform: rotate(126deg); }
|
||||||
|
.progress-circle.p36 .value-bar { transform: rotate(130deg); }
|
||||||
|
.progress-circle.p37 .value-bar { transform: rotate(133deg); }
|
||||||
|
.progress-circle.p38 .value-bar { transform: rotate(137deg); }
|
||||||
|
.progress-circle.p39 .value-bar { transform: rotate(140deg); }
|
||||||
|
.progress-circle.p40 .value-bar { transform: rotate(144deg); }
|
||||||
|
.progress-circle.p41 .value-bar { transform: rotate(148deg); }
|
||||||
|
.progress-circle.p42 .value-bar { transform: rotate(151deg); }
|
||||||
|
.progress-circle.p43 .value-bar { transform: rotate(155deg); }
|
||||||
|
.progress-circle.p44 .value-bar { transform: rotate(158deg); }
|
||||||
|
.progress-circle.p45 .value-bar { transform: rotate(162deg); }
|
||||||
|
.progress-circle.p46 .value-bar { transform: rotate(166deg); }
|
||||||
|
.progress-circle.p47 .value-bar { transform: rotate(169deg); }
|
||||||
|
.progress-circle.p48 .value-bar { transform: rotate(173deg); }
|
||||||
|
.progress-circle.p49 .value-bar { transform: rotate(176deg); }
|
||||||
|
.progress-circle.p50 .value-bar { transform: rotate(180deg); }
|
||||||
|
.progress-circle.p51 .value-bar { transform: rotate(184deg); }
|
||||||
|
.progress-circle.p52 .value-bar { transform: rotate(187deg); }
|
||||||
|
.progress-circle.p53 .value-bar { transform: rotate(191deg); }
|
||||||
|
.progress-circle.p54 .value-bar { transform: rotate(194deg); }
|
||||||
|
.progress-circle.p55 .value-bar { transform: rotate(198deg); }
|
||||||
|
.progress-circle.p56 .value-bar { transform: rotate(202deg); }
|
||||||
|
.progress-circle.p57 .value-bar { transform: rotate(205deg); }
|
||||||
|
.progress-circle.p58 .value-bar { transform: rotate(209deg); }
|
||||||
|
.progress-circle.p59 .value-bar { transform: rotate(212deg); }
|
||||||
|
.progress-circle.p60 .value-bar { transform: rotate(216deg); }
|
||||||
|
.progress-circle.p61 .value-bar { transform: rotate(220deg); }
|
||||||
|
.progress-circle.p62 .value-bar { transform: rotate(223deg); }
|
||||||
|
.progress-circle.p63 .value-bar { transform: rotate(227deg); }
|
||||||
|
.progress-circle.p64 .value-bar { transform: rotate(230deg); }
|
||||||
|
.progress-circle.p65 .value-bar { transform: rotate(234deg); }
|
||||||
|
.progress-circle.p66 .value-bar { transform: rotate(238deg); }
|
||||||
|
.progress-circle.p67 .value-bar { transform: rotate(241deg); }
|
||||||
|
.progress-circle.p68 .value-bar { transform: rotate(245deg); }
|
||||||
|
.progress-circle.p69 .value-bar { transform: rotate(248deg); }
|
||||||
|
.progress-circle.p70 .value-bar { transform: rotate(252deg); }
|
||||||
|
.progress-circle.p71 .value-bar { transform: rotate(256deg); }
|
||||||
|
.progress-circle.p72 .value-bar { transform: rotate(259deg); }
|
||||||
|
.progress-circle.p73 .value-bar { transform: rotate(263deg); }
|
||||||
|
.progress-circle.p74 .value-bar { transform: rotate(266deg); }
|
||||||
|
.progress-circle.p75 .value-bar { transform: rotate(270deg); }
|
||||||
|
.progress-circle.p76 .value-bar { transform: rotate(274deg); }
|
||||||
|
.progress-circle.p77 .value-bar { transform: rotate(277deg); }
|
||||||
|
.progress-circle.p78 .value-bar { transform: rotate(281deg); }
|
||||||
|
.progress-circle.p79 .value-bar { transform: rotate(284deg); }
|
||||||
|
.progress-circle.p80 .value-bar { transform: rotate(288deg); }
|
||||||
|
.progress-circle.p81 .value-bar { transform: rotate(292deg); }
|
||||||
|
.progress-circle.p82 .value-bar { transform: rotate(295deg); }
|
||||||
|
.progress-circle.p83 .value-bar { transform: rotate(299deg); }
|
||||||
|
.progress-circle.p84 .value-bar { transform: rotate(302deg); }
|
||||||
|
.progress-circle.p85 .value-bar { transform: rotate(306deg); }
|
||||||
|
.progress-circle.p86 .value-bar { transform: rotate(310deg); }
|
||||||
|
.progress-circle.p87 .value-bar { transform: rotate(313deg); }
|
||||||
|
.progress-circle.p88 .value-bar { transform: rotate(317deg); }
|
||||||
|
.progress-circle.p89 .value-bar { transform: rotate(320deg); }
|
||||||
|
.progress-circle.p90 .value-bar { transform: rotate(324deg); }
|
||||||
|
.progress-circle.p91 .value-bar { transform: rotate(328deg); }
|
||||||
|
.progress-circle.p92 .value-bar { transform: rotate(331deg); }
|
||||||
|
.progress-circle.p93 .value-bar { transform: rotate(335deg); }
|
||||||
|
.progress-circle.p94 .value-bar { transform: rotate(338deg); }
|
||||||
|
.progress-circle.p95 .value-bar { transform: rotate(342deg); }
|
||||||
|
.progress-circle.p96 .value-bar { transform: rotate(346deg); }
|
||||||
|
.progress-circle.p97 .value-bar { transform: rotate(349deg); }
|
||||||
|
.progress-circle.p98 .value-bar { transform: rotate(353deg); }
|
||||||
|
.progress-circle.p99 .value-bar { transform: rotate(356deg); }
|
||||||
|
.progress-circle.p100 .value-bar { transform: rotate(360deg); }
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from "vue";
|
import {computed, onMounted} from "vue";
|
||||||
|
import {
|
||||||
|
IonButton
|
||||||
|
} from '@ionic/vue';
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { useStore } from "vuex";
|
import { useStore } from "vuex";
|
||||||
|
|
||||||
|
|
@ -8,6 +11,12 @@ const router = useRouter();
|
||||||
|
|
||||||
const user = computed(() => store.state.auth.user);
|
const user = computed(() => store.state.auth.user);
|
||||||
|
|
||||||
|
const emit = defineEmits(['updateTitle']);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
emit('updateTitle', 'Bullpens');
|
||||||
|
});
|
||||||
|
|
||||||
const managePlayers = () => {
|
const managePlayers = () => {
|
||||||
router.push({ path: "/players" });
|
router.push({ path: "/players" });
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,7 @@ import {
|
||||||
IonItem,
|
IonItem,
|
||||||
IonLabel,
|
IonLabel,
|
||||||
IonList,
|
IonList,
|
||||||
IonNote,
|
IonNote
|
||||||
IonProgressBar
|
|
||||||
} from '@ionic/vue';
|
} from '@ionic/vue';
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { useStore } from "vuex";
|
import { useStore } from "vuex";
|
||||||
|
|
@ -20,6 +19,7 @@ import Bullpen from '@/types/Bullpen';
|
||||||
import BullpenSessionService from "@/services/BullpenSessionService";
|
import BullpenSessionService from "@/services/BullpenSessionService";
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import PitchType from '@/types/PitchType';
|
import PitchType from '@/types/PitchType';
|
||||||
|
import "../assets/css/circular-progress-bar.css";
|
||||||
|
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
@ -63,6 +63,10 @@ const determinePitchTypeName = (id: number): string => {
|
||||||
return pitchType?.name ?? 'Unknown';
|
return pitchType?.name ?? 'Unknown';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const percentageClass = (value: number) => {
|
||||||
|
return "p" + value;
|
||||||
|
};
|
||||||
|
|
||||||
const ionInfinite = (event: InfiniteScrollCustomEvent) => {
|
const ionInfinite = (event: InfiniteScrollCustomEvent) => {
|
||||||
generateItems();
|
generateItems();
|
||||||
setTimeout(() => event.target.complete(), 500);
|
setTimeout(() => event.target.complete(), 500);
|
||||||
|
|
@ -73,33 +77,45 @@ generateItems();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ion-list inset="false">
|
<ion-list :inset="false">
|
||||||
<ion-item v-for="(bullpen, index) in items" :key="index" class="custom-item" :button="true" detail="false">
|
<ion-item v-for="(bullpen, index) in items" :key="index" class="custom-item" :button="true" :detail="false">
|
||||||
<!-- Top-left icon -->
|
<!-- Top-left icon -->
|
||||||
<ion-icon :icon="baseballOutline" slot="start" class="item-icon"></ion-icon>
|
<ion-icon :icon="baseballOutline" slot="start" class="item-icon"></ion-icon>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<strong>{{formatDate(bullpen.startedAt)}}</strong>
|
<strong>{{formatDate(bullpen.startedAt)}}</strong>
|
||||||
<ion-label class="item-labels">
|
<ion-label class="item-labels">
|
||||||
<div class="progress-section">
|
<!-- Horizontale Anordnung der Kreise -->
|
||||||
<div class="top-row">
|
<div class="circle-container">
|
||||||
<span class="left-label">Strike</span>
|
<div class="circle-wrapper">
|
||||||
<span class="right-label">{{ (0.57 * 100).toFixed(0) }}%</span>
|
<div class="progress-circle" :class="percentageClass(57)">
|
||||||
|
<span>{{ (0.57 * 100).toFixed(0) }}%</span>
|
||||||
|
<div class="left-half-clipper">
|
||||||
|
<div class="first50-bar"></div>
|
||||||
|
<div class="value-bar"></div>
|
||||||
</div>
|
</div>
|
||||||
<ion-progress-bar :value="0.57" color="success"></ion-progress-bar>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="progress-section">
|
<label>Precision</label>
|
||||||
<div class="top-row">
|
|
||||||
<span class="left-label">Balls</span>
|
|
||||||
<span class="right-label">{{ (0.33 * 100).toFixed(0) }}%</span>
|
|
||||||
</div>
|
</div>
|
||||||
<ion-progress-bar :value="0.33" color="warning"></ion-progress-bar>
|
<div class="circle-wrapper">
|
||||||
|
<div class="progress-circle" :class="percentageClass(77)">
|
||||||
|
<span>{{ (0.77 * 100).toFixed(0) }}%</span>
|
||||||
|
<div class="left-half-clipper">
|
||||||
|
<div class="first50-bar"></div>
|
||||||
|
<div class="value-bar"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="progress-section">
|
|
||||||
<div class="top-row">
|
|
||||||
<span class="left-label">Precision</span>
|
|
||||||
<span class="right-label">{{ (0.77 * 100).toFixed(0) }}%</span>
|
|
||||||
</div>
|
</div>
|
||||||
<ion-progress-bar :value="0.77" color="danger"></ion-progress-bar>
|
<label>Strike</label>
|
||||||
|
</div>
|
||||||
|
<div class="circle-wrapper">
|
||||||
|
<div class="progress-circle" :class="percentageClass(33)">
|
||||||
|
<span>{{ (0.33 * 100).toFixed(0) }}%</span>
|
||||||
|
<div class="left-half-clipper">
|
||||||
|
<div class="first50-bar"></div>
|
||||||
|
<div class="value-bar"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<label>Balls</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
@ -108,19 +124,6 @@ generateItems();
|
||||||
<ion-icon color="medium" :icon="chevronForward"></ion-icon>
|
<ion-icon color="medium" :icon="chevronForward"></ion-icon>
|
||||||
</div>
|
</div>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<!-- <ion-item v-for="(bullpen, index) in items" :key="index">-->
|
|
||||||
<!-- <ion-icon aria-hidden="true" :icon="baseball" slot="start"></ion-icon>-->
|
|
||||||
<!-- <ion-label>Bullpen from ({{formatDate(bullpen.startedAt)}})</ion-label>-->
|
|
||||||
<!-- <ion-list v-for="(pitch, index) in bullpen.pitches" :key="index">-->
|
|
||||||
<!-- <ion-item>-->
|
|
||||||
<!-- <ion-icon slot="start" :icon="baseballOutline" class="icon-login"></ion-icon>-->
|
|
||||||
<!-- <ion-label>{{determinePitchTypeName(pitch.pitchTypeId)}}</ion-label>-->
|
|
||||||
<!-- <ion-badge>{{pitch.aimedArea}}</ion-badge>-->
|
|
||||||
<!-- <ion-badge>{{pitch.hitArea}}</ion-badge>-->
|
|
||||||
<!-- </ion-item>-->
|
|
||||||
<!-- </ion-list>-->
|
|
||||||
<!-- </ion-item>-->
|
|
||||||
</ion-list>
|
</ion-list>
|
||||||
<ion-infinite-scroll @ionInfinite="ionInfinite">
|
<ion-infinite-scroll @ionInfinite="ionInfinite">
|
||||||
<ion-infinite-scroll-content></ion-infinite-scroll-content>
|
<ion-infinite-scroll-content></ion-infinite-scroll-content>
|
||||||
|
|
@ -166,27 +169,33 @@ ion-label strong{
|
||||||
|
|
||||||
.item-labels {
|
.item-labels {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-section {
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-row {
|
/* Circle progress bar */
|
||||||
padding: 2px 0 0 0;
|
.circle-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 6px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.left-label {
|
.circle-wrapper {
|
||||||
font-weight: normal;
|
flex: 1;
|
||||||
font-size: 16px;
|
text-align: center;
|
||||||
|
margin: 10px 10px 10px 0;
|
||||||
|
display: flex; /* Flexbox für vertikale Ausrichtung */
|
||||||
|
flex-direction: column; /* Elemente übereinander anordnen */
|
||||||
|
justify-content: center; /* Vertikale Zentrierung */
|
||||||
|
align-items: center; /* Horizontale Zentrierung */
|
||||||
}
|
}
|
||||||
|
|
||||||
.right-label {
|
.circle-wrapper label {
|
||||||
font-weight: normal;
|
display: block;
|
||||||
font-size: 14px;
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--ion-color-medium);
|
||||||
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue