jquery 如何根据百分比将背景颜色从黄色更改为红色?

mi7gmzs6  于 2023-10-17  发布在  jQuery
关注(0)|答案(5)|浏览(123)

我正在开发一个投票网站,其中投票选项的进展会根据投票的百分比改变颜色。目前,颜色的变化使用一个if语句来检查进度百分比。有没有更好的方法来做到这一点,而不依赖于这么多的if语句?像是某种梯度?我可以使用vanilla和jQuery解决方案。

function progressColor(progress) {
    if (progress >= 0 && progress <= 24) return '#FFE169';
    else if (progress >= 25 && progress <= 49) return '#FFDE59';
    else if (progress >= 50 && progress <= 74) return '#FF914D';
    else if (progress >= 75 && progress <= 89) return '#FF7A7A';
    else if (progress >= 90 && progress <= 100) return '#FF5757';
}
mqxuamgl

mqxuamgl1#

这是一个近似的参数化你的色标。
您也可以使用滑块更改背景颜色。

function progressColorPara(progress) {
  const progressP = progress / 100;
  const hue = 48 * (1 - progressP);
  const lightness = 71 - 11 * progressP;
  return `hsl(${hue},100%,${lightness}%)`;
}

for(let i = 0; i < 100; i+=10) {
  const div = document.createElement("div");
  div.style.backgroundColor = progressColorPara(i);
  div.innerText = i;
  document.body.appendChild(div);
}

document.getElementById("p").addEventListener(
  "input",
  e => document.body.style.backgroundColor = progressColorPara(e.target.valueAsNumber),
);
div {
  padding: 0.5em;
}
input {
width: 100%
}
<input type="range" min=0 max=100 step=0.1 id=p />
jyztefdp

jyztefdp2#

同样的功能,使用数学。底色:0xFFE 169最终颜色0xFF 5757和它们之间.0xFFE169 - 0xFF 5757 = 8a 12,因此:每个百分比都是十六进制的~ 162 =(DEC)354

function progressColor(progress) {
    if(progress == 0) return 'FFE169';
      else {
          return (Number("0x"+"FFE169") - (354 * progress)).toString(16);
             }
}
zyfwsgd6

zyfwsgd63#

对计算机来说,颜色只是一串数字。这意味着,从理论上讲,你可以做一些数学计算,得到一个数字,这是一个特定的百分点之间的差异,一个较低的数字和较高的数字。有了你的规模,我不认为它是那么简单,但我们将保持这个想法的本质,并得到一些帮助与库,做所有复杂的数学:chroma.js
chrome.js有一个名为scale的函数,它可以获取出现在刻度上的颜色数组。使用你问题中的颜色,你可以建立一个像这样的规模:

const scale = chroma.scale(["#FFE169", "#FFDE59", "#FF914D", "#FF7A7A", "#FF5757"]);

scale返回一个函数,你可以用一个百分比来调用它,以获得刻度上该百分比的颜色。

scale(0); // #FFE169
scale(0.25); // #FFDE59
scale(0.5); // #FF914D
scale(0.75); // #FF7A7A
scale(1); // #FF5757

下面是一个演示,从你的问题中的颜色构建一个规模,并使用输入来改变百分比,并获得规模上的特定颜色。

const initialValue = 0;
const number = document.getElementById("number");
const range = document.getElementById("range");
const output = document.getElementById("output");
const scale = chroma.scale(["#FFE169", "#FFDE59", "#FF914D", "#FF7A7A", "#FF5757"]);

number.value = initialValue;
range.value = initialValue;

const initialColor = scale(initialValue * 0.01).toString();
output.style.backgroundColor = initialColor;
output.textContent = initialColor;

function updateColor(percentage) {
  const color = scale(event.target.value * 0.01).toString();
  output.style.backgroundColor = color;
  output.textContent = color;
}

number.addEventListener("change", ({ target: { value } }) => {
  range.value = value;
  updateColor(value);
});

range.addEventListener("input", ({ target: { value } }) => {
  number.value = value;
  updateColor(value)
});
body {
  font-family: monospace;
}

#range {
  width: 100%;
}

#output {
  align-content: center;
  display: flex;
  flex-direction: column;
  font-size: 24px;
  font-weight: bold;
  height: 50vh;
  justify-content: center;
  text-align: center;
  width: 100vw;
}
<input id="number" type="number" min="0" max="100" />
<input id="range" type="range" min="0" max="100" />
<output id="output"></output>
<script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/chroma-js/2.4.2/chroma.min.js"></script>
rkue9o1l

rkue9o1l4#

