import * as React from "react"; import { Color3, Color4 } from "babylonjs/Maths/math.color"; import { ColorComponentEntry } from './colorComponentEntry'; import { HexColor } from './hexColor'; require("./colorPicker.scss"); /** * Interface used to specify creation options for color picker */ export interface IColorPickerProps { color: Color3 | Color4, debugMode?: boolean, onColorChanged?: (color: Color3 | Color4) => void } /** * Interface used to specify creation options for color picker */ export interface IColorPickerState { color: Color3; alpha: number; } /** * Class used to create a color picker */ export class ColorPicker extends React.Component { private _saturationRef: React.RefObject; private _hueRef: React.RefObject; private _isSaturationPointerDown: boolean; private _isHuePointerDown: boolean; constructor(props: IColorPickerProps) { super(props); if (this.props.color instanceof Color4) { this.state = {color: new Color3(this.props.color.r, this.props.color.g, this.props.color.b), alpha: this.props.color.a}; } else { this.state = {color : this.props.color.clone(), alpha: 1}; } this._saturationRef = React.createRef(); this._hueRef = React.createRef(); } onSaturationPointerDown(evt: React.PointerEvent) { this._evaluateSaturation(evt); this._isSaturationPointerDown = true; evt.currentTarget.setPointerCapture(evt.pointerId); } onSaturationPointerUp(evt: React.PointerEvent) { this._isSaturationPointerDown = false; evt.currentTarget.releasePointerCapture(evt.pointerId); } onSaturationPointerMove(evt: React.PointerEvent) { if (!this._isSaturationPointerDown) { return; } this._evaluateSaturation(evt); } onHuePointerDown(evt: React.PointerEvent) { this._evaluateHue(evt); this._isHuePointerDown = true; evt.currentTarget.setPointerCapture(evt.pointerId); } onHuePointerUp(evt: React.PointerEvent) { this._isHuePointerDown = false; evt.currentTarget.releasePointerCapture(evt.pointerId); } onHuePointerMove(evt: React.PointerEvent) { if (!this._isHuePointerDown) { return; } this._evaluateHue(evt); } private _evaluateSaturation(evt: React.PointerEvent) { let left = evt.nativeEvent.offsetX; let top = evt.nativeEvent.offsetY; const saturation = Math.min(1, Math.max(0.0001, left / this._saturationRef.current!.clientWidth)); const value = Math.min(1, Math.max(0.0001, 1 - (top / this._saturationRef.current!.clientHeight))); if (this.props.debugMode) { console.log("Saturation: " + saturation); console.log("Value: " + value); } let hsv = this.state.color.toHSV(); Color3.HSVtoRGBToRef(hsv.r, saturation, value, this.state.color); this.setState({color: this.state.color}); } private _evaluateHue(evt: React.PointerEvent) { let left = evt.nativeEvent.offsetX; const hue = 360 * Math.min(0.9999, Math.max(0.0001, left / this._hueRef.current!.clientWidth)); if (this.props.debugMode) { console.log("Hue: " + hue); } let hsv = this.state.color.toHSV(); Color3.HSVtoRGBToRef(hue, Math.max(hsv.g, 0.0001), Math.max(hsv.b, 0.0001), this.state.color); this.setState({color: this.state.color}); } componentDidUpdate() { this.raiseOnColorChanged(); } raiseOnColorChanged() { if (!this.props.onColorChanged) { return; } if (this.props.color instanceof Color4) { let newColor4 = Color4.FromColor3(this.state.color, this.state.alpha); this.props.onColorChanged(newColor4); return; } this.props.onColorChanged(this.state.color.clone()); } public render() { let colorHex = this.state.color.toHexString(); let hsv = this.state.color.toHSV(); let colorRef = new Color3(); Color3.HSVtoRGBToRef(hsv.r, 1, 1, colorRef) let colorHexRef = colorRef.toHexString(); let hasAlpha = this.props.color instanceof Color4; return (
this.onSaturationPointerMove(e)} onPointerDown={e => this.onSaturationPointerDown(e)} onPointerUp={e => this.onSaturationPointerUp(e)} ref={this._saturationRef} style={{ background: colorHexRef }}>
this.onHuePointerMove(e)} onPointerDown={e => this.onHuePointerDown(e)} onPointerUp={e => this.onHuePointerUp(e)} >
{ this.state.color.r = value / 255.0; this.forceUpdate(); }}/>
{ this.state.color.g = value / 255.0; this.forceUpdate(); }}/>
{ this.state.color.b = value / 255.0; this.forceUpdate(); }}/>
{ this.setState({alpha: value / 255.0}); this.forceUpdate(); }}/>
Hex
{ this.setState({color: Color3.FromHexString(value)}); }}/>
); } }