Error on bodymovin animation in react native? - json

I am using sample.json image file which is for bodymovin animation in my page through Lottie for React Native.
I am getting the image but the image is not fully retrieved, some parts of the image is missing and also in some side of the image, green color pasted on the image.
But i checked the sample.json through online json image viewr. But there is no issue with the image from the source
here is issue https://i.stack.imgur.com/yFZfg.jpg
here is original image https://i.stack.imgur.com/4sBzg.jpg
so here is my code
import React from 'react';
import { Animated, Easing, easing } from 'react-native';
import Animation from 'lottie-react-native';
export default class BasicExample extends React.Component {
constructor(props) {
super(props);
this.state = {
progress: new Animated.Value(0.5),
};
}
componentDidMount() {
this.startAnimation();
}
startAnimation() {
Animated.timing(
this.state.progress,
{
toValue: 1,
from: 0,
to: 1,
duration: 5000,
}
)
.start(() => {
// Restart at end
this.state.progress.setValue(0);
this.startAnimation();
});
}
render() {
const easing = Easing.inOut(Easing.quad);
const { Animate } = this.props;
return (
<Animation
style={{
width: 300,
height: 300,
}}
source={this.props.Animate}
progress={this.state.progress}
/>
);
}
}
i installed lottie npm also.
so this is my issue please help me to overcome this
Thanks in advance

