LFFE-10 bring radial chart and complete search part of province and year
This commit is contained in:
@@ -472,7 +472,16 @@
|
|||||||
},
|
},
|
||||||
"reports": {
|
"reports": {
|
||||||
"loan_progress": "درصد پیشرفت تسویه وام",
|
"loan_progress": "درصد پیشرفت تسویه وام",
|
||||||
"loan_distribution": "درصد توضیع وام ها در هر مرحله",
|
"loan_distribution": "درصد توزیع وام ها در هر مرحله",
|
||||||
"filter_as": "فیلتر های اعمال شده"
|
"filter_as": "فیلتر های اعمال شده",
|
||||||
|
"loan_details": "اطلاعات وام ها"
|
||||||
|
},
|
||||||
|
"filters": {
|
||||||
|
"provinces": "استان های",
|
||||||
|
"province": "استان",
|
||||||
|
"year": "سال",
|
||||||
|
"years": "سال های",
|
||||||
|
"text_field_loading_provinces_list": "درحال دریافت استان ها",
|
||||||
|
"text_field_error_fetching_provinces": "خطا در دریافت استان ها"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import {Box, Chip, FormControl, InputLabel, MenuItem, OutlinedInput, Select} from "@mui/material";
|
import {Box, FormControl, InputLabel, MenuItem, OutlinedInput, Select, Typography} from "@mui/material";
|
||||||
|
import {useTranslations} from "next-intl";
|
||||||
|
import useProvince from "@/lib/app/hooks/useProvince";
|
||||||
|
|
||||||
const provinceList = [
|
const provinceList = [
|
||||||
{name: "قزوین", id: 1},
|
{name: "قزوین", id: 1},
|
||||||
@@ -6,11 +8,29 @@ const provinceList = [
|
|||||||
{name: "مشهد", id: 3}
|
{name: "مشهد", id: 3}
|
||||||
]
|
]
|
||||||
|
|
||||||
const ProvinceFilter = ({formik, multiple}) => {
|
const ProvinceFilter = ({formik, multiple, setFilteredText}) => {
|
||||||
|
const {errorProvinceList, isLoadingProvinceList, provinceList} = useProvince();
|
||||||
|
const t = useTranslations();
|
||||||
const provinceChange = (event) => {
|
const provinceChange = (event) => {
|
||||||
const {target: {value}} = event;
|
const {target: {value}} = event;
|
||||||
formik.handleChange(event);
|
formik.handleChange(event);
|
||||||
formik.setFieldValue('province_id', value);
|
formik.setFieldValue('province_id', value);
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
const province_names = []
|
||||||
|
value.map((item) => {
|
||||||
|
province_names.push(provinceList.find(province => province.id === item).name)
|
||||||
|
})
|
||||||
|
setFilteredText(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
province: province_names.length !== 0 ? `| ${t("filters.provinces")}: ${province_names.join(' , ')}` : ""
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
const selectedProvince = provinceList.find(province => province.id === value);
|
||||||
|
setFilteredText(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
province: `| ${t("filters.province")}: ${selectedProvince.name}`
|
||||||
|
}));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<FormControl sx={{width: 300, mx: 1}}>
|
<FormControl sx={{width: 300, mx: 1}}>
|
||||||
@@ -24,29 +44,38 @@ const ProvinceFilter = ({formik, multiple}) => {
|
|||||||
onChange={provinceChange}
|
onChange={provinceChange}
|
||||||
onBlur={formik.handleBlur("province_id")}
|
onBlur={formik.handleBlur("province_id")}
|
||||||
input={<OutlinedInput label="انتخاب استان"/>}
|
input={<OutlinedInput label="انتخاب استان"/>}
|
||||||
|
disabled={isLoadingProvinceList || errorProvinceList}
|
||||||
renderValue={multiple ? (selected) => (
|
renderValue={multiple ? (selected) => (
|
||||||
<Box sx={{display: 'flex', flexWrap: 'wrap', gap: 0.5}}>
|
<Box sx={{
|
||||||
|
display: 'flex', gap: 0.7, overflow: "hidden",
|
||||||
|
width: '100%',
|
||||||
|
}}>
|
||||||
{selected.map((value) => {
|
{selected.map((value) => {
|
||||||
const selectedProvince = provinceList.find(province => province.id === value);
|
const selectedProvince = provinceList.find(province => province.id === value);
|
||||||
return (
|
return (
|
||||||
<Chip
|
<Typography key={value} variant="button">
|
||||||
key={value}
|
{selectedProvince ? selectedProvince.name : ''}
|
||||||
label={selectedProvince ? selectedProvince.name : ''}
|
</Typography>
|
||||||
sx={{color: "#fff", backgroundColor: "primary.dark"}}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</Box>
|
</Box>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
>
|
>
|
||||||
{provinceList.map((province) => (
|
{isLoadingProvinceList ? (
|
||||||
<MenuItem
|
<MenuItem>
|
||||||
key={province.id}
|
{t("filters.text_field_loading_provinces_list")}
|
||||||
value={province.id}
|
|
||||||
>
|
|
||||||
{province.name}
|
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
) : errorProvinceList ? (
|
||||||
|
<MenuItem>
|
||||||
|
{t("filters.text_field_error_fetching_provinces")}
|
||||||
|
</MenuItem>
|
||||||
|
) : (
|
||||||
|
provinceList.map((item) => (
|
||||||
|
<MenuItem key={item.id} value={item.id}>
|
||||||
|
{item.name}
|
||||||
|
</MenuItem>
|
||||||
|
))
|
||||||
|
)}
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,14 +1,27 @@
|
|||||||
import {Box, Chip, FormControl, InputLabel, MenuItem, OutlinedInput, Select} from "@mui/material";
|
import {Box, Chip, FormControl, InputLabel, MenuItem, OutlinedInput, Select} from "@mui/material";
|
||||||
import moment from "jalali-moment";
|
import moment from "jalali-moment";
|
||||||
|
import {useTranslations} from "next-intl";
|
||||||
|
|
||||||
const currentShamsiYear = moment().format('jYYYY');
|
const currentShamsiYear = moment().format('jYYYY');
|
||||||
const shamsiYearList = Array.from({length: currentShamsiYear - 1399}, (_, index) => (currentShamsiYear - index).toString());
|
const shamsiYearList = Array.from({length: currentShamsiYear - 1399}, (_, index) => (currentShamsiYear - index).toString());
|
||||||
|
|
||||||
const YearFilter = ({formik, multiple}) => {
|
const YearFilter = ({formik, multiple, setFilteredText}) => {
|
||||||
|
const t = useTranslations();
|
||||||
const yearChange = (event) => {
|
const yearChange = (event) => {
|
||||||
const {target: {value}} = event;
|
const {target: {value}} = event;
|
||||||
formik.handleChange(event);
|
formik.handleChange(event);
|
||||||
formik.setFieldValue('date', value);
|
formik.setFieldValue('date', value);
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
setFilteredText(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
year: `| ${t("filters.years")}: ${value.join(' , ')}`
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
setFilteredText(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
year: `| ${t("filters.year")}: ${value}`
|
||||||
|
}));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<FormControl sx={{width: 300, mx: 1}}>
|
<FormControl sx={{width: 300, mx: 1}}>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import FilterAltIcon from '@mui/icons-material/FilterAlt';
|
|||||||
import {useTranslations} from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
import TroubleshootIcon from '@mui/icons-material/Troubleshoot';
|
import TroubleshootIcon from '@mui/icons-material/Troubleshoot';
|
||||||
import moment from "jalali-moment";
|
import moment from "jalali-moment";
|
||||||
|
import {useState} from "react";
|
||||||
|
|
||||||
const periodOfYear = (year) => {
|
const periodOfYear = (year) => {
|
||||||
const isLeapYear = moment.jIsLeapYear(year);
|
const isLeapYear = moment.jIsLeapYear(year);
|
||||||
@@ -19,10 +20,11 @@ const periodOfYear = (year) => {
|
|||||||
|
|
||||||
const Filter = ({title, filterItem, expanded}) => {
|
const Filter = ({title, filterItem, expanded}) => {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
|
|
||||||
const filter_by_province = filterItem.find((item) => item.type === "province");
|
const filter_by_province = filterItem.find((item) => item.type === "province");
|
||||||
const filter_by_year = filterItem.find((item) => item.type === "year");
|
const filter_by_year = filterItem.find((item) => item.type === "year");
|
||||||
|
|
||||||
|
const [filteredText, setFilteredText] = useState({province: "", year: ""});
|
||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
...(filter_by_year && {
|
...(filter_by_year && {
|
||||||
@@ -32,11 +34,6 @@ const Filter = ({title, filterItem, expanded}) => {
|
|||||||
province_id: filter_by_province.multiple ? [] : ""
|
province_id: filter_by_province.multiple ? [] : ""
|
||||||
})
|
})
|
||||||
}, onSubmit: (values, {setSubmitting}) => {
|
}, onSubmit: (values, {setSubmitting}) => {
|
||||||
const dates = values.date
|
|
||||||
dates.map((date) => {
|
|
||||||
periodOfYear(date);
|
|
||||||
})
|
|
||||||
console.log("val", values);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
@@ -51,7 +48,7 @@ const Filter = ({title, filterItem, expanded}) => {
|
|||||||
<Box sx={{display: "flex", alignItems: "center", gap: 0.5}}>
|
<Box sx={{display: "flex", alignItems: "center", gap: 0.5}}>
|
||||||
<Typography sx={{fontWeight: 500, color: "primary.main"}}>{title}</Typography>
|
<Typography sx={{fontWeight: 500, color: "primary.main"}}>{title}</Typography>
|
||||||
<Typography variant="caption" sx={{fontWeight: 500}} color="error">
|
<Typography variant="caption" sx={{fontWeight: 500}} color="error">
|
||||||
| {t("reports.filter_as")} :
|
{filteredText.province} {filteredText.year}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<FilterAltIcon sx={{color: "primary.main"}}/>
|
<FilterAltIcon sx={{color: "primary.main"}}/>
|
||||||
@@ -60,10 +57,12 @@ const Filter = ({title, filterItem, expanded}) => {
|
|||||||
<AccordionDetails sx={{display: "flex", justifyContent: "space-between", alignItems: "center"}}>
|
<AccordionDetails sx={{display: "flex", justifyContent: "space-between", alignItems: "center"}}>
|
||||||
<Stack sx={{flexDirection: {xs: "column", sm: "row"}, alignItems: "center", flexWrap: 'wrap'}}>
|
<Stack sx={{flexDirection: {xs: "column", sm: "row"}, alignItems: "center", flexWrap: 'wrap'}}>
|
||||||
{filter_by_province ?
|
{filter_by_province ?
|
||||||
<ProvinceFilter formik={formik} multiple={filter_by_province.multiple}/> : ""
|
<ProvinceFilter formik={formik} multiple={filter_by_province.multiple}
|
||||||
|
setFilteredText={setFilteredText}/> : ""
|
||||||
}
|
}
|
||||||
{filter_by_year ?
|
{filter_by_year ?
|
||||||
<YearFilter formik={formik} multiple={filter_by_year.multiple}/> : ""
|
<YearFilter formik={formik} multiple={filter_by_year.multiple}
|
||||||
|
setFilteredText={setFilteredText}/> : ""
|
||||||
}
|
}
|
||||||
</Stack>
|
</Stack>
|
||||||
<Stack>
|
<Stack>
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import Chart from "@/core/components/Chart";
|
||||||
|
import {calculateGradientColor} from "@/core/utils/gradientColorHandler";
|
||||||
|
|
||||||
|
const RadialBarChart = ({data}) => {
|
||||||
|
const specialOption = {
|
||||||
|
title: {
|
||||||
|
text: undefined,
|
||||||
|
},
|
||||||
|
plotOptions: {
|
||||||
|
radialBar: {
|
||||||
|
startAngle: -90,
|
||||||
|
endAngle: 90,
|
||||||
|
track: {
|
||||||
|
background: "#e7e7e7",
|
||||||
|
strokeWidth: '90%',
|
||||||
|
margin: 5, // margin is in pixels
|
||||||
|
dropShadow: {
|
||||||
|
enabled: true,
|
||||||
|
top: 2,
|
||||||
|
left: 0,
|
||||||
|
color: '#999',
|
||||||
|
opacity: 1,
|
||||||
|
blur: 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dataLabels: {
|
||||||
|
name: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
offsetY: -2,
|
||||||
|
fontSize: '22px'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fill: {
|
||||||
|
colors: calculateGradientColor(data)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const series = [data]
|
||||||
|
return (
|
||||||
|
<Chart chartId="LoanProgressBar" type="radialBar" specialOption={specialOption} series={series}/>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RadialBarChart;
|
||||||
31
src/components/dashboard/reports/LoanDetails/index.jsx
Normal file
31
src/components/dashboard/reports/LoanDetails/index.jsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import {Grid, Paper} from "@mui/material";
|
||||||
|
import {useTranslations} from "next-intl";
|
||||||
|
import Filter from "@/components/dashboard/reports/Filter";
|
||||||
|
import RadialBarChart from "@/components/dashboard/reports/LoanDetails/RadialBarChart";
|
||||||
|
|
||||||
|
const LoanDetails = () => {
|
||||||
|
const t = useTranslations();
|
||||||
|
return (
|
||||||
|
<Paper elevation={2} sx={{width: "95%", mx: "auto", my: 2, pb: 2, background: "#f7f7f7e6"}}>
|
||||||
|
<Filter title={t("reports.loan_details")}
|
||||||
|
filterItem={[
|
||||||
|
{type: "province", type_fa: "استان", multiple: false},
|
||||||
|
{type: "year", type_fa: "سال", multiple: false}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<Grid container spacing={2} sx={{justifyContent: "space-between"}}>
|
||||||
|
<Grid item xs={4} sx={{height: "300px"}}>
|
||||||
|
<RadialBarChart data={90}/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4} sx={{height: "300px"}}>
|
||||||
|
<RadialBarChart data={50}/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4} sx={{height: "300px"}}>
|
||||||
|
<RadialBarChart data={10}/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Paper>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LoanDetails;
|
||||||
@@ -7,19 +7,15 @@ const Pie = ({data}) => {
|
|||||||
},
|
},
|
||||||
plotOptions: {
|
plotOptions: {
|
||||||
pie: {
|
pie: {
|
||||||
rings: {
|
|
||||||
strokeWidth: 3,
|
|
||||||
strokeColor: '#fff',
|
|
||||||
},
|
|
||||||
fill: {
|
fill: {
|
||||||
colors: ['red', 'blue', 'green', 'yellow', 'pink']
|
colors: ['#F99417', '#363062', '#005B41', '#C70039', '#EE9322']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
fill: {
|
fill: {
|
||||||
opacity: 0.9,
|
opacity: 0.9,
|
||||||
},
|
},
|
||||||
labels: ['Team A', 'Team B', 'Team C', 'Team D', 'Team E'],
|
labels: [' آیتم 1', ' آیتم 2', ' آیتم 3', ' آیتم 4', ' آیتم 5'],
|
||||||
dataLabels: {
|
dataLabels: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
style: {
|
style: {
|
||||||
|
|||||||
@@ -12,14 +12,14 @@ const PolarChart = ({data}) => {
|
|||||||
strokeColor: '#e3e3e3',
|
strokeColor: '#e3e3e3',
|
||||||
},
|
},
|
||||||
fill: {
|
fill: {
|
||||||
colors: ['red', 'blue', 'green', 'yellow', 'pink']
|
colors: ['#F99417', '#363062', '#005B41', '#C70039', '#EE9322']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
fill: {
|
fill: {
|
||||||
opacity: 0.9,
|
opacity: 0.9,
|
||||||
},
|
},
|
||||||
labels: ['Team A', 'Team B', 'Team C', 'Team D', 'Team E'],
|
labels: [' آیتم 1', ' آیتم 2', ' آیتم 3', ' آیتم 4', ' آیتم 5'],
|
||||||
dataLabels: {
|
dataLabels: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
style: {
|
style: {
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ const LoanDistribution = () => {
|
|||||||
<Filter title={t("reports.loan_distribution")}
|
<Filter title={t("reports.loan_distribution")}
|
||||||
filterItem={[
|
filterItem={[
|
||||||
{type: "province", type_fa: "استان", multiple: false},
|
{type: "province", type_fa: "استان", multiple: false},
|
||||||
{type: "year", type_fa: "سال", multiple: true}
|
{type: "year", type_fa: "سال", multiple: false}
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<Grid container spacing={2} sx={{justifyContent: "space-between"}}>
|
<Grid container spacing={2} sx={{justifyContent: "space-between"}}>
|
||||||
|
|||||||
@@ -1,36 +1,5 @@
|
|||||||
import Chart from "@/core/components/Chart";
|
import Chart from "@/core/components/Chart";
|
||||||
|
import {calculateGradientColor} from "@/core/utils/gradientColorHandler";
|
||||||
function calculateGradientColor(percentage) {
|
|
||||||
let colorStops = [
|
|
||||||
{percent: 0, color: [199, 18, 5]}, // 0%: #3D0C11
|
|
||||||
{percent: 33, color: [240, 59, 47]}, // 33%: #D80032
|
|
||||||
{percent: 34, color: [237, 204, 101]}, // 34%: #F2F7A1
|
|
||||||
{percent: 66, color: [240, 184, 7]}, // 66%: #E9B824
|
|
||||||
{percent: 67, color: [167, 211, 151]}, // 67%: #B0D9B1
|
|
||||||
{percent: 100, color: [0, 91, 65]} // 100%: #005B41
|
|
||||||
];
|
|
||||||
|
|
||||||
let segment;
|
|
||||||
for (let i = 0; i < colorStops.length - 1; i++) {
|
|
||||||
if (percentage >= colorStops[i].percent && percentage <= colorStops[i + 1].percent) {
|
|
||||||
segment = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let color1 = colorStops[segment].color;
|
|
||||||
let color2 = colorStops[segment + 1].color;
|
|
||||||
let ratio = (percentage - colorStops[segment].percent) / (colorStops[segment + 1].percent - colorStops[segment].percent);
|
|
||||||
|
|
||||||
let color = [
|
|
||||||
Math.round(color1[0] + ratio * (color2[0] - color1[0])),
|
|
||||||
Math.round(color1[1] + ratio * (color2[1] - color1[1])),
|
|
||||||
Math.round(color1[2] + ratio * (color2[2] - color1[2]))
|
|
||||||
];
|
|
||||||
|
|
||||||
return `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const BarChart = ({data}) => {
|
const BarChart = ({data}) => {
|
||||||
const usableArray = data.map(({name, data, ...rest}) => ({
|
const usableArray = data.map(({name, data, ...rest}) => ({
|
||||||
@@ -83,7 +52,7 @@ const BarChart = ({data}) => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
const series = [{
|
const series = [{
|
||||||
name: 'اطلاعی ندارم',
|
name: 'درصد پیشرفت',
|
||||||
data: usableArray
|
data: usableArray
|
||||||
}]
|
}]
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ const LoanProgress = () => {
|
|||||||
<Paper elevation={2} sx={{width: "95%", mx: "auto", my: 2, pb: 2, background: "#f7f7f7e6"}}>
|
<Paper elevation={2} sx={{width: "95%", mx: "auto", my: 2, pb: 2, background: "#f7f7f7e6"}}>
|
||||||
<Filter title={t("reports.loan_progress")}
|
<Filter title={t("reports.loan_progress")}
|
||||||
filterItem={[
|
filterItem={[
|
||||||
{type: "province", type_fa: "استان", multiple: false},
|
{type: "province", type_fa: "استان", multiple: true},
|
||||||
{type: "year", type_fa: "سال", multiple: true}
|
{type: "year", type_fa: "سال", multiple: false}
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import LoanProgress from "@/components/dashboard/reports/LoanProgress";
|
import LoanProgress from "@/components/dashboard/reports/LoanProgress";
|
||||||
import LoanDistribution from "@/components/dashboard/reports/LoanDistribution";
|
import LoanDistribution from "@/components/dashboard/reports/LoanDistribution";
|
||||||
|
import LoanDetails from "@/components/dashboard/reports/LoanDetails";
|
||||||
|
|
||||||
const DashboardReportsComponent = (props) => {
|
const DashboardReportsComponent = (props) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<LoanProgress/>
|
<LoanProgress/>
|
||||||
<LoanDistribution/>
|
<LoanDistribution/>
|
||||||
|
<LoanDetails/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|||||||
31
src/core/utils/gradientColorHandler.js
Normal file
31
src/core/utils/gradientColorHandler.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
export const calculateGradientColor = (percentage) => {
|
||||||
|
let colorStops = [
|
||||||
|
{percent: 0, color: [199, 18, 5]}, // 0%: #3D0C11
|
||||||
|
{percent: 33, color: [240, 59, 47]}, // 33%: #D80032
|
||||||
|
{percent: 34, color: [237, 204, 101]}, // 34%: #F2F7A1
|
||||||
|
{percent: 66, color: [240, 184, 7]}, // 66%: #E9B824
|
||||||
|
{percent: 67, color: [167, 211, 151]}, // 67%: #B0D9B1
|
||||||
|
{percent: 100, color: [0, 91, 65]} // 100%: #005B41
|
||||||
|
];
|
||||||
|
|
||||||
|
let segment;
|
||||||
|
for (let i = 0; i < colorStops.length - 1; i++) {
|
||||||
|
if (percentage >= colorStops[i].percent && percentage <= colorStops[i + 1].percent) {
|
||||||
|
segment = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let color1 = colorStops[segment].color;
|
||||||
|
let color2 = colorStops[segment + 1].color;
|
||||||
|
let ratio = (percentage - colorStops[segment].percent) / (colorStops[segment + 1].percent - colorStops[segment].percent);
|
||||||
|
|
||||||
|
let color = [
|
||||||
|
Math.round(color1[0] + ratio * (color2[0] - color1[0])),
|
||||||
|
Math.round(color1[1] + ratio * (color2[1] - color1[1])),
|
||||||
|
Math.round(color1[2] + ratio * (color2[2] - color1[2]))
|
||||||
|
];
|
||||||
|
|
||||||
|
return `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user