你可以使用一种不太常见的switch语法

progress    = 85;

color       = 'gray';
switch(true){
  case (progress>=90) : color   = 'blue';     break;
  case (progress>=80) : color   = 'yellow';   break;
}
test.style.background    = color;
div {
   height  : 100px;
}
<div id=test></div>

你不需要else if,因为条件是相互排斥的,只需要separate if语句就可以了。
我很喜欢if语法,它很健壮,可以准确地显示你在做什么

kmb7vmvb

kmb7vmvb5#

就我个人而言,我很感激我偏离了你指定的配色方案,我会按如下方式处理(解释性注解在下面的代码中):

// using document.querySelector() to retrieve the first element on the page that
// matches the supplied CSS selector (this returns null if no element is found,
// in production please use sanity-checks to guard against errors of that kind:
let input = document.querySelector('input'),
    // this is the name of the event we're using to set/updated the CSS custom
    // properties:
        evtName = 'input';

// here we use EventTarget.addEventListener() to bind the anonymous function of
// the method as the event-handler for the named - 'input' - event:
input.addEventListener(evtName, (evt)=>{

  // from the Event Object - passed in automatically - we retrieve the
  // element to which the event-listener was bound (the <input>):
    let changed = evt.currentTarget;
  
  // from the <input> we navigate up through the parent elements to find the
  // first <main> element, and use CSSStyleDeclaration.setProperty() to
  // set the custom property (indicated by the '--' notation) that's equal
  // to the <input> element's 'name' attribute, setting that property to
  // the value of the <input> element:
    changed.closest('main').style.setProperty(`--${changed.name}`, `${changed.value}%`);
  
  // from the <input> we find the first ancestor <label>, and from there
  // we use Element.querySelector() to find the <output> element contained
  // within; we then set its textContent property - using a template-literal String
  // (as above) - to be equal to the value of the <input>, followed by the '%' sign:
  changed.closest('label').querySelector('output').textContent = `${changed.value}%`;
});

// here we use EventTarget.dispatchEvent() to trigger the named event ('input')
// on the <input> element, causing the event-listener to run, and initialise
// the state according to the starting value(s):
input.dispatchEvent(new Event(evtName));
:root {
  --main-inline-size: 80%;
  --main-max-inline-size: 1200px;
  --main-min-inline-size: 20rem;
  --spacing: 0.5rem;
}

*,
::before,
::after {
  box-sizing: border-box;
  font: inherit;
  margin: 0;
  padding: 0;
}

body {
  block-size: 100vh;
  font-family: system-ui;
  font-size: 16px;
  font-weight: 400;
  padding: var(--spacing);
}

main {
  /* here we set the background-color of the <main> element, using the color-mix() function;
     first we set (and this is required) the color-space in which the colors should be mixed,
     here I use the 'oklab' color-space; we then mix the end-color using the var() function
     at a percentage equivalent to the "progress"; that way zero progress results in zero
     of the end-color, and 100% progress results in 100% percent of the end-color.
     These CSS custom properties are set via JavaScript, but handled by CSS: */
  background-color: color-mix(in oklab, var(--end) var(--progress), var(--start));
  border: 1px solid currentColor;
  inline-size: clamp(var(--main-min-inline-size), var(--main-inline-size), var(--main-max-inline-size));
  margin-inline: auto;
  min-block-size: 100%;
  padding: var(--spacing);
}

form {
  /* backdrop-filter is used to differentiate the background of the <form> and to have
     the various form-elements stand out, by rotating the hue of the ancestor's background
     by 15degrees, and increasing the brightness by 75% (if we set the brightness filter
     to 100% then we'd have the same brightness as the ancestor's background): */
  backdrop-filter: hue-rotate(15deg) brightness(175%);
  border: 1px solid currentColor;
  border-radius: 0.5rem;
  inline-size: fit-content;
  margin-block: 0.5rem;
  margin-inline: auto;
  padding: 1rem;
}

label {
  display: flex;
  gap: 1rem;
  padding: 0.5rem;
}

output {
  inline-size: 5rem;
}
<!--
  using the "style" attribute to define the initial CSS custom properties, one of which
  - --progress - will be updated later with JavaScript:
-->
<main style="--start: #FFE169; --end: #FF5757; --progress: 0%;">
  <form action="#" method="post">
    <legend>Simulate progress:</legend>
    <label>
      <span class="labelText">Progress</span>
      <input type="range" name="progress" min="0" max="100" step="0.1" value="0" id="progress">
      <output for="progress"></output>
    </label>
  </form>
</main>

JS Fiddle demo
参考文献:

相关问题