2024-03-16 14:11:43 +08:00

132 lines
5.2 KiB
JavaScript

import React, { Component } from 'react';
import { StyleSheet, View, PanResponder } from 'react-native';
import { Icon } from '../Icon';
import styles from './styles';
import variables from '../../common/styles/variables';
const rateStyles = StyleSheet.create(styles);
export class Rate extends Component {
constructor(props) {
super(props);
this.panResponder = null;
this.containerView = null;
this.createPanResponder();
}
validateProps(props) {
const { value } = props;
let tmpValue = value == null ? 0 : value;
tmpValue = Number(tmpValue);
if (isNaN(tmpValue)) {
throw Error('Rate 组件请提供有效的 value 参数');
}
const integer = parseInt(tmpValue, 10);
if (tmpValue - integer !== 0 && tmpValue - integer !== 0.5) {
throw Error('Rate 组件请提供有效的 value 参数');
}
}
render() {
this.validateProps(this.props);
return (React.createElement(View, { ref: c => { this.containerView = c; }, style: [rateStyles.wrapper, this.props.style], collapsable: false },
React.createElement(View, Object.assign({ collapsable: false, style: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, zIndex: 1 } }, this.panResponder.panHandlers)),
this.renderIcons(this.props.value)));
}
renderIcons(value) {
const { icons: { half, full, empty }, total, iconSpace, iconSize, iconColor } = this.props;
const ret = [];
for (let i = 0; i < total; i++) {
const marginRight = i === total - 1 ? 0 : iconSpace;
if (half &&
value > i &&
value < i + 1) {
const tmpProps = { ...half.props, key: i, style: [{ marginRight }, half.props.style] };
if (half && half.type && half.type.displayName === 'Icon') {
tmpProps.size = iconSize;
tmpProps.tintColor = iconColor;
}
ret.push(React.cloneElement(half, tmpProps));
}
else if (value >= i + 1) {
const tmpProps = { ...full.props, key: i, style: [{ marginRight }, full.props.style] };
if (full && full.type && full.type.displayName === 'Icon') {
tmpProps.size = iconSize;
tmpProps.tintColor = iconColor;
}
ret.push(React.cloneElement(full, tmpProps));
}
else {
const tmpProps = { ...empty.props, key: i, style: [{ marginRight }, empty.props.style] };
if (empty && empty.type && empty.type.displayName === 'Icon') {
tmpProps.size = iconSize;
tmpProps.tintColor = iconColor;
}
ret.push(React.cloneElement(empty, tmpProps));
}
}
return ret;
}
getValue(pageX) {
const p = new Promise((resolve) => {
this.containerView && this.containerView.measure((ox, oy, width, height, px, py) => {
resolve(px);
});
});
return p.then((containerViewX) => {
const { iconSize, iconSpace, total, enableHalf } = this.props;
const locationX = pageX - containerViewX;
// console.log(pageX, containerViewX)
if (locationX <= 0) {
return 0;
}
const unitWidth = iconSize + iconSpace;
let value = Math.floor(locationX / unitWidth);
if (value >= total) {
return total;
}
const rest = locationX - unitWidth * value;
if (rest > 0 && rest < (iconSize / 2)) {
if (!enableHalf) {
value = value + 1;
}
else {
value = value + 0.5;
}
}
if (rest > (iconSize / 2)) {
value = value + 1;
}
return value;
});
}
handleChange(value) {
this.props.onChange && this.props.onChange(value);
}
createPanResponder() {
this.panResponder = PanResponder.create({
onStartShouldSetPanResponder: () => true,
onPanResponderGrant: (event, gesture) => {
this.getValue(event.nativeEvent.pageX).then((value) => {
this.handleChange(value);
});
},
onPanResponderMove: (event, gesture) => {
this.getValue(event.nativeEvent.pageX).then((value) => {
this.handleChange(value);
});
},
onPanResponderRelease: event => {
},
});
}
}
Rate.defaultProps = {
total: 5,
icons: {
empty: React.createElement(Icon, { source: require(`../../common/images/icons/star-o.png`) }),
full: React.createElement(Icon, { source: require(`../../common/images/icons/star.png`) }),
half: React.createElement(Icon, { source: require(`../../common/images/icons/star-half-o.png`) })
},
iconSize: 20,
iconSpace: 4,
enableHalf: true,
iconColor: variables.mtdBrandPrimaryDark
};
//# sourceMappingURL=index.js.map