123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417 |
- /// <reference path="../../../dist/preview release/babylon.d.ts"/>
- module BABYLON.GUI {
- export class ColorPicker extends Control {
- private _colorWheelCanvas: HTMLCanvasElement;
-
- private _value: Color3 = Color3.Red();
- private _tmpColor = new Color3();
- private _pointerStartedOnSquare = false;
- private _pointerStartedOnWheel = false;
-
- private _squareLeft = 0;
- private _squareTop = 0;
- private _squareSize = 0;
- private _h = 360;
- private _s = 1;
- private _v = 1;
-
- public onValueChangedObservable = new Observable<Color3>();
- public get value(): Color3 {
- return this._value;
- }
- public set value(value: Color3) {
- if (this._value.equals(value)) {
- return;
- }
- this._value.copyFrom(value);
- this._RGBtoHSV(this._value, this._tmpColor);
-
- this._h = this._tmpColor.r;
- this._s = Math.max(this._tmpColor.g, 0.00001);
- this._v = Math.max(this._tmpColor.b, 0.00001);
- this._markAsDirty();
- this.onValueChangedObservable.notifyObservers(this._value);
- }
- public set width(value: string | number ) {
- if (this._width.toString(this._host) === value) {
- return;
- }
- if (this._width.fromString(value)) {
- this._height.fromString(value);
- this._markAsDirty();
- }
- }
- public set height(value: string | number ) {
- if (this._height.toString(this._host) === value) {
- return;
- }
- if (this._height.fromString(value)) {
- this._width.fromString(value);
- this._markAsDirty();
- }
- }
- public get size(): string | number {
- return this.width;
- }
- public set size(value: string | number){
- this.width = value;
- }
- constructor(public name?: string) {
- super(name);
- this.value = new BABYLON.Color3(.88, .1, .1);
- this.size = "200px";
- this.isPointerBlocker = true;
- }
- protected _getTypeName(): string {
- return "ColorPicker";
- }
- private _updateSquareProps():void {
- var radius = Math.min(this._currentMeasure.width, this._currentMeasure.height)*.5;
- var wheelThickness = radius*.2;
- var innerDiameter = (radius-wheelThickness)*2;
- var squareSize = innerDiameter/(Math.sqrt(2));
- var offset = radius - squareSize*.5;
- this._squareLeft = this._currentMeasure.left + offset;
- this._squareTop = this._currentMeasure.top + offset;
- this._squareSize = squareSize;
- }
- private _drawGradientSquare(hueValue:number, left:number, top:number, width:number, height:number, context: CanvasRenderingContext2D) {
- var lgh = context.createLinearGradient(left, top, width+left, top);
- lgh.addColorStop(0, '#fff');
- lgh.addColorStop(1, 'hsl(' + hueValue + ', 100%, 50%)');
- context.fillStyle = lgh;
- context.fillRect(left, top, width, height);
- var lgv = context.createLinearGradient(left, top, left, height+top);
- lgv.addColorStop(0, 'rgba(0,0,0,0)');
- lgv.addColorStop(1, '#000');
- context.fillStyle = lgv;
- context.fillRect(left, top, width, height);
- }
- private _drawCircle(centerX:number, centerY:number, radius:number, context: CanvasRenderingContext2D) {
- context.beginPath();
- context.arc(centerX, centerY, radius+1, 0, 2 * Math.PI, false);
- context.lineWidth = 3;
- context.strokeStyle = '#333333';
- context.stroke();
- context.beginPath();
- context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
- context.lineWidth = 3;
- context.strokeStyle = '#ffffff';
- context.stroke();
- }
- private _createColorWheelCanvas(radius:number, thickness:number): HTMLCanvasElement {
- var canvas = document.createElement("canvas");
- canvas.width = radius * 2;
- canvas.height = radius * 2;
- var context = <CanvasRenderingContext2D>canvas.getContext("2d");
- var image = context.getImageData(0, 0, radius * 2, radius * 2);
- var data = image.data;
-
- var color = this._tmpColor;
- var maxDistSq = radius*radius;
- var innerRadius = radius - thickness;
- var minDistSq = innerRadius*innerRadius;
- for (var x = -radius; x < radius; x++) {
- for (var y = -radius; y < radius; y++) {
-
- var distSq = x*x + y*y;
-
- if (distSq > maxDistSq || distSq < minDistSq) {
- continue;
- }
- var dist = Math.sqrt(distSq);
- var ang = Math.atan2(y, x);
-
- this._HSVtoRGB(ang * 180/Math.PI + 180, dist/radius, 1, color);
-
- var index = ((x + radius) + ((y + radius)*2*radius)) * 4;
-
- data[index] = color.r*255;
- data[index + 1] = color.g*255;
- data[index + 2] = color.b*255;
- var alphaRatio = (dist - innerRadius) / (radius - innerRadius);
- //apply less alpha to bigger color pickers
- var alphaAmount = .2;
- var maxAlpha = .2;
- var minAlpha = .04;
- var lowerRadius = 50;
- var upperRadius = 150;
- if(radius < lowerRadius){
- alphaAmount = maxAlpha;
- }else if(radius > upperRadius){
- alphaAmount = minAlpha;
- }else{
- alphaAmount = (minAlpha - maxAlpha)*(radius - lowerRadius)/(upperRadius - lowerRadius) + maxAlpha;
- }
-
- var alphaRatio = (dist - innerRadius) / (radius - innerRadius);
- if (alphaRatio < alphaAmount) {
- data[index + 3] = 255 * (alphaRatio / alphaAmount);
- } else if (alphaRatio > 1 - alphaAmount) {
- data[index + 3] = 255 * (1.0 - ((alphaRatio - (1 - alphaAmount)) / alphaAmount));
- } else {
- data[index + 3] = 255;
- }
- }
- }
- context.putImageData(image, 0, 0);
- return canvas;
- }
- private _RGBtoHSV(color:Color3, result:Color3){
- var r = color.r;
- var g = color.g;
- var b = color.b;
- var max = Math.max(r, g, b);
- var min = Math.min(r, g, b);
- var h = 0;
- var s = 0;
- var v = max;
-
- var dm = max - min;
-
- if(max !== 0){
- s = dm / max;
- }
- if(max != min) {
- if(max == r){
- h = (g - b) / dm;
- if(g < b){
- h += 6;
- }
- }else if(max == g){
- h = (b - r) / dm + 2;
- }else if(max == b){
- h = (r - g) / dm + 4;
- }
- h *= 60;
- }
-
- result.r = h;
- result.g = s;
- result.b = v;
- }
- private _HSVtoRGB(hue:number, saturation:number, value:number, result:Color3) {
- var chroma = value * saturation;
- var h = hue / 60;
- var x = chroma * (1- Math.abs((h % 2) - 1));
- var r = 0;
- var g = 0;
- var b = 0;
- if (h >= 0 && h <= 1) {
- r = chroma;
- g = x;
- } else if (h >= 1 && h <= 2) {
- r = x;
- g = chroma;
- } else if (h >= 2 && h <= 3) {
- g = chroma;
- b = x;
- } else if (h >= 3 && h <= 4) {
- g = x;
- b = chroma;
- } else if (h >= 4 && h <= 5) {
- r = x;
- b = chroma;
- } else if (h >= 5 && h <= 6) {
- r = chroma;
- b = x;
- }
-
- var m = value - chroma;
- result.set((r+m), (g+m), (b+m));
- }
- public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
- context.save();
- this._applyStates(context);
- if (this._processMeasures(parentMeasure, context)) {
- var radius = Math.min(this._currentMeasure.width, this._currentMeasure.height)*.5;
- var wheelThickness = radius*.2;
- var left = this._currentMeasure.left;
- var top = this._currentMeasure.top;
- if(!this._colorWheelCanvas || this._colorWheelCanvas.width != radius*2){
- this._colorWheelCanvas = this._createColorWheelCanvas(radius, wheelThickness);
- }
- this._updateSquareProps();
- if(this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY){
- context.shadowColor = this.shadowColor;
- context.shadowBlur = this.shadowBlur;
- context.shadowOffsetX = this.shadowOffsetX;
- context.shadowOffsetY = this.shadowOffsetY;
-
- context.fillRect(this._squareLeft, this._squareTop, this._squareSize, this._squareSize);
- }
- context.drawImage(this._colorWheelCanvas, left, top);
- if(this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY){
- context.shadowBlur = 0;
- context.shadowOffsetX = 0;
- context.shadowOffsetY = 0;
- }
- this._drawGradientSquare(this._h,
- this._squareLeft,
- this._squareTop,
- this._squareSize,
- this._squareSize,
- context);
-
- var cx = this._squareLeft + this._squareSize*this._s;
- var cy = this._squareTop + this._squareSize*(1 - this._v);
-
- this._drawCircle(cx, cy, radius*.04, context);
- var dist = radius - wheelThickness*.5;
- cx = left + radius + Math.cos((this._h-180)*Math.PI/180)*dist;
- cy = top + radius + Math.sin((this._h-180)*Math.PI/180)*dist;
- this._drawCircle(cx, cy, wheelThickness*.35, context);
- }
- context.restore();
- }
- // Events
- private _pointerIsDown = false;
- private _updateValueFromPointer(x: number, y:number): void {
- if(this._pointerStartedOnWheel)
- {
- var radius = Math.min(this._currentMeasure.width, this._currentMeasure.height)*.5;
- var centerX = radius + this._currentMeasure.left;
- var centerY = radius + this._currentMeasure.top;
- this._h = Math.atan2(y - centerY, x - centerX)*180/Math.PI + 180;
- }
- else if(this._pointerStartedOnSquare)
- {
- this._updateSquareProps();
- this._s = (x - this._squareLeft) / this._squareSize;
- this._v = 1 - (y - this._squareTop) / this._squareSize;
- this._s = Math.min(this._s, 1);
- this._s = Math.max(this._s, 0.00001);
- this._v = Math.min(this._v, 1);
- this._v = Math.max(this._v, 0.00001);
- }
- this._HSVtoRGB(this._h, this._s, this._v, this._tmpColor);
- this.value = this._tmpColor;
- }
- private _isPointOnSquare(coordinates: Vector2):boolean {
- this._updateSquareProps();
- var left = this._squareLeft;
- var top = this._squareTop;
- var size = this._squareSize;
- if(coordinates.x >= left && coordinates.x <= left + size &&
- coordinates.y >= top && coordinates.y <= top + size){
- return true;
- }
- return false;
- }
- private _isPointOnWheel(coordinates: Vector2):boolean {
- var radius = Math.min(this._currentMeasure.width, this._currentMeasure.height)*.5;
- var centerX = radius + this._currentMeasure.left;
- var centerY = radius + this._currentMeasure.top;
- var wheelThickness = radius*.2;
- var innerRadius = radius-wheelThickness;
- var radiusSq = radius*radius;
- var innerRadiusSq = innerRadius*innerRadius;
- var dx = coordinates.x - centerX;
- var dy = coordinates.y - centerY;
- var distSq = dx*dx + dy*dy;
- if(distSq <= radiusSq && distSq >= innerRadiusSq){
- return true;
- }
- return false;
- }
- public _onPointerDown(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): boolean {
- if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
- return false;
- }
- this._pointerIsDown = true;
- this._pointerStartedOnSquare = false;
- this._pointerStartedOnWheel = false;
- if(this._isPointOnSquare(coordinates)){
- this._pointerStartedOnSquare = true;
- }else if(this._isPointOnWheel(coordinates)){
- this._pointerStartedOnWheel = true;
- }
- this._updateValueFromPointer(coordinates.x, coordinates.y);
- this._host._capturingControl[pointerId] = this;
- return true;
- }
- public _onPointerMove(target: Control, coordinates: Vector2): void {
- if (this._pointerIsDown) {
- this._updateValueFromPointer(coordinates.x, coordinates.y);
- }
- super._onPointerMove(target, coordinates);
- }
- public _onPointerUp (target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number, notifyClick: boolean): void {
- this._pointerIsDown = false;
-
- delete this._host._capturingControl[pointerId];
- super._onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick);
- }
- }
- }
|