RingBufferGeometry thetaLength animation with GSAP and react-three-fiber - three.js

I would like to animate my ringBufferGeometry like in example below, but I would like to use GSAP to animate this ringBufferGeometry for certain amount of time and I would like then to stop it when the thetaLength will equal to some value. Something like in example below but without the use of Math.sin().
three js RingBufferGeometry, update thetaLength
This is what I want to achieve(link below), but I want stop to animate when it reaches the full triangle form.
https://jsfiddle.net/02oyunbj/1/
My code
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
function Container(props) {
return <div style={{ position: 'absolute', inset: 0 }} {...props} />
}
ReactDOM.render(
<Container>
<App />
</Container>,
document.getElementById('root')
)
import { useRef, useEffect } from 'react'
import { Canvas } from '#react-three/fiber'
import { OrbitControls } from '#react-three/drei'
import * as THREE from 'three'
import gsap from 'gsap'
export default function App() {
return (
<Canvas camera={{ position: [0, 0, 15] }}>
<color attach="background" args={['black']} />
<OrbitControls />
<spotLight position={[15, 15, 15]} angle={0.3} color={'white'} />
<TriangleRing />
</Canvas>
)
}
const TriangleRing = () => {
const triangleRingRef = useRef()
const parametersObj = {
innerRadius: 4,
outerRadius: 8,
thetaSegments: 1,
phiSegments: 30,
thetaStart: 1.55,
thetaLength: 0,
}
const parameters = [
parametersObj.innerRadius,
parametersObj.outerRadius,
parametersObj.thetaSegments,
parametersObj.phiSegments,
parametersObj.thetaStart,
parametersObj.thetaLength,
]
useEffect(() => {
console.log(triangleRingRef.current)
const triangleGeometry = triangleRingRef.current.geometry
gsap.set(triangleGeometry, {
parameters: { ...parametersObj, thetaLength: 0 },
})
const tl = gsap.timeline({ defaults: { ease: 'power3.inOut' } })
tl.to(triangleGeometry, {
parameters: { ...parametersObj, thetaLength: 6.3 },
duration: 4,
})
})
return (
<mesh ref={triangleRingRef}>
<ringBufferGeometry args={parameters} name="TriangleRing" />
<meshToonMaterial side={THREE.DoubleSide} color={0xffffff} />
</mesh>
)
}
Link to sandbox:
https://codesandbox.io/s/affectionate-lichterman-edpfr?file=/src/App.jsx:0-1517

By default GSAP works in terms of seconds, not velocity or anything like that. So you'll need to calculate how long the tween(s) should run (by using the difference in value and the rate at which you want it to move) to get it to result in the end value that you need.
Without a minimal, complete, and verifiable example it's hard for us to help more at this point.

Related

React Native Expo (Image Picker) is not displaying the Images

Please help me out with this problem.
I can able to pick the image from my Local storage. In the Console also it is showing, But I cannot able to display it on the screen.
Here is my code.
import * as ImagePicker from "expo-image-picker";
import React, { useState } from "react";
import {
ActivityIndicator,
Button,
FlatList,
Image,
StyleSheet,
Text,
useWindowDimensions,
View
} from "react-native";
import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context";
export default function App() {
const [images, setImages] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const pickImages = async () => {
// No permissions request is necessary for launching the image library
setIsLoading(true);
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
// allowsEditing: true,
allowsMultipleSelection: true,
selectionLimit: 10,
aspect: [4, 3],
quality: 1,
});
setIsLoading(false);
console.log(result);
if (!result.canceled) {
setImages(result.uri ? [result.uri] : result.selected);
}
};
return (
<>
<FlatList
data={images}
renderItem={({ item }) => (
<Image
source={{ uri: item.uri }}
style={{ width: 100, height: 100 }}
/>
)}
keyExtractor={(item) => item.uri}
contentContainerStyle={{ marginVertical: 50, paddingBottom: 50 }}
ListHeaderComponent={
isLoading ? (
<View>
<Text
style={{ fontSize: 20, fontWeight: "bold", textAlign: "center" }}
>
Loading...
</Text>
<ActivityIndicator size={"large"} />
</View>
) : (
<Button title="Pick images" onPress={pickImages} />
)
}
/>
</>
);
}
I can able to pick the image from my Local storage. In Console also it is showing, But i cannot able to display it in screen.
Kindly help me out.
It looks like you're already passing the uri into the array. by doing [result.uri] and then in the image you're doing it again item.uri. trying just doing the item.

