diff --git a/js/project/Fireworks.js b/js/project/Fireworks.js
new file mode 100644
index 0000000..ad163ed
--- /dev/null
+++ b/js/project/Fireworks.js
@@ -0,0 +1,191 @@
+'use strict'
+import React,{
+ StyleSheet,
+ View,
+ Animated,
+ Component
+} from 'react-native';
+import Dimensions from 'Dimensions';
+
+var screenWidth = Dimensions.get('window').width;
+var screenHeight = Dimensions.get('window').height;
+
+var COLORS = ['#FF5252', '#FF4081', '#E040FB', '#7C4DFF', '#448AFF', '#40C4FF', '#69F0AE', '#FFFF00', '#FFD740', '#FF6E40'];
+var PARTICLE_COUNT = 12;
+
+class SingleFirework extends Component {
+ constructor(props) {
+ super(props);
+ this._mounted = false;
+ this.riseAnim = new Animated.Value(0);
+ this.riseOpacity = new Animated.Value(1);
+ this.particles = [];
+ for (var i = 0; i < PARTICLE_COUNT; i++) {
+ this.particles.push({
+ x: new Animated.Value(0),
+ y: new Animated.Value(0),
+ opacity: new Animated.Value(0),
+ });
+ }
+ this.state = {
+ color: COLORS[Math.floor(Math.random() * COLORS.length)],
+ originX: Math.random() * (screenWidth - 60) + 30,
+ targetY: -(Math.random() * screenHeight * 0.3 + screenHeight * 0.15),
+ };
+ }
+
+ componentDidMount() {
+ this._mounted = true;
+ this._delayTimer = setTimeout(() => {
+ if (this._mounted) {
+ this._startAnimation();
+ }
+ }, this.props.delay || 0);
+ }
+
+ componentWillUnmount() {
+ this._mounted = false;
+ if (this._delayTimer) {
+ clearTimeout(this._delayTimer);
+ }
+ if (this._restartTimer) {
+ clearTimeout(this._restartTimer);
+ }
+ }
+
+ _resetValues() {
+ this.riseAnim.setValue(0);
+ this.riseOpacity.setValue(1);
+ this.particles.forEach(function(p) {
+ p.x.setValue(0);
+ p.y.setValue(0);
+ p.opacity.setValue(0);
+ });
+ }
+
+ _startAnimation() {
+ if (!this._mounted) return;
+
+ this._resetValues();
+
+ var newColor = COLORS[Math.floor(Math.random() * COLORS.length)];
+ var newOriginX = Math.random() * (screenWidth - 60) + 30;
+ var newTargetY = -(Math.random() * screenHeight * 0.3 + screenHeight * 0.15);
+ this.setState({color: newColor, originX: newOriginX, targetY: newTargetY});
+
+ var riseDuration = 800 + Math.random() * 400;
+
+ var riseAnimation = Animated.parallel([
+ Animated.timing(this.riseAnim, {
+ toValue: 1,
+ duration: riseDuration,
+ }),
+ Animated.timing(this.riseOpacity, {
+ toValue: 0,
+ duration: riseDuration,
+ }),
+ ]);
+
+ var explodeAnimations = this.particles.map(function(p, i) {
+ var angle = (i / PARTICLE_COUNT) * Math.PI * 2;
+ var distance = 30 + Math.random() * 60;
+ var dx = Math.cos(angle) * distance;
+ var dy = Math.sin(angle) * distance;
+
+ return Animated.parallel([
+ Animated.timing(p.x, {toValue: dx, duration: 700}),
+ Animated.timing(p.y, {toValue: dy + 20, duration: 700}),
+ Animated.sequence([
+ Animated.timing(p.opacity, {toValue: 1, duration: 50}),
+ Animated.timing(p.opacity, {toValue: 0, duration: 650}),
+ ]),
+ ]);
+ });
+
+ var self = this;
+ Animated.sequence([
+ riseAnimation,
+ Animated.parallel(explodeAnimations),
+ ]).start(function() {
+ if (self._mounted) {
+ self._restartTimer = setTimeout(function() {
+ self._startAnimation();
+ }, Math.random() * 1000 + 500);
+ }
+ });
+ }
+
+ render() {
+ var color = this.state.color;
+ var originX = this.state.originX;
+ var targetY = this.state.targetY;
+
+ var riseY = this.riseAnim.interpolate({
+ inputRange: [0, 1],
+ outputRange: [0, targetY],
+ });
+
+ var particleViews = this.particles.map(function(p, i) {
+ return (
+
+ );
+ });
+
+ return (
+
+
+
+ {particleViews}
+
+
+ );
+ }
+}
+
+export default class Fireworks extends Component {
+ render() {
+ return (
+
+
+
+
+
+
+
+ );
+ }
+}
+
+var styles = StyleSheet.create({
+ container: {
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ right: 0,
+ bottom: 0,
+ backgroundColor: 'transparent',
+ },
+});
diff --git a/js/project/MyIndex.js b/js/project/MyIndex.js
index c9b371a..269cf77 100644
--- a/js/project/MyIndex.js
+++ b/js/project/MyIndex.js
@@ -8,22 +8,25 @@ import React,{
TouchableHighlight,
TouchableOpacity,
NavigatorIOS,
- Component
+ Component,
+ Alert,
+ AppState
} from 'react-native';
import Swiper from 'react-native-swiper';
import Dimensions from 'Dimensions';
import ServiceType from './serviceType';
import Home from './Home.js';
+import Fireworks from './Fireworks.js';
var width = Dimensions.get('window').width;
export default class MyIndex extends Component{
constructor(props){
super(props);
this.state = {
-
imageurls:[]
}
-
+ this._lastAlertDate = null;
+ this._handleAppStateChange = this._handleAppStateChange.bind(this);
}
banner(urls){
@@ -44,7 +47,35 @@ export default class MyIndex extends Component{
});
}
+ _checkDailyReminder(){
+ var now = new Date();
+ var hour = now.getHours();
+ var todayStr = now.getFullYear() + '-' + (now.getMonth() + 1) + '-' + now.getDate();
+ if (hour === 8 && this._lastAlertDate !== todayStr) {
+ this._lastAlertDate = todayStr;
+ Alert.alert(
+ '新品推荐',
+ '今日有新产品上线,欢迎前往线下门店选购!',
+ [{text: '知道了'}]
+ );
+ }
+ }
+ _handleAppStateChange(appState){
+ if (appState === 'active') {
+ this._checkDailyReminder();
+ }
+ }
componentDidMount(){
+ Alert.alert(
+ '温馨提示',
+ '本网站正在升级中,部分功能可能暂时无法使用,敬请谅解!',
+ [{text: '我知道了'}]
+ );
+ this._checkDailyReminder();
+ this._reminderTimer = setInterval(() => {
+ this._checkDailyReminder();
+ }, 60000);
+ AppState.addEventListener('change', this._handleAppStateChange);
fetch('http://api.gujia007.com/v1/flash-data')
.then((res) => {
@@ -62,6 +93,12 @@ export default class MyIndex extends Component{
}
+ componentWillUnmount(){
+ if (this._reminderTimer) {
+ clearInterval(this._reminderTimer);
+ }
+ AppState.removeEventListener('change', this._handleAppStateChange);
+ }
render() {
let urls = this.state.imageurls;
@@ -94,6 +131,7 @@ export default class MyIndex extends Component{
+
);