UPDATE: Now that I looked your code closer I found out that you're animating by changing the value of progress prop. That's not how to do it. You need to use ref for referring the animation to.
return (
<Animation
ref={(animation) => this.myAnimation = animation}
style={{
width: 300,
height: 300,
}}
source={this.props.Animate}
/>
);
And then:
componentDidMount() {
this.startAnimation();
}
startAnimation() {
this.myAnimation.play();
}
OLD ANSWER:
Your code seems perfectly legit and if you see an image, it proofs that you're doing it right.
I'd assume there's either something wrong with the JSON or then Lottie just interprets values wrong.
I've encountered small styling issues on Android devices, but not with iOS. And they're mostly related to alignment.
If you don't get any proper answers here in SO, I'd suggest you to file an issue to github (see this for instance: https://github.com/airbnb/lottie-react-native/issues/182)

Related

show legend by default on a kepler gl point map

I would like to export my point map done using kepler gl to an interactive html file. This interactive html file should have a legend (colour key) visible by default. What I mean is i shouldn't click on the show legend button to see the meaning of colours on the map - the show legend should be visible and fixed by default after exporting. Is this possible? Can anyone please guide me on how to achive this?
I am not sure about html exporting thing, and I am also not sure if you mean how to do it with the demo, basically using a front-end (GUI), or by the API components.
Since I made the legend open by default using react, I'll talk about it.
/* store.js */
// some of your import
import { createStore, applyMiddleware } from "redux";
import keplerGlReducer, { uiStateUpdaters } from 'kepler.gl/reducers';
import { taskMiddleware } from "react-palm/tasks";
// rest of them
const customizedKeplerGlReducer = keplerGlReducer
.initialState({
uiState: {
mapControls: {
...uiStateUpdaters.DEFAULT_MAP_CONTROLS,
mapLegend: {
show: true,
active: false
},
/* another map controls */
//toggle3d: {
// show: true
//},
}
}
});
export default createStore(customizedKeplerGlReducer, {}, applyMiddleware(taskMiddleware));
This way your legend will be open (clicked) by default, unless this is not what you asked for.
Full example by kepler.gl

React - is the following true about how html tags' attribute values change when a component is reexecuted?

Can I verify my observation (based on the code below)?:
Class values of an element added in the html markup of a component don't neccessarily 'persist' - when the component is re-executed (perhaps as the result of a change in state), the class value from the last execution can disappear.
However, class values written via vanilla JS persist.
I'm always looking for best practices in code to avoid problems down the line. Is this code a reasonable way to add a class to a tag in React?
sandbox: https://codesandbox.io/s/purple-moon-epmmu?file=/src/styles.css:59-126
import "./styles.css";
import React, { useState, useEffect } from "react";
export default function App() {
let [color, setColor] = useState(false);
function updateColor() {
if (color) {
setColor("");
} else {
setColor("red");
}
}
useEffect(() => {
document.querySelector(`div`).classList.add(`green-text`);
}, []);
return (
<>
<div className={color ? "red" : null} onClick={updateColor}>
Click to add/remove red class
</div>
</>
);
}
.red {
background-color: red;
}
.green-text {
color: green;
}
I would highly recommend you to try out the classnames library to inject class attribute value dynamically. It's a very elegant library which helps avoid complicated code pertaining to css updates, when the codebase gets bigger.
I have tweaked your example, including some naming changes, removing unwanted code and added classnames. Also you can pass in any other class names from other components as such, and render it dynamically too. This is how you'd do it:
import "./styles.css";
import React, { useState, useEffect } from "react";
import classnames from "classnames"
export default function App(props) {
const [hasRed, setHasRed] = useState(false);
return (
<div className={classnames(
["green-text", props.otherClassNamesIfAny],
{
"red": hasRed,
}
)}
onClick={setHasRed(!hasRed)}
>
Click to add/remove red class
</div>
);
};

How to reserve space for responsive img (stop blocks jumping down)

How to solve a problem of jumping down blocks after image load if image should be responsive?
Codesandbox.
Info:
Image should shrink on window resize
Image max-width is it's own width
We don't know image size
JS can be used
Idea:
If it's not possible without any image size data, then can it be done only with image aspect ratio?
If you know image aspect ratio, you can calculate block height and put responsive image inside with some unused space (at least unused space will be not big on small window size).
Image loading:
Image loaded:
Html:
import React from "react";
import "./styles.css";
const img =
"https://s3.amazonaws.com/images.seroundtable.com/google-css-images-1515761601.jpg";
export default function App() {
return (
<div className="app">
<img alt="" src={img + `?${Date.now()}`} className="img" />
<h1>I always jump down :(</h1>
</div>
);
}
CSS:
.app {
box-sizing: border-box;
}
.img {
max-width: 100%;
}
h1 {
background-color: red;
}
AS #DBS sad, it seems that only solution is to wrap image in div block with calculated height based on window.width and aspect ratio (in my case i know it). If there is any better solutions, don't hesitate to answer.
Sandbox solution example.
import React from "react";
import "./styles.css";
import styled from "styled-components";
const aspectRatio = [1, 5];
const img =
"https://s3.amazonaws.com/images.seroundtable.com/google-css-images-1515761601.jpg";
export default function App() {
return (
<div className="app">
<StyledDiv>
<img alt="" src={img + `?${Date.now()}`} className="img" />
</StyledDiv>
<h1>I always jump down :(</h1>
</div>
);
}
const StyledDiv = styled.div`
height: calc(100vw / ${aspectRatio[1]});
overflow-y: hidden;
`;
As you've already determined, even when knowing the aspect ratio, we still have the problem of not knowing the width of the image, making the aspect ratio useless if we are to conform to your requirement Image max-width is it's own width.
What would work is a build time solution (if you know your image urls at build time). There are plenty of server side rendering options for react apps and I will not elaborate on them.
Instead there's a super rudimentary DIY approach.
Create a Node script to run on your server. It will build JSON file with image dimensions. Let's call it "buildImageDimensionData.js". It will output a JSON file imageDimensions.json.
var probe = require("probe-image-size"); // For getting image dimensions without downloading full image
const fs = require("fs"); // For writing our image dimensions to file
// Supply the image urls by hand, or build a webpack script to extract them etc...
const imageUrls = [
`http://localhost:5000/image1.jpg`,
`http://localhost:5000/image2.jpg`,
];
async function getImageDimensionsByUrl(urlList) {
const probePromises = urlList.map(async (imageUrl) => await probe(imageUrl));
let probedImagesData = [];
try {
probedImagesData = await Promise.all(probePromises);
} catch (error) {
// We are programming gods and there will be no error.
}
return probedImagesData.reduce((accumulator, imageData) => {
accumulator[imageData.url] = [imageData.width, imageData.height];
return accumulator;
}, {});
}
getImageDimensionsByUrl(imageUrls).then((dimensions) =>
fs.writeFileSync("imageDimensions.json", JSON.stringify(dimensions))
);
Run the script before build. For example, if you're using Create React App, in package.json:
...
"start": "buildImageDimensionData && react-scripts start",
"build": "buildImageDimensionData && react-scripts build",
...
In your react image component, import imageDimensions.json and use the data to set dimensions for image wrapper based on url of the image.
Note this is more for demonstraing how it could work and there will definitely be packages for doing this better.
Another, albeit poor option is of course just waiting for the images to load before rendering your other content so no jumps occur.
To ignore the jump down, you have to set margin of the next sibling to 0,
.app {
box-sizing: border-box;
}
.img {
max-width: 100%;
}
.app :nth-child(2) {
margin:0px
}

How to navigate in React-Native?

I am using ReactNavigation library in my react-native project and since 6 hours I am trying to navigate from one screen to others screen and have tried every possible way but I think I am not able to get the logic properly.
This is my project structure.
Here
The way I am doing it.
const AppStack = StackNavigator({ Main: Feeds });
const AuthStack = StackNavigator({ Launch: LaunchScreen, });
export default SwitchNavigator({
Auth: AuthStack,
App: AppStack
});
In my LaunchScreen.js
const SimpleTabs = TabNavigator(
{
Login: {
screen: Login,
path: ""
},
SignUp: {
screen: SignUp,
path: "doctor"
}
},
);
<SimpleTabs screenProps={{rootNavigation : this.props.navigation }}/>
But the problem is in my LaunchScreen Component there is a TabNavigator which contains my other two components Login.js and SignUp.js but the button in my Login.js doesn't navigate it to Feed.js.
When you click on the button this is performed.
signInAsync = async () => {
await AsyncStorage.setItem('userToken', 'abc');
this.props.navigation.navigate('Main');
console.log("AAAAAsSSS");
};
My LaunchScreen.js contains a TabNavigation which lets you slide between two components ie. Login.js and SignUp.js.
Now when you click on the Login button which is in Login.js component it will authenticate the user and will switch the entire LauchScreen.js component with the Feed.js component.
I am a noob to react-native.
You can use react-native-router-flux (npm install --save react-native-router-flux)
just make one Navigator.js file and define each page you wanted to navigate.
import React from 'react';
import { Router, Scene } from 'react-native-router-flux';
import LaunchScreen from '../components/LaunchScreen.js';
import Feed from '../components/Feed.js';
const Navigator = () => {
return (
<Router>
<Scene key="root">
<Scene key="lauchscreen" component={LaunchScreen} hideNavBar initial />
<Scene key="feedscreen" type="reset" hideNavBar component={Feed} />
</Scene>
</Router>
);
};
export default Navigator;
now in your App.js file add this:
import Navigator from './src/Navigator.js';
export default class App extends Component<Props> {
render() {
return (
<Navigator />
);
}
}
now in your login.js when you click on login button write this:
import { Actions } from 'react-native-router-flux';
onLoginClick() {
Actions.feedscreen();
}
Thats it.. happy coding.
If you want to navigate to Feeds.js then navigate as
this.props.navigation.navigate('App');
not as
this.props.navigation.navigate('Main');
because your
export default SwitchNavigator({
Auth: AuthStack,
App: AppStack // here is your stack of Main
});
refer example
I came across the same issue few months ago. Thank god you have spent just 6 hours, i almost spent around 4 days in finding a solution for it.
Coming to the issue, Please note that in react-navigation you can either navigate to siblings or children classes.
So here, You have a swtichNavigator which contain 2 stack navigators (say stack 1 and stack 2), stack1 has feeds and stack2 has a tab navigator with login and signup.
Now you want to navigate from login.js to feeds.js(say file name is feeds.js). As mentioned already you can not navigate back to parent or grandparent. Then how to solve this issue?
In react native you have the privilege to pass params (screenprops) from parent to children. Using this, you need to store this.props.navigation of launchScreen into a variable and pass it to tab/login (check the tree structure). Now in the login.js use this variable to navigate.
You are simply passing the navigating privilege from parent to children.
Editing here:
<InnerTab screenProps={{rootNavigation : this.props.navigation }} />
Here, InnerTab is the tab navigator.
export const InnerTab = TabNavigator({
login: {
screen: login,
},
},
signup: {
screen: signup,
},
},
},
in login class, use const { navigate } = this.props.screenProps.rootNavigation;
Now you can use variable navigate.
I know its little tricky to understand but i have tried and it works.
Write your Navigator.js file as below,
import React from 'react'
import { NavigationContainer, useNavigation } from '#react-navigation/native'
import { createStackNavigator } from '#react-navigation/stack'
const SwitchNavigatorStack = () => {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName='{nameofscreen}' screenOptions={screenOptions}>
<Stack.Screen name='{nameofscreen}' component={{nameofscreen}}/>
<Stack.Screen name='{nameofscreen}' component={{nameofscreen}}/>
<Stack.Screen name='{nameofscreen}' component={{nameofscreen}}/>
<Stack.Screen name='{nameofscreen}' component={{nameofscreen}}/>
</Stack.Navigator>
</NavigationContainer>
)
}
export default SwitchNavigatorStack
Once, you are done with that change your App.js file to,
import SignedInStack from './navigation'
import React from 'react'
export default function App() {
return <SwitchNavigatorStack/>
}
After this, you are done with setting your project for navigating. In all the components where you want to add navigation feature make sure you use the navigation.navigate() (or) navigation.push() method. Also make sure you hook navigation constant by import useNavigation library. For example,
const Login = () => {
const navigation = useNavigation()
< Button title = 'Login' onPress={() => navigation.navigate('{nameofscreen}')} />
}
with this code snippet you can implement navigation between screens using #react-navigation/native and #react-navigation/stack

ReactJS adding onClick handler into element given an HTML string

I'm given an HTML string from an API:
<div><h1>something</h1><img src="something" /></div>
I would like to add an onClick handler onto the img tag. I thought about using regex replace, but it's highly advised against.
I'm new to React... how would you go about solving this problem?
Any links or pointing into the right direction would be highly appreciated!
EDIT
Is there a way to add a listener to all anchor tags in a react friendly way? I'm thinking then I can just check the anchor tag's children, and if there's an image element, then I can run my code block.
I think a more idiomatic React way of doing this would be to refactor this into a component, replete with it's own onClick handler, and then insert your image URL via props. Something like
class MyImg extends React.Component {
onClick() {
// foo
}
render() {
return (
<div onClick={this.onClick}>
<h1>{this.props.foo}</h1>
<img src={this.props.imgSrc} />
</div>
);
}
}
Can you update your API to return JSON instead of HTML? JSON is easier to manipulate and you can create react elements on the fly, for example, let's assume your API returns this:
{
component: 'div',
children: [
{ component: 'h1', text: 'Something here' },
{ component: 'img', src: 'something.jpg' },
],
}
If you have that kind of response is very easy to create React elements at run time, you can also add events when creating these components, for example:
class DynamicContent extends PureComponent {
onImageClick = () => {
// Do something here!
console.log('Testing click!');
}
render() {
const children = response.children;
return React.createElement(response.component, null,
React.createElement(children[0].component, null, children[0].text),
React.createElement(children[1].component, {
...children[1],
onClick: this.onImageClick, // <-- Adds the click event
}),
);
}
}
You might want to create an utility that dynamically walks through the response object and creates all the components that you need.