Я создал погодное приложение, которое меняет цвет фона в зависимости от температуры и описания погоды.
Это код, который я должен заставить работать.
const body = document.querySelector('body');
const colorList = [
{weather: 'Clear', color1: '#7AE7C7', color2: '#72C1E1'},
{weather: 'Clouds', color1: '#F981BB', color2: '#7F7E84'},
{weather: 'Drizzle', color1: '#b2c9c8', color2: '#698b8b'},
{weather: 'Fog', color1: '#C5B2A6', color2: '#7F7E84'},
{weather: 'Rain', color1: '#504AC4', color2: '#59AED1'},
{weather: 'Snow', color1: '#bfc9cf', color2: '#77BDE0'},
{weather: 'Thunderstorm', color1: '#314F71', color2: '#4A4176'},
{weather: 'Tornado', color1: '#939393', color2: '#e47977c5'}
]
const colorList2 = [
{color1: '#C94926', color2: '#BB9F34'},
{color1: '#89a1dd', color2: '#E4E5E7' }
]
if(weather.list[0].main.temp < 5 && weather.list[0].weather[0].main == 'Clear') {
body.style.backgroundImage = `linear-gradient(to bottom right,
${colorList2[1].color1}, ${colorList2[1].color2})`;
} else if(weather.list[0].main.temp > 15 && weather.list[0].weather[0].main == 'Clear'){
body.style.backgroundImage = `linear-gradient(to bottom right,
${colorList2[0].color1}, ${colorList2[0].color2})`;
} else {
colorList.forEach(color => {
if(color.weather == weather.list[0].weather[0].main) {
body.style.backgroundImage = `linear-gradient(to bottom right,
${color.color1}, ${color.color2})`;
}
Есть ли более эффективный способ сделать то же самое? Являются ли циклы forEach излишними? Следует ли использовать операторы if else? Должен ли я вообще делать это на JavaScript?
Спасибо заранее.
2 ответа
Во-первых, ваш список цветов погоды уникален weather
key, и вы запрашиваете цвет на его основе. Я бы посоветовал превратить это в объект, цвета которого зависят от погодных условий. Таким образом легче найти цвета по условию, чем с помощью цикла. Вы также получаете одно дополнительное преимущество: вы можете добавить свои особые случаи Clear в один и тот же объект, только с уникальным значением ключа.
Затем вы захотите присвоить эти свойства переменным. Считывание длинных доступов к свойствам затруднено.
Теперь вы захотите разделить свою логику. В вашем коде вы смешиваете логику выбора цвета с логикой настройки фона в условном. Всегда важно выяснить, что на самом деле является условным, из того, что из этого можно извлечь. В этом случае только color1
и color2
являются условными, а не настройкой фона.
Вот как бы я это сделал.
const colorsByCondition = {
Clear: {
color1: '#7AE7C7',
color2: '#72C1E1'
},
// Special forms of Clear
Clear5: {
color1: '#89a1dd',
color2: '#E4E5E7'
},
Clear15: {
color1: '#C94926',
color2: '#BB9F34'
},
// Other conditions
Clouds: {
color1: '#F981BB',
color2: '#7F7E84'
},
// and so on...
}
// Assign to variables
// const weather = weather.list[0]
// const temp = weather.main.temp
// const conditions = weather.weather[0].main
// Assuming these values represent our weather
const temp = 6
const conditions="Clear"
// Find the right colors
const { color1, color2 } = temp < 5 && conditions == 'Clear'
? colorsByCondition.Clear5
: temp > 15 && conditions == 'Clear'
? colorsByCondition.Clear15
: colorsByCondition[conditions]
// Apply to the body
document.body.style.backgroundImage = `linear-gradient(to bottom right, ${color1}, ${color2})`
Использовать CSS для стиля
Вы пытаетесь добавить стили с помощью JavaScript. Это заставляет ваш JavaScript смешивать логику и стили вместе. Я бы предложил разделить стили на CSS.
Например, ваш Javascript:
{weather: 'Clear', color1: '#7AE7C7', color2: '#72C1E1'},
/* ... */
{color1: '#C94926', color2: '#BB9F34'},
/* ... */
body.style.backgroundImage = `linear-gradient(to bottom right, ${color.color1}, ${color.color2})`;
Вы можете преобразовать его в CSS, например
.weather-clear { --color-start: #7AE7C7; --color-end: #72C1E1; }
/* ... */
.weather-clear.weather-cold { --color-start: #C94926; --color-end: #BB9F34; }
/* ... */
body { background-image: linear-gradient(to bottom right, var(--color-start), var(--color-end)); }
И вам нужно только установить className в теле, чтобы применить указанный цвет.
const body = document.body;
body.classList.add('weather-' + weather.list[0].weather[0].main.toLowerCase());
if (weather.list[0].main.temp < 5) body.classList.add('weather-cold');
if (weather.list[0].main.temp > 15) body.classList.add('weather-hot');
Сложите все вместе:
const body = document.body;
const temp = 18, main = 'Clear';
body.classList.add('weather-' + main.toLowerCase());
if (temp < 5) body.classList.add('weather-cold');
if (temp > 15) body.classList.add('weather-hot');
.weather-clear { --color-start: #7AE7C7; --color-end: #72C1E1; }
.weather-clouds { --color-start: #F981BB; --color-end: #7F7E84; }
.weather-drizzle { --color-start: #b2c9c8; --color-end: #698b8b; }
.weather-fog { --color-start: #C5B2A6; --color-end: #7F7E84; }
.weather-rain { --color-start: #504AC4; --color-end: #59AED1; }
.weather-snow { --color-start: #bfc9cf; --color-end: #77BDE0; }
.weather-thunderstorm { --color-start: #314F71; --color-end: #4A4176; }
.weather-tornado { --color-start: #939393; --color-end: #e47977c5; }
.weather-clear.weather-cold { --color-start: #C94926; --color-end: #BB9F34; }
.weather-clear.weather-hot { --color-start: #89a1dd; --color-end: #E4E5E7; }
body { background-image: linear-gradient(to bottom right, var(--color-start), var(--color-end)); }
body { height: 100vh; box-sizing: border-box; margin: 0; }
[Note] Если вы нацелены на поддержку старых браузеров (без поддержки CSS var): удалите переменные CSS, используйте linear-gradient
прямо в .weather-clear
и так.
Спасибо, ваша помощь очень ценится! Да, мне показалось, что иметь дополнительный список под названием «colorList2» было немного беспорядочно. Ваш путь кажется намного лучше и чище.
— МБГ