add touchable support for shape elements

This commit is contained in:
Horcrux
2016-06-09 23:30:10 +08:00
parent 16b4f741f5
commit 7307715712
12 changed files with 123 additions and 67 deletions
+1 -2
View File
@@ -568,8 +568,7 @@ npm install
1. add native method for elements 1. add native method for elements
2. more Text features support 2. more Text features support
3. Pattern element 3. Pattern element
4. implement touchable elements 4. implement Animated elements
5. implement Animated elements
#### Thanks: #### Thanks:
-18
View File
@@ -4,11 +4,9 @@ import createNativeComponent from '../lib/createNativeComponent';
import mergeContext from '../lib/mergeContext'; import mergeContext from '../lib/mergeContext';
import {circleProps, pathProps, fillProps, strokeProps, numberProp} from '../lib/props'; import {circleProps, pathProps, fillProps, strokeProps, numberProp} from '../lib/props';
class Circle extends Component{
static displayName = 'Circle'; static displayName = 'Circle';
static propTypes = { static propTypes = {
...pathProps, ...pathProps,
...circleProps
}; };
static contextTypes = { static contextTypes = {
@@ -19,28 +17,12 @@ class Circle extends Component{
svgId: numberProp svgId: numberProp
}; };
//constructor() {
// super(...arguments);
// _.forEach(SvgTouchableMixin, (method, key) => {
// this[key] = method.bind(this);
// });
//
// this.state = this.touchableGetInitialState();
//};
render() { render() {
let props = mergeContext(this.props, this.context); let props = mergeContext(this.props, this.context);
return <RNSVGCircle return <RNSVGCircle
{...extractProps(props)}
cx={props.cx.toString()} cx={props.cx.toString()}
cy={props.cy.toString()} cy={props.cy.toString()}
r={props.r.toString()} r={props.r.toString()}
//onStartShouldSetResponder={this.touchableHandleStartShouldSetResponder}
//onResponderTerminationRequest={this.touchableHandleResponderTerminationRequest}
//onResponderGrant={this.touchableHandleResponderGrant}
//onResponderMove={this.touchableHandleResponderMove}
//onResponderRelease={this.touchableHandleResponderRelease}
//onResponderTerminate={this.touchableHandleResponderTerminate}
/>; />;
} }
} }
+4 -4
View File
@@ -1,11 +1,11 @@
import React, {PropTypes, Component} from 'react'; import React, {PropTypes} from 'react';
import extractProps from '../lib/extract/extractProps';
import createNativeComponent from '../lib/createNativeComponent'; import createNativeComponent from '../lib/createNativeComponent';
import mergeContext from '../lib/mergeContext'; import mergeContext from '../lib/mergeContext';
import Shape from './Shape';
import {ellipseProps, pathProps, fillProps, strokeProps, numberProp} from '../lib/props'; import {ellipseProps, pathProps, fillProps, strokeProps, numberProp} from '../lib/props';
class Ellipse extends Component{ class Ellipse extends Shape{
static displayName = 'Ellipse'; static displayName = 'Ellipse';
static propTypes = { static propTypes = {
...pathProps, ...pathProps,
@@ -23,7 +23,7 @@ class Ellipse extends Component{
render() { render() {
let props = mergeContext(this.props, this.context); let props = mergeContext(this.props, this.context);
return <RNSVGEllipse return <RNSVGEllipse
{...extractProps(props)} {...this.extractProps(props)}
cx={props.cx.toString()} cx={props.cx.toString()}
cy={props.cy.toString()} cy={props.cy.toString()}
rx={props.rx.toString()} rx={props.rx.toString()}
+4 -4
View File
@@ -1,11 +1,11 @@
import React, {Component, PropTypes} from 'react'; import React, {PropTypes} from 'react';
import extractProps from '../lib/extract/extractProps';
import createNativeComponent from '../lib/createNativeComponent'; import createNativeComponent from '../lib/createNativeComponent';
import {numberProp} from '../lib/props'; import {numberProp} from '../lib/props';
import Shape from './Shape';
import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource'; import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource';
class Image extends Component{ class Image extends Shape {
static displayName = 'Image'; static displayName = 'Image';
static propTypes = { static propTypes = {
x: numberProp, x: numberProp,
@@ -20,7 +20,7 @@ class Image extends Component{
render() { render() {
let {props} = this; let {props} = this;
return <RNSVGImage return <RNSVGImage
{...extractProps(props, {transform: true, responder: true})} {...this.extractProps(props, {transform: true, responder: true})}
x={props.x.toString()} x={props.x.toString()}
y={props.y.toString()} y={props.y.toString()}
width={props.width.toString()} width={props.width.toString()}
+4 -4
View File
@@ -1,10 +1,10 @@
import React, {PropTypes, Component} from 'react'; import React, {PropTypes} from 'react';
import extractProps from '../lib/extract/extractProps';
import createNativeComponent from '../lib/createNativeComponent'; import createNativeComponent from '../lib/createNativeComponent';
import mergeContext from '../lib/mergeContext'; import mergeContext from '../lib/mergeContext';
import Shape from './Shape';
import {lineProps, pathProps, fillProps, strokeProps, numberProp} from '../lib/props'; import {lineProps, pathProps, fillProps, strokeProps, numberProp} from '../lib/props';
class Line extends Component{ class Line extends Shape {
static displayName = 'Line'; static displayName = 'Line';
static propTypes = { static propTypes = {
...pathProps, ...pathProps,
@@ -22,7 +22,7 @@ class Line extends Component{
render() { render() {
let props = mergeContext(this.props, this.context); let props = mergeContext(this.props, this.context);
return <RNSVGLine return <RNSVGLine
{...extractProps(props)} {...this.extractProps(props)}
x1={props.x1.toString()} x1={props.x1.toString()}
y1={props.y1.toString()} y1={props.y1.toString()}
x2={props.x2.toString()} x2={props.x2.toString()}
+6 -13
View File
@@ -1,12 +1,12 @@
import React, {Component, PropTypes} from 'react'; import React, {PropTypes} from 'react';
import _ from 'lodash';
import Defs from './Defs'; import Defs from './Defs';
import extractProps from '../lib/extract/extractProps';
import SerializablePath from '../lib/SerializablePath'; import SerializablePath from '../lib/SerializablePath';
import createNativeComponent from '../lib/createNativeComponent'; import createNativeComponent from '../lib/createNativeComponent';
import mergeContext from '../lib/mergeContext';
import Shape from './Shape';
import {pathProps, numberProp} from '../lib/props'; import {pathProps, numberProp} from '../lib/props';
class Path extends Component{ class Path extends Shape {
static displayName = 'Path'; static displayName = 'Path';
static propTypes = { static propTypes = {
@@ -30,13 +30,7 @@ class Path extends Component{
}; };
render() { render() {
let {props} = this; let props = mergeContext(this.props, this.context);
if (this.context.isInGroup) {
props = _.defaults(this.context, props, {
isInGroup: null
});
}
if (props.id) { if (props.id) {
return <Defs.Item return <Defs.Item
@@ -49,10 +43,9 @@ class Path extends Component{
} }
let d = new SerializablePath(props.d).toJSON(); let d = new SerializablePath(props.d).toJSON();
return ( return (
<RNSVGPath <RNSVGPath
{...extractProps(props)} {...this.extractProps(props)}
d={d} d={d}
/> />
); );
+4 -4
View File
@@ -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 './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 createNativeComponent from '../lib/createNativeComponent';
import mergeContext from '../lib/mergeContext'; import mergeContext from '../lib/mergeContext';
import {rectProps, pathProps, fillProps, strokeProps, numberProp} from '../lib/props'; 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 displayName = 'Rect';
static propTypes = { static propTypes = {
...pathProps, ...pathProps,
@@ -24,7 +24,7 @@ class Rect extends Component{
let props = mergeContext(this.props, this.context); let props = mergeContext(this.props, this.context);
return <RNSVGRect return <RNSVGRect
{...extractProps({ {...this.extractProps({
...props, ...props,
x: null, x: null,
y: null y: null
+32
View File
@@ -0,0 +1,32 @@
import {Component} from 'react';
import extractProps from '../lib/extract/extractProps';
import SvgTouchableMixin from '../lib/SvgTouchableMixin';
import _ from 'lodash';
class Shape extends Component {
constructor() {
super(...arguments);
_.forEach(SvgTouchableMixin, (method, key) => {
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;
+5 -11
View File
@@ -1,13 +1,13 @@
import React, {Component, PropTypes} from 'react'; import React, {PropTypes} from 'react';
import createNativeComponent from '../lib/createNativeComponent'; import createNativeComponent from '../lib/createNativeComponent';
import Defs from './Defs'; import Defs from './Defs';
import _ from 'lodash';
import extractProps from '../lib/extract/extractProps'; import extractProps from '../lib/extract/extractProps';
import extractText from '../lib/extract/extractText'; import extractText from '../lib/extract/extractText';
import mergeContext from '../lib/mergeContext';
import {numberProp, textProps, fillProps, strokeProps, pathProps} from '../lib/props'; import {numberProp, textProps, fillProps, strokeProps, pathProps} from '../lib/props';
import Shape from './Shape';
class Text extends Shape {
class Text extends Component{
static displayName = 'Text'; static displayName = 'Text';
static propTypes = { static propTypes = {
dx: numberProp, dx: numberProp,
@@ -27,13 +27,7 @@ class Text extends Component{
}; };
render() { render() {
let {props} = this; let props = mergeContext(this.props, this.context);
if (this.context.isInGroup) {
props = _.defaults(this.context, props, {
isInGroup: null
});
}
let x = 0; let x = 0;
if (props.x) { if (props.x) {
+50
View File
@@ -3,6 +3,56 @@ const PRESS_RETENTION_OFFSET = {top: 20, left: 20, right: 20, bottom: 30};
export default { export default {
...Touchable.Mixin, ...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) { touchableHandlePress: function(e) {
this.props.onPress && this.props.onPress(e); this.props.onPress && this.props.onPress(e);
}, },
+12 -5
View File
@@ -1,19 +1,26 @@
import {responderProps} from '../props'; import {responderProps, touchableProps} from '../props';
import _ from 'lodash'; import _ from 'lodash';
export default function (props) { export default function (props) {
let responsible;
let touchable; let touchable;
return _.reduce(props, (prev, value, key) => { return _.reduce(props, (prev, value, key) => {
if (value && responderProps[key]) { if (value && (responderProps[key] || touchableProps[key])) {
prev[key] = value; prev[key] = value;
if (!responsible) {
if (!touchable) { responsible = true;
prev.responsible = true;
}
if (!touchable && touchableProps[key]) {
touchable = true; touchable = true;
prev.touchable = true; prev.touchable = true;
} }
} }
return prev; return prev;
}, {}); }, {
responsible: false,
touchable: false
});
} }
+1 -2
View File
@@ -3,7 +3,6 @@ import {PanResponder} from 'react-native';
const numberProp = PropTypes.oneOfType([PropTypes.string, PropTypes.number]); const numberProp = PropTypes.oneOfType([PropTypes.string, PropTypes.number]);
const touchableProps = { const touchableProps = {
disabled: PropTypes.bool, disabled: PropTypes.bool,
onPress: PropTypes.func, onPress: PropTypes.func,
@@ -18,7 +17,7 @@ const touchableProps = {
const touchablePropsKeys = Object.keys(touchableProps); const touchablePropsKeys = Object.keys(touchableProps);
const responderPropsKeys = [ const responderPropsKeys = [
...Object.keys(PanResponder.create({onStartShouldSetPanResponder: () => {}}).panHandlers), ...Object.keys(PanResponder.create({}).panHandlers),
'pointerEvents' 'pointerEvents'
]; ];