mirror of
https://github.com/scratchfoundation/scratch-paint.git
synced 2024-12-22 13:32:28 -05:00
Merge pull request #261 from paulkaplan/touch-sliders
Make color pick touch accessible and jump on click
This commit is contained in:
commit
efe30ec50d
4 changed files with 53 additions and 17 deletions
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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.handleColorChange();
|
||||
this.setState({hue: hue}, () => {
|
||||
this.handleColorChange();
|
||||
});
|
||||
}
|
||||
handleSaturationChange (saturation) {
|
||||
this.setState({saturation: saturation});
|
||||
this.handleColorChange();
|
||||
this.setState({saturation: saturation}, () => {
|
||||
this.handleColorChange();
|
||||
});
|
||||
}
|
||||
handleBrightnessChange (brightness) {
|
||||
this.setState({brightness: brightness});
|
||||
this.handleColorChange();
|
||||
this.setState({brightness: brightness}, () => {
|
||||
this.handleColorChange();
|
||||
});
|
||||
}
|
||||
handleColorChange () {
|
||||
this.props.onChangeColor(hsvToHex(
|
||||
|
|
|
@ -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
16
src/lib/touch-utils.js
Normal 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
|
||||
};
|
Loading…
Reference in a new issue