javascript - 根据百分比值在两种颜色之间进行插值

标签 javascript reactjs animation colors

我目前正在用 JS 开发动画库,需要根据 0 - 1 之间的进度值计算两个值之间的颜色。

例如,该函数可能如下所示。这将以 HEX 格式输入两种颜色。

  • colourA = 初始颜色
  • colourB = 最终颜色
  • 进度 = 0.5 (50%)

const interpolateColour = (colourA, colourB, progress) => { return polColour } 

目标是返回颜色 0.5 progress 或两种颜色之间的 50%。我知道 HEX 颜色很可能需要转换为 RGBA 以实现 HSV 以实现此效果,但不确定哪种方法是最佳方法。

编辑: 我想通了...


const is = {
    hex: a => /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(a),
    rgb: a => /^rgb/.test(a),
    hsl: a => /^hsl/.test(a),
    col: a => (is.hex(a) || is.rgb(a) || is.hsl(a)),
}

const convertToRgba = (colour) => {
    return is.hex(colour) ? hexToRgba(colour)
        : is.rgb(colour) ? rbgToRgba(colour)
            : is.hsl(colour) ? hslToRgba(colour)
                : colour
}

const hexToRgba = (colour, alpha = 1) => {
    const [r, g, b] = colour.match(/\w\w/g).map(x => parseInt(x, 16))
    return `rgba(${r},${g},${b},${alpha})`
};

const rbgToRgba = (colour, alpha = 1) => {
    const [r, g, b] = colour.replace(/[^\d,]/g, '').split(',')
    return `rgba(${r},${g},${b},${alpha})`
}

const deconstructRgba = (rgba) => {
    return rgba.replace(/[^\d,]/g, '').split(',').map(x => parseInt(x))
}

const formatRbga = (colour) => {
    return `rgba(${colour.r},${colour.g},${colour.b},${colour.a})`
}

const interpolateColour = (colourA, colourB, progress) => {
    const [r1, g1, b1, a1] = deconstructRgba(convertToRgba(colourA))
    const [r2, g2, b2, a2] = deconstructRgba(convertToRgba(colourB))
    return formatRbga({
        r: Math.round((r1 + r2) * progress),
        g: Math.round((g1 + g2) * progress),
        b: Math.round((b1 + b2) * progress),
        a: Math.round((a1 + a2) * progress)
    })
}

export {
    interpolateColour,
    convertToRgba,
    hexToRgba,
    rbgToRgba,
    deconstructRgba
}

最佳答案

R、G 和 B 值的简单插值应该足够了。

// extract numeric r, g, b values from `rgb(nn, nn, nn)` string
function getRgb(color) {
  let [r, g, b] = color.replace('rgb(', '')
    .replace(')', '')
    .split(',')
    .map(str => Number(str));;
  return {
    r,
    g,
    b
  }
}

function colorInterpolate(colorA, colorB, intval) {
  const rgbA = getRgb(colorA),
    rgbB = getRgb(colorB);
  const colorVal = (prop) =>
    Math.round(rgbA[prop] * (1 - intval) + rgbB[prop] * intval);
  return {
    r: colorVal('r'),
    g: colorVal('g'),
    b: colorVal('b'),
  }
}


function doit(progression) {
  const div1 = document.getElementById('color1');
  const color1 = div1.style.backgroundColor;
  const div2 = document.getElementById('color2');
  const color2 = div2.style.backgroundColor;

  const rgbNew = colorInterpolate(
    color1,
    color2, progression
  );

  const divResult = document.getElementById('result');
  divResult.style.backgroundColor =
    `rgb( ${rgbNew.r}, ${rgbNew.g}, ${rgbNew.b})`;
}

document.querySelector('button').onclick = () => {
  const intval = Number(document.querySelector('input').value);
  doit(intval);
};
#color1,
#color2,
#result {
  width: 200px;
  height: 40px;
  margin: 12px;
  padding: 0.2rem 0.5rem;
}
<h4>Interpolate Between Two Colors</h4>
<label for="number">Interpolate by:</label>
<input id="number" type="number" value="0.5" min="0" max="1" step="0.05" />
<button>Interpolate</button>

<div style="display: flex">
  <div id="color1" style="background-color: #922B21">color1</div>
  <div id="result" style="background-color: #e0e0e0">interpolated</div>
  <div id="color2" style="background-color: #85C1E9">color2</div>
</div>

关于javascript - 根据百分比值在两种颜色之间进行插值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66123016/

相关文章:

javascript - 日期范围选择器输入字段不是 24 小时格式

javascript - 如何在 Javascript 中增加方括号内的数字

javascript - 如何防止 bootstrap 下拉菜单在悬停时打开

javascript - 单击动态生成的图像时触发事件

javascript - 如何在 React Router v4 中向子进程发送 props?

javascript - 内表中的最后一行在固定数据表中不展开

node.js - Heroku 上的生产构建中显示开发构建错误

简写的 CSS3 动画播放状态在 IE 和 Safari 中不起作用

animation - move 到行为不起作用 : Game Salad

ios - 如何沿圆形路径为 UIView 设置动画?