Skip to content

Instantly share code, notes, and snippets.

@chunpu
Last active April 21, 2021 08:13
Show Gist options
  • Save chunpu/4ab60b752f2d81d20d548808231087bd to your computer and use it in GitHub Desktop.
Save chunpu/4ab60b752f2d81d20d548808231087bd to your computer and use it in GitHub Desktop.
blend color with alpha 层叠混合带透明度的颜色, 支持任意层叠数
<canvas width="800" height="600" style="border: 1px solid red"></canvas>
<script>
var canvas = document.querySelector('canvas')
var ctx = canvas.getContext("2d")
var color1 = [255, 152, 0, 0.5]
var color2 = [76, 175, 80, 0.5]
var color3 = [33, 150, 243, 0.5]
var blended = blend(color1, color2, color3)
console.log({ blended })
ctx.fillStyle = `rgba(${color1.join(',')})`;
drawRectByPath(20, 20, 75, 50)
ctx.fillStyle = `rgba(${color2.join(',')})`;
drawRectByPath(30, 30, 75, 50);
ctx.fillStyle = `rgba(${color3.join(',')})`;
drawRectByPath(40, 40, 75, 50);
ctx.fillStyle = `rgba(${blended.join(',')})`;
drawRectByPath(200, 40, 75, 50);
function drawRectByPath(x, y, w, h) {
ctx.beginPath()
ctx.moveTo(x, y)
ctx.lineTo(x + w, y)
ctx.lineTo(x + w, y + h)
ctx.lineTo(x, y + h)
ctx.closePath()
ctx.fill()
}
function blend() {
// 参数顺序是按照自下而上, 顺序敏感
var arr = [].slice.call(arguments)
arr = arr.map(function(item) {
item = item.slice()
if (item[3] == null) {
item[3] = 1
}
return item
})
var base = arr.shift()
if (arr.length === 0) {
return base
}
var added = arr.shift()
var mix = []
mix[3] = 1 - (1 - added[3]) * (1 - base[3]) // alpha
mix[0] = Math.round((added[0] * added[3] / mix[3]) + (base[0] * base[3] * (1 - added[3]) / mix[3])) // red
mix[1] = Math.round((added[1] * added[3] / mix[3]) + (base[1] * base[3] * (1 - added[3]) / mix[3])) // green
mix[2] = Math.round((added[2] * added[3] / mix[3]) + (base[2] * base[3] * (1 - added[3]) / mix[3])) // blue
if (arr.length === 0) {
return mix
}
return blend.apply(null, [mix].concat(arr))
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment