File "BaseRating.vue"
Full Path: /home/pulsehostuk9/public_html/invoicer.pulsehost.co.uk/resources/scripts/components/icons/dashboard/BaseRating.vue
File size: 5.28 KB
MIME-type: text/html
Charset: utf-8
<template>
<div class="star-rating">
<div
v-for="(star, index) in stars"
:key="index"
:title="rating"
class="star-container"
>
<svg
:style="[
{ fill: `url(#gradient${star.raw})` },
{ width: style.starWidth },
{ height: style.starHeight },
]"
class="star-svg"
>
<polygon :points="getStarPoints" style="fill-rule: nonzero" />
<defs>
<!--
id has to be unique to each star fullness(dynamic offset) - it indicates fullness above
-->
<linearGradient :id="`gradient${star.raw}`">
<stop
id="stop1"
:offset="star.percent"
:stop-color="getFullFillColor(star)"
stop-opacity="1"
></stop>
<stop
id="stop2"
:offset="star.percent"
:stop-color="getFullFillColor(star)"
stop-opacity="0"
></stop>
<stop
id="stop3"
:offset="star.percent"
:stop-color="style.emptyStarColor"
stop-opacity="1"
></stop>
<stop
id="stop4"
:stop-color="style.emptyStarColor"
offset="100%"
stop-opacity="1"
></stop>
</linearGradient>
</defs>
</svg>
</div>
<div v-if="isIndicatorActive" class="indicator">{{ rating }}</div>
</div>
</template>
<script>
export default {
name: 'StarsRating',
components: {},
directives: {},
props: {
config: {
type: Object,
default: null,
},
rating: {
type: [Number],
default: 0,
},
},
data: function () {
return {
stars: [],
emptyStar: 0,
fullStar: 1,
totalStars: 5,
isIndicatorActive: false,
style: {
fullStarColor: '#F1C644',
emptyStarColor: '#D4D4D4',
starWidth: 20,
starHeight: 20,
},
}
},
computed: {
getStarPoints: function () {
let centerX = this.style.starWidth / 2
let centerY = this.style.starHeight / 2
let innerCircleArms = 5 // a 5 arms star
let innerRadius = this.style.starWidth / innerCircleArms
let innerOuterRadiusRatio = 2.5 // Unique value - determines fatness/sharpness of star
let outerRadius = innerRadius * innerOuterRadiusRatio
return this.calcStarPoints(
centerX,
centerY,
innerCircleArms,
innerRadius,
outerRadius
)
},
},
created() {
this.initStars()
this.setStars()
this.setConfigData()
},
methods: {
calcStarPoints(
centerX,
centerY,
innerCircleArms,
innerRadius,
outerRadius
) {
let angle = Math.PI / innerCircleArms
let angleOffsetToCenterStar = 60
let totalArms = innerCircleArms * 2
let points = ''
for (let i = 0; i < totalArms; i++) {
let isEvenIndex = i % 2 == 0
let r = isEvenIndex ? outerRadius : innerRadius
let currX = centerX + Math.cos(i * angle + angleOffsetToCenterStar) * r
let currY = centerY + Math.sin(i * angle + angleOffsetToCenterStar) * r
points += currX + ',' + currY + ' '
}
return points
},
initStars() {
for (let i = 0; i < this.totalStars; i++) {
this.stars.push({
raw: this.emptyStar,
percent: this.emptyStar + '%',
})
}
},
setStars() {
let fullStarsCounter = Math.floor(this.rating)
for (let i = 0; i < this.stars.length; i++) {
if (fullStarsCounter !== 0) {
this.stars[i].raw = this.fullStar
this.stars[i].percent = this.calcStarFullness(this.stars[i])
fullStarsCounter--
} else {
let surplus = Math.round((this.rating % 1) * 10) / 10 // Support just one decimal
let roundedOneDecimalPoint = Math.round(surplus * 10) / 10
this.stars[i].raw = roundedOneDecimalPoint
return (this.stars[i].percent = this.calcStarFullness(this.stars[i]))
}
}
},
setConfigData() {
if (this.config) {
this.setBindedProp(this.style, this.config.style, 'fullStarColor')
this.setBindedProp(this.style, this.config.style, 'emptyStarColor')
this.setBindedProp(this.style, this.config.style, 'starWidth')
this.setBindedProp(this.style, this.config.style, 'starHeight')
if (this.config.isIndicatorActive) {
this.isIndicatorActive = this.config.isIndicatorActive
}
console.log('isIndicatorActive: ', this.isIndicatorActive)
}
},
getFullFillColor(starData) {
return starData.raw !== this.emptyStar
? this.style.fullStarColor
: this.style.emptyStarColor
},
calcStarFullness(starData) {
let starFullnessPercent = starData.raw * 100 + '%'
return starFullnessPercent
},
setBindedProp(localProp, propParent, propToBind) {
if (propParent[propToBind]) {
localProp[propToBind] = propParent[propToBind]
}
},
},
}
</script>
<style scoped lang="scss">
.star-rating {
display: flex;
align-items: center;
.star-container {
display: flex;
.star-svg {
}
}
.indicator {
}
.star-container:not(:last-child) {
margin-right: 5px;
}
}
</style>