Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/color/mix.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@ function mix(weight: number | string, color: string, otherColor: string): string
// http://sass-lang.com/documentation/Sass/Script/Functions.html#mix-instance_method
const alphaDelta = color1.alpha - color2.alpha
const x = parseFloat(weight) * 2 - 1
const y = x * alphaDelta === -1 ? x : x + alphaDelta
const z = 1 + x * alphaDelta
const weight1 = (y / z + 1) / 2.0
// When `x * alphaDelta === -1`, `z` is `0`, so fall back to `x` rather than
// dividing by it (matches the reference Sass implementation and avoids NaN).
const y = x * alphaDelta === -1 ? x : (x + alphaDelta) / z
const weight1 = (y + 1) / 2.0
const weight2 = 1 - weight1

const mixedColor = {
Expand Down
7 changes: 7 additions & 0 deletions src/color/test/mix.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,11 @@ describe('mix', () => {
it('should return the second color when weight is 0', () => {
expect(mix(0, 'rgba(0, 0, 0, 1)', 'rgba(255, 255, 255, 0)')).toEqual('rgba(255, 255, 255, 0)')
})

it('should not produce NaN channels when the alpha delta cancels the weight', () => {
// weight 1 makes `x === 1`, and the opposing alphas make `alphaDelta === -1`,
// so `1 + x * alphaDelta === 0`. The previous implementation divided by that
// zero and returned `rgba(NaN,NaN,NaN,0)`. weight 1 should yield color1.
expect(mix(1, 'rgba(255, 0, 0, 0)', 'rgba(0, 0, 255, 1)')).toEqual('rgba(255,0,0,0)')
})
})