A quick and very simple snippet I just wrote to blend two hex colours together based on a desired percentage. I wrote this to set the colour of a password strength meter – could also be used for a progress bar or any similar application.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
blendHexColor( startColor, endColor, percentage) { var rFrom = parseInt( startColor.replace( '#', '' ).substr( 0, 2 ), 16 ), gFrom = parseInt( startColor.replace( '#', '' ).substr( 2, 2 ), 16 ), bFrom = parseInt( startColor.replace( '#', '' ).substr( 4, 2 ), 16 ), rTo = parseInt( endColor.substr( 0, 2 ), 16 ), gTo = parseInt( endColor.substr( 2, 2 ), 16 ), bTo = parseInt( endColor.substr( 4, 2 ), 16 ), rFactor = ( rTo - rFrom ) / 100, gFactor = ( gTo - gFrom ) / 100, bFactor = ( bTo - bFrom ) / 100, r = ( Math.round( rFrom + ( complexity * rFactor) ) ).toString( 16 ), g = ( Math.round( gFrom + ( complexity * gFactor) ) ).toString( 16 ), b = ( Math.round( bFrom + ( complexity * bFactor) ) ).toString( 16 ), blendedHex = '#' + r + g + b; return blendedHex; }; |
So that version does all the calculation on the fly – feed in any two colours whenever you want to get the result. Odds are however, you’ll be working with a fixed pair of colours normally, and recalculating all those, admittedly simple numbers, is a waste of CPU. Here is a version that calculates all the key values beforehand, and works with the complexify jQuery plugin [http://danpalmer.me/jquery-complexify/]:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
var dangerColor = 'f14f4f', successColor = '66d92f', rFrom = parseInt( dangerColor.substr( 0, 2 ), 16 ), gFrom = parseInt( dangerColor.substr( 2, 2 ), 16 ), bFrom = parseInt( dangerColor.substr( 4, 2 ), 16 ), rTo = parseInt( successColor.substr( 0, 2 ), 16 ), gTo = parseInt( successColor.substr( 2, 2 ), 16 ), bTo = parseInt( successColor.substr( 4, 2 ), 16 ), rFactor = ( rTo - rFrom ) / 100, gFactor = ( gTo - gFrom ) / 100, bFactor = ( bTo - bFrom ) / 100; $( '#new-password' ) .complexify( { minimumChars : 10 }, function( valid, complexity ){ var r = ( Math.round( rFrom + ( complexity * rFactor) ) ).toString( 16 ), g = ( Math.round( gFrom + ( complexity * gFactor) ) ).toString( 16 ), b = ( Math.round( bFrom + ( complexity * bFactor) ) ).toString( 16 ), rgb = '#' + r + g + b; $( '.strength span' ).css( { width : complexity + '%', backgroundColor : rgb } ); } ); |
Okay, all well and good so far. In my case I have a strength meter that transforms from red to green via all the colours in-between!
There’s a word for such colours, now what was it?
Oh yeah. Fugly.
They all naaaaasty browns.
What we really want is a nice mid-way colour, a good ‘warning’ orange, so we go from danger, to warning, to safety in a nice smooth transitions.
Well, all we need to do is calculate a few more variables and we are there:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
var dangerColor = 'f14f4f', warningColor = 'f6b83f', successColor = '66d92f', rLowerFrom = parseInt( dangerColor.substr( 0, 2 ), 16 ), gLowerFrom = parseInt( dangerColor.substr( 2, 2 ), 16 ), bLowerFrom = parseInt( dangerColor.substr( 4, 2 ), 16 ), rLowerTo = parseInt( warningColor.substr( 0, 2 ), 16 ), gLowerTo = parseInt( warningColor.substr( 2, 2 ), 16 ), bLowerTo = parseInt( warningColor.substr( 4, 2 ), 16 ), rLowerFactor = ( rLowerTo - rLowerFrom ) / 100, gLowerFactor = ( gLowerTo - gLowerFrom ) / 100, bLowerFactor = ( bLowerTo - bLowerFrom ) / 100; rUpperFrom = parseInt( warningColor.substr( 0, 2 ), 16 ), gUpperFrom = parseInt( warningColor.substr( 2, 2 ), 16 ), bUpperFrom = parseInt( warningColor.substr( 4, 2 ), 16 ), rUpperTo = parseInt( successColor.substr( 0, 2 ), 16 ), gUpperTo = parseInt( successColor.substr( 2, 2 ), 16 ), bUpperTo = parseInt( successColor.substr( 4, 2 ), 16 ), rUpperFactor = ( rUpperTo - rUpperFrom ) / 100, gUpperFactor = ( gUpperTo - gUpperFrom ) / 100, bUpperFactor = ( bUpperTo - bUpperFrom ) / 100; $( '#new-password' ) .complexify( { minimumChars : 10 }, function( valid, complexity ){ var rFrom = (complexity < 50 ) ? rLowerFrom : rUpperFrom, rFactor = (complexity < 50 ) ? rLowerFactor : rUpperFactor, gFrom = (complexity < 50 ) ? gLowerFrom : gUpperFrom, gFactor = (complexity < 50 ) ? gLowerFactor : gUpperFactor, bFrom = (complexity < 50 ) ? bLowerFrom : bUpperFrom, bFactor = (complexity < 50 ) ? bLowerFactor : bUpperFactor, r = ( Math.round( rFrom + ( complexity * rFactor) ) ).toString( 16 ), g = ( Math.round( gFrom + ( complexity * gFactor) ) ).toString( 16 ), b = ( Math.round( bFrom + ( complexity * bFactor) ) ).toString( 16 ), rgb = '#' + r + g + b, strongIcon = $( '.validation-password-strength i[class^="icon-"]' ); $( '.strength span' ).css( { width : complexity + '%', backgroundColor : rgb } ); } ); |
What’s wrong here? DRY, baby, DRY! Don’t Repeat Yourself. That massive stack of vars can be broken down with some little functions to reduce the humidity around here. But I don’t have time for that right now. The overseer is cracking his whip..
A demo would be nice, wouldn’t it? Tough. I’ve got work to do. Sort it out on your own.
And oh look! I FINALLY have syntax highlighting on the new site! At some point I will have to trawl through the old posts and get them formatted and highlighted.
One day…