React Three Fiber | Lines are not casting shadows

I recently started digging into ThreeJS, followed some tutorials and now I have a problem with my line / bufferGeometry not casting any shadows. Shadows are casted, as long as I use boxBufferGeometry inside a mesh. But if I use lines, nothing happens
import React from 'react'
import { Canvas } from '#react-three/fiber'
import Curve from './components/Curve';
import Controls from './components/Controls';
import Plane from './components/Plane';
import * as THREE from 'three';
const App = () => {
return (
<div className="App">
<Canvas shadows colorManagement camera={{position: [5,5,5]}} onCreated={({gl}) => {
gl.shadowMap.enabled = true;
gl.shadowMap.type = THREE.PCFShadowMap;
gl.setPixelRatio(window.devicePixelRatio || 2);
}}>
<spotLight
position={[0,70,0]}
color="white"
intensity={1.5}
castShadow
shadowMapHeight={1024}
shadowMapWidth={1024}
shadowCameraNear={200}
shadowCameraFar={2000}
shadowBias={ - 0.00022}
angle={0.01}
/>
<ambientLight color="#f0f0f0" />
<Controls />
<Curve />
<Plane />
<gridHelper args={[30, 100, 'white', 'white']} position={[0,-3.99,0]} receiveShadow />
</Canvas>
</div>
);
}
export default App;
import React, { useLayoutEffect, useRef } from 'react';
import * as THREE from 'three';
const Curve = () => {
const curve = new THREE.CubicBezierCurve3
(
new THREE.Vector3( -10, 0, 0 ),
new THREE.Vector3( -5, 15, 0 ),
new THREE.Vector3( 20, 15, 0 ),
new THREE.Vector3( 10, 0, 0 )
);
const points = curve.getPoints( 50 );
const ref = useRef()
useLayoutEffect(() => {void ref.current.setFromPoints(points); }, [points])
return (
<line>
<bufferGeometry ref={ref} />
<lineBasicMaterial color={0xd2452b} />
</line>
);
};
export default Curve;
import React from 'react';
const Plane = () =>
<mesh rotation={[-Math.PI / 2, 0, 0]} position={[0,-4,0]} receiveShadow>
<planeGeometry
attach="geometry"
args={[1024,1024]}
/>
<shadowMaterial attach="material" color="#000000" opacity="1" />
</mesh>
export default Plane;
Rendering this component (Box) instead of curve, would cast a shadow.
import React, { useState } from 'react';
import { useSpring, a } from '#react-spring/three';
const Box = () => {
const [hovered, setHovered] = useState(false);
const [active, setActive] = useState(false);
const props = useSpring({
scale: active ? 2 : 1,
color: hovered ? 'red' : 'gray',
});
return (
<a.mesh
onPointerOver={() => setHovered(true)}
onPointerOut={() => setHovered(false)}
onClick={() => setActive(!active)}
scale={props.scale}
castShadow
>
<boxBufferGeometry
attach="geometry"
args={[1,1,1]}
/>
<a.meshPhysicalMaterial attach="material" color={props.color} />
</a.mesh>
);
};
export default Box;
The only difference (I'm still a newbie), is that I am using lines instead of mesh. Mesh accepts attributes like "receiveShadow and castShadow", lines doesn't.
How do I manage to let my lines cast shadows, too?
Thanks a lot in advance

react-three, unable to get mouse position for html content

I'm trying to to get current mouse position on the canvas when html contents are clicked. With useFrame, I can successfully print out mouse position on any parts of canvas except when mouse is on html contents (it just shows the last mouse position before it enters html part and just stops there).
Are there any ways I can get mouse position when it hovers on html content?
Here are my codes:
#app.js
import React, {useRef, useState } from 'react';
import {Canvas, useFrame, useThree } from '#react-three/fiber';
import { Stars, Html } from '#react-three/drei'
function Sphere(props){
const mesh = useRef(null);
const { viewport, mouse } = useThree()
useFrame(({ mouse }) => {
const x_viewport = (mouse.x * viewport.height) / 2
console.log(x_viewport)
});
return(
<mesh
ref={mesh}
<sphereGeometry args={[1, 16, 16]} />
<meshStandardMaterial />
</mesh>
);
};
function Blocks (props) {
const {handlePost } = props;
let rows = [];
for (let i = 0; i < 30; i++) {
rows.push(<div onClick={handlePost} key={i} ></div>);
}
return (
<>
<div> { rows } </div>
</>
)
}
export default function Meshes() {
const [ hasRender, setRender ] = useState(false);
const handlePost = (e) => {
setRender(true);
}
return (
<>
<Canvas
orthographic
dpr={[1, 1.5]}
mode="concurrent"
camera={{ zoom: 10, position: [0, 0, 500] }}
style={{ width: c_width, color: "black" }}
>
<color attach="background" args={["black"]} />
<Html >
<Blocks handlePost={handlePost} />
</Html>
<ambientLight intensity={0.1} />
<directionalLight position={[0, 1, 1]} />
<Sphere days={days}/>
</Canvas>
{ hasRender && ( <PostItems /> )}
</>
);
}
function App() {
return (
<>
<Meshes />
</>
)
}

Image not loading in React Native when I use require but loads when I load from URL

When I try to load an image by using require, the image does not load but when I load the same image from a URL, the image loads. Here is the snippet of code that I am calling the image from
class Home extends React.Component {
render() {
return (
<ScrollView
noSpacer={true}
noScroll={true}
style={styles.container}
showVerticalSCrollIndicator = {false}
showHorizontalScrollIndicator = {false}
>
{this.state.loading ? (
<ActivityIndicator
style={[styles.centering, styles.gray]}
color="#5d38aa"
size="large"
/>
) : (
<div>
<Header title={this.state.user.name} />
<div id='image'>
<Image
source={require('./arrow.png')}
style={styles.image}
/>
</div>
</div>
)}
</ScrollView>
);
}
}
The image is loaded here
<Image
source={require('./arrow.png')}
style={styles.image}
/>
Please make sure that you give the right path to your image.
You can use the source as an object:
<Image source={{ uri: 'something.jpg' }} />
But what you have should work, check your path.
There were few errors here and there, I think you were trying to port ReactJS code to RN and not surprisingly there were few slip-ups like you used div instead and View and small things like that, also boxShadow was not working so I removed that.
After a few tweaks code is working and images are loading.
As I stated earlier, I have omitted the User component and sanityClient, you can implement them later.
Here is the working home.js after changes.
import React from "react";
import {
ScrollView,
ActivityIndicator,
StyleSheet,
Image,
ImageBackground,
View,
} from "react-native";
// import UserList from "./user-list";
import Header from "./header";
// import sanityClient from "";
// import BackButton from "./back-button";
// import User from "./user";
// import {Asset} from 'expo-asset';
// const imageURI = Asset.fromModule(require('./arrow.png')).uri;
// const image = require("./assets/aoeu.jpg");
class Home extends React.Component {
state = {
user: {},
loading: true,
};
componentDidMount() {
// TODO: get users
this.getUser();
}
async getUser() {
// sanityClient
// .fetch(
// `*[ _type == "user" && emailAddress.current == "dwight#viamaven.com"]`
// )
// .then((data) => {
// console.log(data);
// this.setState({ user: data[0], loading: false });
// console.log(this.state.user);
// })
// .catch((err) => console.error(err));
// const res = await fetch("https://randomuser.me/api/?results=20");
// const { results} = await res.json();
// // console.log(results)
// this.setState({users: [...results], loading: false});
}
render() {
return (
<ScrollView
noSpacer={true}
noScroll={true}
style={styles.container}
showVerticalSCrollIndicator={false}
showHorizontalScrollIndicator={false}
>
{!this.state.loading ? (
<ActivityIndicator
style={[styles.centering, styles.gray]}
color="#5d38aa"
size="large"
/>
) : (
<View>
<Header title={"Spidy"} />
<View id="image">
<Image source={require("./arrow.png")} style={styles.image} />
</View>
{/* <User /> */}
</View>
)}
</ScrollView>
);
}
}
var styles = StyleSheet.create({
container: {
backgroundColor: "white",
width: 375,
height: 812,
// top: '50px',
},
centering: {
alignItems: "center",
justifyContent: "center",
padding: 8,
height: "100vh",
},
image: {
width: 50,
height: 50,
marginRight: 20,
// boxShadow: "0px 1px 2px 0px rgba(0,0,0,0.1)",
// boxShadow: "10px 10px 17px -12px rgba(0,0,0,0.75)",
},
});
export default Home;
Zip file containing all the changes: src
Output:

Image not showing in React Native Web App. Appears when I build for Android or iOS but doesn't show when using react-scripts start

I am trying to display an image in a React Native Web App which is run using react-scripts start. When I build the App for iOS or Android, the image appears perfectly fine (using expo) but when I build it for the Web App, the image fails to load. Here is the code snippet for the Home component where the image is loaded
import React from "react";
import { ScrollView, ActivityIndicator, StyleSheet, Image, ImageBackground } from "react-native";
import UserList from "./user-list";
import Header from './header';
import sanityClient from './assets/client'
import BackButton from './back-button'
import User from './user'
// import {Asset} from 'expo-asset';
// const imageURI = Asset.fromModule(require('./arrow.png')).uri;
const image = require('./assets/aoeu.jpg');
class Home extends React.Component {
state = {
user: {},
loading: true
};
componentDidMount() {
// TODO: get users
this.getUser();
}
async getUser() {
sanityClient.fetch(`*[ _type == "user" && emailAddress.current == "dwight#viamaven.com"]`)
.then((data) => {
console.log(data);
this.setState({user: data[0], loading: false});
console.log(this.state.user);
})
.catch((err) => console.error(err))
// const res = await fetch("https://randomuser.me/api/?results=20");
// const { results} = await res.json();
// // console.log(results)
// this.setState({users: [...results], loading: false});
}
render() {
return (
<ScrollView
noSpacer={true}
noScroll={true}
style={styles.container}
showVerticalSCrollIndicator = {false}
showHorizontalScrollIndicator = {false}
>
{this.state.loading ? (
<ActivityIndicator
style={[styles.centering, styles.gray]}
color="#5d38aa"
size="large"
/>
) : (
<View>
<Header title={this.state.user.name} />
<View>
<Image
source={require('./arrow.png')}
style={styles.image}
/>
</View>
<User />
</View>
)}
</ScrollView>
);
}
}
var styles = StyleSheet.create({
container: {
backgroundColor: "white",
width: '375px',
height: '812px',
// top: '50px',
},
centering: {
alignItems: "center",
justifyContent: "center",
padding: 8,
height: '100vh'
},
image: {
width: '50px',
height: '50px',
marginRight: 20,
boxShadow: "0 1px 2px 0 rgba(0,0,0,0.1)"
}
});
export default Home;
Here is a link to the GitHub repo where the entire project is stored https://github.com/nimbusdin/stackreactnative
Try to import this way and use it like this
import image = './assets/aoeu.jpg';
<Image
source={image}
style={styles.image}
/>

Resources