Closed craigcosmo closed 1 year ago
You can set initialAnimation to false to prevent the first animation, and only subsequent animations will run which I believe is what you want.
I set to false. then I got this. watch the bottom of the screen
it's a bit weird
Do you continuously update the component? If so, can you try slowing down the update rates and see if it still persists?
in progressive jackpot, it got updated continuously
I think this is might happen if the next update happens before the previous update has finished. Can you try slowing down the update rate, so that each update only occurs after previous animation has completed, and see if this issue still persists?
i slowed it down. quite closed.
But doesn't look right when it transition from something like 19 to 20. The last digit (9) had to go all the way from 9-8-7-6-5-4-2-1 to become 0. the last digit should just be 9 then 0.
This is the current implementation. Unfortunately, I'm not actively working on this repo, but If you want, you can create PR with a fix and I'll be happy to merge it :)
I faster the animation, the effect of 9 to 0 is unnoticeable. Now I need to put a thousand separator, any suggestion on how to do that?
Yes, you can add comma to the range prop ("9876543210,") and pass the text formatted ("1,234").
somehow it doesnt show the comma
Can u post your code?
yes, can
export default class SlotMachine extends Component {
static get defaultProps() {
return {
text: 0,
width: 37,
height: 50,
padding: 4,
duration: 110,
delay: 0,
slotInterval: 500,
defaultChar: '0',
range: '9876543210,',
initialAnimation: false,
styles: {},
renderTextContent: (currentChar) => currentChar,
useNativeDriver: false,
};
}
constructor(props) {
super(props);
this.renderSlot = this.renderSlot.bind(this);
this.startInitialAnimation = this.startInitialAnimation.bind(this);
this.renderContent = this.renderContent.bind(this);
this.text = props.text;
let values;
if (props.initialAnimation) {
values = this.getInitialSlotsValues(props);
} else {
values = this.getAlignedValues(props).map(val => new Animated.Value(val));
}
this.state = {values, initialAnimation: false};
}
componentDidMount() {
const {delay, initialAnimation} = this.props;
if (!initialAnimation) {
return;
}
setTimeout(this.startInitialAnimation, delay);
}
componentWillReceiveProps(newProps) {
if (newProps.text === this.text) {
return;
}
this.text = newProps.text;
const {range, duration, useNativeDriver} = newProps;
const easing = Easing.inOut(Easing.ease);
const paddedStr = this.getPaddedString(newProps);
const newValues = this.getAdjustedAnimationValues(newProps);
this.setState({values: newValues}, () => {
const newAnimations = paddedStr.split('').map((char, i) => {
const index = range.indexOf(char);
const animationValue = -1 * (index) * newProps.height;
return Animated.timing(this.state.values[i], {toValue: animationValue, duration, easing, useNativeDriver: useNativeDriver});
});
Animated.parallel(newAnimations).start();
});
}
getAdjustedAnimationValues(props) {
const {values} = this.state;
const paddedStr = this.getPaddedString(props);
let neededValues = paddedStr.length - values.length;
if (neededValues <= 0) {
return values;
}
const defaultIndex = props.range.indexOf(props.defaultChar);
const defaultPosition = this.getPosition(defaultIndex, props);
const newValues = [...values];
while (neededValues--) {
newValues.unshift(new Animated.Value(defaultPosition));
}
return newValues;
}
getPosition(index, props = this.props) {
const position = -1 * (index) * props.height;
return position;
}
getAlignedValues(props) {
const paddedStr = this.getPaddedString();
const {range} = props;
const values = paddedStr.split('').map((char) => {
const index = range.indexOf(char);
const animationValue = this.getPosition(index, props);
return animationValue;
});
return values;
}
getInitialSlotsValues(props) {
const values = [];
const strNum = String(this.text);
const animationValue = this.getPosition(props.range.length - 1, props);
let slotCount = Math.max(props.padding, strNum.length);
while (slotCount--) {
values.push(new Animated.Value(animationValue));
}
return values;
}
getPaddedString(props = this.props) {
const {padding, defaultChar} = props;
let paddedText = String(this.text);
let neededPadding = Math.max(0, padding - paddedText.length);
while ((neededPadding--) > 0) {
paddedText = `${defaultChar}${paddedText}`;
}
return paddedText;
}
generateSlots() {
const paddedStr = this.getPaddedString();
const elements = paddedStr.split('').map(this.renderSlot);
return elements;
}
startInitialAnimation() {
const {values} = this.state;
const {duration, slotInterval, useNativeDriver} = this.props;
const easing = Easing.inOut(Easing.ease);
const animations = values.map((value, i) => {
const animationDuration = duration - (values.length - 1 - i) * slotInterval;
return Animated.timing(value, {toValue: 0, duration: animationDuration, easing, useNativeDriver: useNativeDriver});
});
Animated.parallel(animations).start(() => {
const newValues = this.getAlignedValues(this.props);
newValues.forEach((value, i) => values[i].setValue(value));
this.setState({initialAnimation: false});
});
this.setState({initialAnimation: true});
}
spinTo(value) {
this.text = value;
const values = this.getInitialSlotsValues(this.props);
this.setState({values}, () => this.startInitialAnimation());
}
renderContent(currentChar, i, range) {
const {styles: overrideStyles, renderTextContent} = this.props;
const textContent = renderTextContent(currentChar, i, range);
return (<Text style={[styles.text, overrideStyles.text]}>{textContent}</Text>);
}
renderSlot(charToShow, position) {
const {range, styles: overrideStyles, height, width, renderContent = this.renderContent} = this.props;
const {initialAnimation, values} = this.state;
const charToShowIndex = range.indexOf(charToShow);
const slots = range.split('').map((num, i) => {
let currentChar = num;
if (initialAnimation) {
const currentIndex = (i + charToShowIndex) % range.length;
currentChar = range[currentIndex];
}
const content = renderContent(currentChar, i, range);
return (
<Animated.View
key={i}
style={[styles.slotInner, {height}, overrideStyles.slotInner, {transform: [{translateY: values[position]}]} ]}
>
{content}
</Animated.View>
);
});
return (
<View key={position} style={[styles.slotWrapper, {height, width}, overrideStyles.slotWrapper]}>
{slots}
<View style={[styles.innerBorder, overrideStyles.innerBorder]} />
<View style={[styles.outerBorder, overrideStyles.outerBorder]} />
</View>
);
}
render() {
const slots = this.generateSlots();
return (
<View style={[styles.container, this.props.styles.container]}>
{slots}
</View>
);
}
}
Isn't this my code?
What I mean is, can you show how you use the component?
<SlotMachine range="9876543210," text="1,234" />
should do the trick of showing comma
sorry, did as you said, it works perfectly.
Just one more thing, I want to change the width, the default is 50, I want to chage it depend on the number of characters in the text.
how should I access the width property within a function?
setSize(text){
if (text.length<6) {
// console.log('text here')
styles.text = {
...styles.text,
fontSize: 64
}
this.width = 88
}
}
componentDidMount() {
const {delay, initialAnimation} = this.props;
if (!initialAnimation) {
return;
}
setTimeout(this.startInitialAnimation, delay);
}
constructor(props) {
this.text = props.text;
this.setSize(this.text)
}
With that code above, I can change the the font size, but not the width. Any suggestion?
instead of random jackpot. Can this be configured to be progessive?
Like I got the number 1,234 the next number will be 1,235 the next one will be 1,235
possible?