提交 559737ed 编写于 作者: D dubejf

Color3: CSS colors parsing for rgba, hsl, hsla

Adds support for:
- rgba(int, int, int, float)
- rgba(pct, pct, pct, float)
- hsl(deg, pct, pct)
- hsla(deg, pct, pct, float)

More tolerant about whitespaces. Add new unit tests.

Finalizes support for parsing "all" CSS color expression. Alpha
component is ignored. Fixes #6014.

Hat tip:
https://www.npmjs.com/package/parse-color
http://www.css-validator.org/
上级 9c490512
...@@ -105,68 +105,112 @@ THREE.Color.prototype = { ...@@ -105,68 +105,112 @@ THREE.Color.prototype = {
setStyle: function ( style ) { 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; switch ( name ) {
this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;
this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;
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; if ( color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%/.exec( components ) ) {
this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;
this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;
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; 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; return this;
} }
// red // color keywords
if ( /^\w+$/i.test( style ) ) {
if ( /^(\w+)$/i.test( style ) ) {
// red
this.setHex( THREE.ColorKeywords[ style ] ); this.setHex( THREE.ColorKeywords[ style ] );
return this; return this;
} }
// unknown color
return this;
}, },
......
...@@ -118,9 +118,25 @@ test( "setStyleRGBRed", function(){ ...@@ -118,9 +118,25 @@ test( "setStyleRGBRed", function(){
ok( c.b === 0, "Blue: " + c.b ); 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(){ test( "setStyleRGBRedWithSpaces", function(){
var c = new THREE.Color(); 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.r == 1, "Red: " + c.r );
ok( c.g === 0, "Green: " + c.g ); ok( c.g === 0, "Green: " + c.g );
ok( c.b === 0, "Blue: " + c.b ); ok( c.b === 0, "Blue: " + c.b );
...@@ -134,33 +150,92 @@ test( "setStyleRGBPercent", function(){ ...@@ -134,33 +150,92 @@ test( "setStyleRGBPercent", function(){
ok( c.b == 0.1, "Blue: " + c.b ); 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(){ test( "setStyleRGBPercentWithSpaces", function(){
var c = new THREE.Color(); 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.r == 1, "Red: " + c.r );
ok( c.g == 0.5, "Green: " + c.g ); ok( c.g == 0.5, "Green: " + c.g );
ok( c.b == 0.1, "Blue: " + c.b ); 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(){ test( "setStyleHexSkyBlue", function(){
var c = new THREE.Color(); var c = new THREE.Color();
c.setStyle('#87CEEB'); c.setStyle('#87CEEB');
ok(c.getHex() == 0x87CEEB, "Hex c: " + c.getHex()); 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(){ test( "setStyleHex2Olive", function(){
var c = new THREE.Color(); var c = new THREE.Color();
c.setStyle('#F00'); c.setStyle('#F00');
ok(c.getHex() == 0xFF0000, "Hex c: " + c.getHex()); 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(){ test( "setStyleColorName", function(){
var c = new THREE.Color(); var c = new THREE.Color();
c.setStyle('powderblue'); c.setStyle('powderblue');
ok(c.getHex() == 0xB0E0E6, "Hex c: " + c.getHex()); ok(c.getHex() == 0xB0E0E6, "Hex c: " + c.getHex());
}); });
test( "getHex", function(){ test( "getHex", function(){
var c = new THREE.Color('red'); var c = new THREE.Color('red');
var res = c.getHex(); var res = c.getHex();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册