From 73077157124c84cfa87c00055b96cfb697288d9d Mon Sep 17 00:00:00 2001 From: Horcrux Date: Thu, 9 Jun 2016 23:30:10 +0800 Subject: [PATCH] add touchable support for shape elements --- README.md | 3 +- elements/Circle.js | 18 ------------ elements/Ellipse.js | 8 +++--- elements/Image.js | 8 +++--- elements/Line.js | 8 +++--- elements/Path.js | 19 ++++--------- elements/Rect.js | 8 +++--- elements/Shape.js | 32 +++++++++++++++++++++ elements/Text.js | 16 ++++------- lib/SvgTouchableMixin.js | 50 +++++++++++++++++++++++++++++++++ lib/extract/extractResponder.js | 17 +++++++---- lib/props.js | 3 +- 12 files changed, 123 insertions(+), 67 deletions(-) create mode 100644 elements/Shape.js diff --git a/README.md b/README.md index a053eeec..115ce654 100644 --- a/README.md +++ b/README.md @@ -568,8 +568,7 @@ npm install 1. add native method for elements 2. more Text features support 3. Pattern element -4. implement touchable elements -5. implement Animated elements +4. implement Animated elements #### Thanks: diff --git a/elements/Circle.js b/elements/Circle.js index 881434eb..be42bebd 100644 --- a/elements/Circle.js +++ b/elements/Circle.js @@ -4,11 +4,9 @@ import createNativeComponent from '../lib/createNativeComponent'; import mergeContext from '../lib/mergeContext'; import {circleProps, pathProps, fillProps, strokeProps, numberProp} from '../lib/props'; -class Circle extends Component{ static displayName = 'Circle'; static propTypes = { ...pathProps, - ...circleProps }; static contextTypes = { @@ -19,28 +17,12 @@ class Circle extends Component{ svgId: numberProp }; - //constructor() { - // super(...arguments); - // _.forEach(SvgTouchableMixin, (method, key) => { - // this[key] = method.bind(this); - // }); - // - // this.state = this.touchableGetInitialState(); - //}; - render() { let props = mergeContext(this.props, this.context); return ; } } diff --git a/elements/Ellipse.js b/elements/Ellipse.js index f3dbddf6..08095b30 100644 --- a/elements/Ellipse.js +++ b/elements/Ellipse.js @@ -1,11 +1,11 @@ -import React, {PropTypes, Component} from 'react'; -import extractProps from '../lib/extract/extractProps'; +import React, {PropTypes} from 'react'; import createNativeComponent from '../lib/createNativeComponent'; import mergeContext from '../lib/mergeContext'; +import Shape from './Shape'; import {ellipseProps, pathProps, fillProps, strokeProps, numberProp} from '../lib/props'; -class Ellipse extends Component{ +class Ellipse extends Shape{ static displayName = 'Ellipse'; static propTypes = { ...pathProps, @@ -23,7 +23,7 @@ class Ellipse extends Component{ render() { let props = mergeContext(this.props, this.context); return ); diff --git a/elements/Rect.js b/elements/Rect.js index 8c477784..5361cb5b 100644 --- a/elements/Rect.js +++ b/elements/Rect.js @@ -1,11 +1,11 @@ -import React, {PropTypes, Component} from 'react'; +import React, {PropTypes} from 'react'; import './Path'; // must import Path first, don`t know why. without this will throw an `Super expression must either be null or a function, not undefined` -import extractProps from '../lib/extract/extractProps'; import createNativeComponent from '../lib/createNativeComponent'; import mergeContext from '../lib/mergeContext'; import {rectProps, pathProps, fillProps, strokeProps, numberProp} from '../lib/props'; +import Shape from './Shape'; -class Rect extends Component{ +class Rect extends Shape { static displayName = 'Rect'; static propTypes = { ...pathProps, @@ -24,7 +24,7 @@ class Rect extends Component{ let props = mergeContext(this.props, this.context); return { + this[key] = method.bind(this); + }); + this.state = this.touchableGetInitialState(); + } + + extractProps = (props) => { + let extractedProps = extractProps(props); + if (extractedProps.touchable && !extractedProps.disabled) { + _.assign(extractedProps, { + onStartShouldSetResponder: this.touchableHandleStartShouldSetResponder, + onResponderTerminationRequest: this.touchableHandleResponderTerminationRequest, + onResponderGrant: this.touchableHandleResponderGrant, + onResponderMove: this.touchableHandleResponderMove, + onResponderRelease: this.touchableHandleResponderRelease, + onResponderTerminate: this.touchableHandleResponderTerminate + }); + } + + return extractedProps; + } +} + +export default Shape; diff --git a/elements/Text.js b/elements/Text.js index 662351e7..7fdf2f77 100644 --- a/elements/Text.js +++ b/elements/Text.js @@ -1,13 +1,13 @@ -import React, {Component, PropTypes} from 'react'; +import React, {PropTypes} from 'react'; import createNativeComponent from '../lib/createNativeComponent'; import Defs from './Defs'; -import _ from 'lodash'; import extractProps from '../lib/extract/extractProps'; import extractText from '../lib/extract/extractText'; +import mergeContext from '../lib/mergeContext'; import {numberProp, textProps, fillProps, strokeProps, pathProps} from '../lib/props'; +import Shape from './Shape'; - -class Text extends Component{ +class Text extends Shape { static displayName = 'Text'; static propTypes = { dx: numberProp, @@ -27,13 +27,7 @@ class Text extends Component{ }; render() { - let {props} = this; - - if (this.context.isInGroup) { - props = _.defaults(this.context, props, { - isInGroup: null - }); - } + let props = mergeContext(this.props, this.context); let x = 0; if (props.x) { diff --git a/lib/SvgTouchableMixin.js b/lib/SvgTouchableMixin.js index 28a1d697..790cf0b5 100644 --- a/lib/SvgTouchableMixin.js +++ b/lib/SvgTouchableMixin.js @@ -3,6 +3,56 @@ const PRESS_RETENTION_OFFSET = {top: 20, left: 20, right: 20, bottom: 30}; export default { ...Touchable.Mixin, + + touchableHandleStartShouldSetResponder: function (e) { + + if (this.props.onStartShouldSetResponder) { + return this.props.onStartShouldSetResponder(e); + } else { + return Touchable.Mixin.touchableHandleStartShouldSetResponder.call(this, e); + } + }, + + touchableHandleResponderTerminationRequest: function (e) { + if (this.props.onResponderTerminationRequest) { + return this.props.onResponderTerminationRequest(e); + } else { + return Touchable.Mixin.touchableHandleResponderTerminationRequest.call(this, e); + } + }, + + touchableHandleResponderGrant: function (e) { + if (this.props.onResponderGrant) { + return this.props.onResponderGrant(e); + } else { + return Touchable.Mixin.touchableHandleResponderGrant.call(this, e); + } + }, + + touchableHandleResponderMove: function (e) { + if (this.props.onResponderMove) { + return this.props.onResponderMove(e); + } else { + return Touchable.Mixin.touchableHandleResponderMove.call(this, e); + } + }, + + touchableHandleResponderRelease: function (e) { + if (this.props.onResponderRelease) { + return this.props.onResponderRelease(e); + } else { + return Touchable.Mixin.touchableHandleResponderRelease.call(this, e); + } + }, + + touchableHandleResponderTerminate: function (e) { + if (this.props.onResponderTerminate) { + return this.props.onResponderTerminate(e); + } else { + return Touchable.Mixin.touchableHandleResponderTerminate.call(this, e); + } + }, + touchableHandlePress: function(e) { this.props.onPress && this.props.onPress(e); }, diff --git a/lib/extract/extractResponder.js b/lib/extract/extractResponder.js index dada41c9..06a52608 100644 --- a/lib/extract/extractResponder.js +++ b/lib/extract/extractResponder.js @@ -1,19 +1,26 @@ -import {responderProps} from '../props'; +import {responderProps, touchableProps} from '../props'; import _ from 'lodash'; export default function (props) { + let responsible; let touchable; return _.reduce(props, (prev, value, key) => { - if (value && responderProps[key]) { + if (value && (responderProps[key] || touchableProps[key])) { prev[key] = value; - - if (!touchable) { + if (!responsible) { + responsible = true; + prev.responsible = true; + } + if (!touchable && touchableProps[key]) { touchable = true; prev.touchable = true; } } return prev; - }, {}); + }, { + responsible: false, + touchable: false + }); } diff --git a/lib/props.js b/lib/props.js index 2bc66c9c..03826127 100644 --- a/lib/props.js +++ b/lib/props.js @@ -3,7 +3,6 @@ import {PanResponder} from 'react-native'; const numberProp = PropTypes.oneOfType([PropTypes.string, PropTypes.number]); - const touchableProps = { disabled: PropTypes.bool, onPress: PropTypes.func, @@ -18,7 +17,7 @@ const touchableProps = { const touchablePropsKeys = Object.keys(touchableProps); const responderPropsKeys = [ - ...Object.keys(PanResponder.create({onStartShouldSetPanResponder: () => {}}).panHandlers), + ...Object.keys(PanResponder.create({}).panHandlers), 'pointerEvents' ];