Merge pull request #261 from paulkaplan/touch-sliders

Make color pick touch accessible and jump on click
This commit is contained in:
Paul Kaplan 2018-01-22 09:17:29 -05:00 committed by GitHub
commit efe30ec50d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 17 deletions

View file

@ -1,6 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import bindAll from 'lodash.bindall';
import {getEventXY} from '../../lib/touch-utils';
import styles from './slider.css';
@ -14,25 +15,39 @@ class SliderComponent extends React.Component {
'handleMouseDown',
'handleMouseUp',
'handleMouseMove',
'handleClickBackground',
'setBackground'
]);
}
handleMouseDown () {
document.addEventListener('mouseup', this.handleMouseUp);
document.addEventListener('mousemove', this.handleMouseMove);
document.addEventListener('mouseup', this.handleMouseUp);
document.addEventListener('touchmove', this.handleMouseMove);
document.addEventListener('touchend', this.handleMouseUp);
}
handleMouseUp () {
document.removeEventListener('mouseup', this.handleMouseUp);
document.removeEventListener('mousemove', this.handleMouseMove);
document.removeEventListener('mouseup', this.handleMouseUp);
document.removeEventListener('touchmove', this.handleMouseMove);
document.removeEventListener('touchend', this.handleMouseUp);
}
handleMouseMove (event) {
event.preventDefault();
this.props.onChange(this.scaleMouseToSliderPosition(event));
}
handleClickBackground (event) {
this.props.onChange(this.scaleMouseToSliderPosition(event));
}
scaleMouseToSliderPosition (event){
const {x} = getEventXY(event);
const backgroundBBox = this.background.getBoundingClientRect();
const x = event.clientX - backgroundBBox.left;
this.props.onChange(Math.max(0, Math.min(100, 100 * x / backgroundBBox.width)));
const scaledX = x - backgroundBBox.left;
return Math.max(0, Math.min(100, 100 * scaledX / backgroundBBox.width));
}
setBackground (ref) {
@ -53,6 +68,7 @@ class SliderComponent extends React.Component {
style={{
backgroundImage: this.props.background
}}
onClick={this.handleClickBackground}
>
<div
className={styles.handle}
@ -60,6 +76,7 @@ class SliderComponent extends React.Component {
left: `${handleOffset}px`
}}
onMouseDown={this.handleMouseDown}
onTouchStart={this.handleMouseDown}
/>
</div>
);

View file

@ -28,9 +28,9 @@ const hsvToHex = (h, s, v) =>
parseColor(`hsv(${3.6 * h}, ${s}, ${v})`).hex
;
// Important! This component ignores new color props and cannot be updated
// This is to make the HSV <=> RGB conversion stable. Because of this, the
// component MUST be unmounted in order to change the props externally.
// Important! This component ignores new color props except when isEyeDropping
// This is to make the HSV <=> RGB conversion stable. The sliders manage their
// own changes until unmounted or color changes with props.isEyeDropping = true.
class ColorPicker extends React.Component {
constructor (props) {
super(props);
@ -51,7 +51,7 @@ class ColorPicker extends React.Component {
};
}
componentWillReceiveProps (newProps) {
if (this.props.color !== newProps.color) {
if (this.props.isEyeDropping && this.props.color !== newProps.color) {
// color set by eye dropper, so update slider states
const hsv = this.getHsv(newProps.color);
this.setState({
@ -68,16 +68,19 @@ class ColorPicker extends React.Component {
[50, 100, 100] : colorStringToHsv(color);
}
handleHueChange (hue) {
this.setState({hue: hue});
this.setState({hue: hue}, () => {
this.handleColorChange();
});
}
handleSaturationChange (saturation) {
this.setState({saturation: saturation});
this.setState({saturation: saturation}, () => {
this.handleColorChange();
});
}
handleBrightnessChange (brightness) {
this.setState({brightness: brightness});
this.setState({brightness: brightness}, () => {
this.handleColorChange();
});
}
handleColorChange () {
this.props.onChangeColor(hsvToHex(

View file

@ -140,14 +140,14 @@ class PaintEditor extends React.Component {
const callback = this.props.changeColorToEyeDropper;
this.eyeDropper.remove();
this.props.previousTool.activate();
this.props.onDeactivateEyeDropper();
this.stopEyeDroppingLoop();
if (!this.eyeDropper.hideLoupe) {
// If not hide loupe, that means the click is inside the canvas,
// so apply the new color
callback(colorString);
}
this.props.previousTool.activate();
this.props.onDeactivateEyeDropper();
this.stopEyeDroppingLoop();
this.setState({colorInfo: null});
}
}

16
src/lib/touch-utils.js Normal file
View file

@ -0,0 +1,16 @@
/* DO NOT EDIT
@todo This file is copied from GUI and should be pulled out into a shared library.
See https://github.com/LLK/scratch-paint/issues/13 */
const getEventXY = e => {
if (e.touches && e.touches[0]) {
return {x: e.touches[0].clientX, y: e.touches[0].clientY};
} else if (e.changedTouches && e.changedTouches[0]) {
return {x: e.changedTouches[0].clientX, y: e.changedTouches[0].clientY};
}
return {x: e.clientX, y: e.clientY};
};
export {
getEventXY
};