瀏覽代碼

Merge pull request #6898 from dubejf/rgba-parse

Color3: CSS colors parsing for rgba, hsl, hsla
Mr.doob 10 年之前
父節點
當前提交
f1cf5fedb6
共有 2 個文件被更改,包括 149 次插入30 次删除
  1. 71 27
      src/math/Color.js
  2. 78 3
      test/unit/math/Color.js

+ 71 - 27
src/math/Color.js

@@ -105,68 +105,112 @@ THREE.Color.prototype = {
 
 	setStyle: function ( style ) {
 
-		// rgb(255,0,0)
+		var m;
 
-		if ( /^rgb\((\d+), ?(\d+), ?(\d+)\)$/i.test( style ) ) {
+		// rgb / hsl
+		if ( m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec( style ) ) {
 
-			var color = /^rgb\((\d+), ?(\d+), ?(\d+)\)$/i.exec( style );
+			var color;
+			var name = m[ 1 ];
+			var components = m[ 2 ];
 
-			this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;
-			this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;
-			this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;
+			switch ( name ) {
 
-			return this;
+				case 'rgb':
+				case 'rgba':
 
-		}
+					if ( color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/.exec( components ) ) {
 
-		// rgb(100%,0%,0%)
+						// rgb(255,0,0)
+						this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;
+						this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;
+						this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;
 
-		if ( /^rgb\((\d+)\%, ?(\d+)\%, ?(\d+)\%\)$/i.test( style ) ) {
+						return this;
 
-			var color = /^rgb\((\d+)\%, ?(\d+)\%, ?(\d+)\%\)$/i.exec( style );
+					}
 
-			this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;
-			this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;
-			this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;
+					if ( color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%/.exec( components ) ) {
 
-			return this;
+						// rgb(100%,0%,0%)
+						this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;
+						this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;
+						this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;
 
-		}
+						return this;
+
+					}
 
-		// #ff0000
+					break;
 
-		if ( /^\#([0-9a-f]{6})$/i.test( style ) ) {
+				case 'hsl':
+				case 'hsla':
 
-			var color = /^\#([0-9a-f]{6})$/i.exec( style );
+					if ( color = /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%/.exec( components ) ) {
 
-			this.setHex( parseInt( color[ 1 ], 16 ) );
+						// hsl(120,50%,50%)
+						var h = parseFloat( color[ 1 ], 10 );
+						var s = parseInt( color[ 2 ], 10 ) / 100;
+						var l = parseInt( color[ 3 ], 10 ) / 100;
+
+						return this.setHSL( h, s, l );
+
+					}
+
+					break;
+
+			}
 
+			// unknown color
 			return this;
 
 		}
 
-		// #f00
+		// hex
+		if ( m = /^\#([A-Fa-f0-9]+)$/.exec( style ) ) {
 
-		if ( /^\#([0-9a-f])([0-9a-f])([0-9a-f])$/i.test( style ) ) {
+			var hex = m[ 1 ];
+			var size = hex.length;
 
-			var color = /^\#([0-9a-f])([0-9a-f])([0-9a-f])$/i.exec( style );
+			if ( size === 3 ) {
 
-			this.setHex( parseInt( color[ 1 ] + color[ 1 ] + color[ 2 ] + color[ 2 ] + color[ 3 ] + color[ 3 ], 16 ) );
+				// # ff0
+				this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;
+				this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;
+				this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;
 
+				return this;
+
+			}
+
+			if ( size === 6 ) {
+
+				// #fa11ac
+				this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;
+				this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;
+				this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;
+
+				return this;
+
+			}
+
+			// unknown color
 			return this;
 
 		}
 
-		// red
-
-		if ( /^(\w+)$/i.test( style ) ) {
+		// color keywords
+		if ( /^\w+$/i.test( style ) ) {
 
+			// red
 			this.setHex( THREE.ColorKeywords[ style ] );
 
 			return this;
 
 		}
 
+		// unknown color
+		return this;
 
 	},
 

+ 78 - 3
test/unit/math/Color.js

@@ -118,9 +118,25 @@ test( "setStyleRGBRed", function(){
     ok( c.b === 0, "Blue: " + c.b );
 });
 
+test( "setStyleRGBARed", function(){
+    var c = new THREE.Color();
+    c.setStyle('rgba(255,0,0,0.5)');
+    ok( c.r == 1, "Red: " + c.r );
+    ok( c.g === 0, "Green: " + c.g );
+    ok( c.b === 0, "Blue: " + c.b );
+});
+
 test( "setStyleRGBRedWithSpaces", function(){
     var c = new THREE.Color();
-    c.setStyle('rgb(255, 0, 0)');
+    c.setStyle('rgb( 255 , 0,   0 )');
+    ok( c.r == 1, "Red: " + c.r );
+    ok( c.g === 0, "Green: " + c.g );
+    ok( c.b === 0, "Blue: " + c.b );
+});
+
+test( "setStyleRGBARedWithSpaces", function(){
+    var c = new THREE.Color();
+    c.setStyle('rgba( 255,  0,  0  , 1 )');
     ok( c.r == 1, "Red: " + c.r );
     ok( c.g === 0, "Green: " + c.g );
     ok( c.b === 0, "Blue: " + c.b );
@@ -134,33 +150,92 @@ test( "setStyleRGBPercent", function(){
     ok( c.b == 0.1, "Blue: " + c.b );
 });
 
+test( "setStyleRGBAPercent", function(){
+    var c = new THREE.Color();
+    c.setStyle('rgba(100%,50%,10%, 0.5)');
+    ok( c.r == 1, "Red: " + c.r );
+    ok( c.g == 0.5, "Green: " + c.g );
+    ok( c.b == 0.1, "Blue: " + c.b );
+});
+
 test( "setStyleRGBPercentWithSpaces", function(){
     var c = new THREE.Color();
-    c.setStyle('rgb(100%,50%,10%)');
+    c.setStyle('rgb( 100% ,50%  , 10% )');
+    ok( c.r == 1, "Red: " + c.r );
+    ok( c.g == 0.5, "Green: " + c.g );
+    ok( c.b == 0.1, "Blue: " + c.b );
+});
+
+test( "setStyleRGBAPercentWithSpaces", function(){
+    var c = new THREE.Color();
+    c.setStyle('rgba( 100% ,50%  ,  10%, 0.5 )');
     ok( c.r == 1, "Red: " + c.r );
     ok( c.g == 0.5, "Green: " + c.g );
     ok( c.b == 0.1, "Blue: " + c.b );
 });
 
+test( "setStyleHSLRed", function(){
+    var c = new THREE.Color();
+    c.setStyle('hsl(360,100%,50%)');
+    ok( c.r == 1, "Red: " + c.r );
+    ok( c.g === 0, "Green: " + c.g );
+    ok( c.b === 0, "Blue: " + c.b );
+});
+
+test( "setStyleHSLARed", function(){
+    var c = new THREE.Color();
+    c.setStyle('hsla(360,100%,50%,0.5)');
+    ok( c.r == 1, "Red: " + c.r );
+    ok( c.g === 0, "Green: " + c.g );
+    ok( c.b === 0, "Blue: " + c.b );
+});
+
+test( "setStyleHSLRedWithSpaces", function(){
+    var c = new THREE.Color();
+    c.setStyle('hsl(360,  100% , 50% )');
+    ok( c.r == 1, "Red: " + c.r );
+    ok( c.g === 0, "Green: " + c.g );
+    ok( c.b === 0, "Blue: " + c.b );
+});
+
+test( "setStyleHSLARedWithSpaces", function(){
+    var c = new THREE.Color();
+    c.setStyle('hsla( 360,  100% , 50%,  0.5 )');
+    ok( c.r == 1, "Red: " + c.r );
+    ok( c.g === 0, "Green: " + c.g );
+    ok( c.b === 0, "Blue: " + c.b );
+});
+
 test( "setStyleHexSkyBlue", function(){
     var c = new THREE.Color();
     c.setStyle('#87CEEB');
     ok(c.getHex() == 0x87CEEB, "Hex c: " + c.getHex());
 });
 
+test( "setStyleHexSkyBlueMixed", function(){
+    var c = new THREE.Color();
+    c.setStyle('#87cEeB');
+    ok(c.getHex() == 0x87CEEB, "Hex c: " + c.getHex());
+});
+
 test( "setStyleHex2Olive", function(){
     var c = new THREE.Color();
     c.setStyle('#F00');
     ok(c.getHex() == 0xFF0000, "Hex c: " + c.getHex());
 });
 
+test( "setStyleHex2OliveMixed", function(){
+    var c = new THREE.Color();
+    c.setStyle('#f00');
+    ok(c.getHex() == 0xFF0000, "Hex c: " + c.getHex());
+});
+
 test( "setStyleColorName", function(){
     var c = new THREE.Color();
     c.setStyle('powderblue');
     ok(c.getHex() == 0xB0E0E6, "Hex c: " + c.getHex());
 });
 
-
 test( "getHex", function(){
     var c = new THREE.Color('red');
     var res = c.getHex();