I am trying to make a native app using expo in which I want to have a plane that I can pan around and zoom in and out of like a map, I am using Three as my 3d engine as I do need it to have the ability to be rotated in a 3d space. I have got a 3d cube in my app rotating as a start. From what I can tell this is pretty simple in a browser using MapControls or Orbit controls, however in native I can't get either of these things working, even when I import the script directly from the examples folder
export default function MapBuilder() {
const onContextCreate = async gl => {
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(
75,
gl.drawingBufferWidth / gl.drawingBufferHeight,
0.1,
1000
)
const renderer = new ExpoTHREE.Renderer({ gl })
renderer.setSize(gl.drawingBufferWidth, gl.drawingBufferHeight)
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshNormalMaterial({ wireframe: true })
const cube = new THREE.Mesh(geometry, material)
scene.add(cube)
const controls = OrbitControls(camera, renderer.domElement)
camera.position.y = 0
camera.position.x = 0
camera.position.z = 5
controls.update()
const animate = () => {
window.requestAnimationFrame(animate)
cube.rotation.x += 0.02
cube.rotation.y += 0.02
renderer.render(scene, camera)
controls.update()
gl.endFrameEXP()
}
animate()
}
return (
<GLView
style={{ flex: 1, backgroundColor: 'black' }}
onContextCreate={onContextCreate}
/>
)
}
I belive the issue could be the renderer.domElement but I dont know what to replace this with.
Any help is appreciated.
I misunderstood the question before
Sorry for the wrong answer
I also had problem with using OrbitControls in Expo today,
and found expo-three-orbit-controls works fine for me
I tested with my iPhone and Android emulator
try using ExpoGraphics.View instead of GLView
I have succeeded making a globe and running it on my iPhone by using expo-three and expo graphics
You can check the core of the source from here:
https://github.com/cryslub/history-expo/blob/master/ThreeScene.js
Related
Hy everyone, I'm building a react native applications but I'm facing a issue for long time which is that the app design is different in iOS devices. The devices work iPhone 6-iphone 8 design is same and iPhone X - iPhone 13 is same. But these both groups are different in design.
When you say they are different in design, do you mean their device dimensions? If so, there are some workarounds for that issue. Personally, I would recommend creating scale functions for the width and height of the device you use to develop your app. Applying the scale functions will keep your design consistent throughout different devices.
import {Dimensions, PixelRatio} from 'react-native';
const {width: SCREEN_WIDTH, height: SCREEN_HEIGHT} = Dimensions.get('window');
// based on iphone 11s's scale
const scalew = SCREEN_WIDTH / 828;
const scaleh = SCREEN_HEIGHT / 1792;
export function normalizeh(size) {
const newSize = size * scaleh;
return Math.round(PixelRatio.roundToNearestPixel(newSize));
}
export function normalizew(size) {
const newSize = size * scalew;
return Math.round(PixelRatio.roundToNearestPixel(newSize));
}
Then when styling,
menuBtn: {
width: normalizew(60),
color: '#212529',
marginRight: normalizew(30),
},
What is the best way to simulate movement inside react-native-maps using an Android emulator? I know that you can load a gpx file in the location settings menu. However that only works with google maps inside the emulator, not a custom app that utilizes react-native-maps.
I'm also aware that it is possible to simulate user movement using the Expo-Location library.
import * as Location from 'expo-location';
const tenMetersWithDegrees = 0.0001;
const getLocation = increment => {
return {
timestamp: 100000,
coords: {
speed: 0,
heading: 0,
accuracy: 5,
altitudeAccuracy: 5,
altitude: 5,
longitude: -122.9779983 + increment * tenMetersWithDegrees,
latitude: 37.5665 + increment * tenMetersWithDegrees,
}
}
}
let counter = 0;
setInterval(() => {
Location.EventEmitter.emit('Expo.locationChanged', {
watchId: Location._getCurrentWatchI(),
location: getLocation(count)
})
counter++
}, 1000);
Would it be possible to build this same type script using just react native geolocation service?
With android emulator, you can simulate route. Check below screenshot
I am using vue 2.6.10 and I have the following dependencies vue-mapbox 0.4.1 and mapbox-gl 1.3.2
The map works, but I cannot get all the points of the map, create bounds and make the map zoom there.
What I am doing now, based on this and this
In my template
<MglMap
ref="map"
#load="mapLoaded()">
and then in my javascript
import Mapbox from "mapbox-gl";
components: { Mapbox}
methods :{
mapLoaded(){
let coords = [];
//coords is array , contains arrays like [-118.578, 51.524]
let bounds = coords.reduce((bounds, coord)=> {
return bounds.extend(coord);
}, this.mapbox.LngLatBounds(coords[0], coords[0])
);
this.$refs['map'].map.fitBounds(bounds, { padding: 20 });
}
},
created(){
this.mapbox = Mapbox;
}
This should work, but I keep getting
TypeError: this.setSouthWest is not a function
so I guess there is a problem in this.mapbox.LngLatBounds(coords[0], coords[0]) , maybe the this.mapbox. or the LngLatBounds does not work.
If I console log the coords[0], prints an array [10.467778, 37.600833]
What am I missing? Thanks
I have got the same error. Turns out I have missed "new" keyword.
You can try adding the "new" keyword for "this.mapbox.LngLatBounds"
The following code worked for me.
import mapboxgl from 'mapbox-gl';
Vue.prototype.$maps = mapboxgl
this.map = new this.$maps.Map({container: 'mapContainer', // container ID
style: 'mapbox://styles/mapbox/streets-v11', // style URL
zoom: 9 // starting zoom
});
const sourceMarker = new this.$maps.Marker().setLngLat(origin).addTo(this.map);
const destMarker = new this.$maps.Marker().setLngLat(destination).addTo(this.map);
const bounds = new this.$maps.LngLatBounds(origin, destination);
this.map.fitBounds(bounds);
Is it possible to change the location of the compass in React-Native Mapbox GL? It currently defaults to the top-right and I have been trying to find how to move it to the top-left.
<Mapbox.MapView
ref={component => this.map = component}
styleURL={this.state.mapStreetView}
zoomLevel={this.state.defaultZoom}
centerCoordinate={[this.state.long, this.state.lat]}
showUserLocation={true}
onPress={this.onLocationPress}
zoomEnabled={true}>
It's possible with iOS - since #389.
See compassViewPosition and compassViewMargins on MapView
No you can't move the compass position, you can only show it or hide it with the compassEnabled property.
(https://github.com/react-native-mapbox-gl/maps/blob/master/docs/MapView.md)
there is a bug in react-native-mapbox-gl/maps 8.5.0 version in android part. They cut density to int when multiply layout pixels and density. (for example, my devices has 2.8125 and 2.75 dencity, but mapbox counts them as 2.
the bug is in #react-native-mapbox-gl/maps/android/rctmgl/src/main/java/com/mapbox/rctmgl/components/mapview/RCTMGLMapView.java in updateUISettings method
and looks like
int pixelDensity = (int)getResources().getDisplayMetrics().density;
so on js side you can simply fix this with coefficient
const androidPixelRatio = PixelRatio.get();
const androidDensityCoefficient = androidPixelRatio / Math.floor(androidPixelRatio);
compassViewMargins = {
x: layoutX * androidDensityCoefficient;
y: layoutY * androidDensityCoefficient;
};
<MapboxGL.MapView
{...restProps}
compassViewMargins={compassViewMargins}
/>
I am developing a React Native app and I wanted to implement a AR scene using Three.js. My project is initialized using "React-native init" and then I installed expo modules. I created a separate module called "CamTab.js" and implemented the AR scene in it. Then I called the component from MainScreen.js. I can build and run my app without any errors but camera screen does not show up as intended. CamTab.js is shown below.
I added the Text "The Text" to see if it shows up and it works.
onContextCreate = async ({gl, scale, width, height, arSession}) => {
//initialize renderer
this.renderer = ExpoTHREE.createRenderer({gl});
this.renderer.setPixelRatio(scale);
this.renderer.setSize(width, height);
//initialize scene
this.scene = new THREE.Scene();
this.scene.background = ExpoTHREE.createARBackgroundTexture(arSession, this.renderer);
//initialize camera
this.camera = ExpoTHREE.createARCamera(arSession, width / scale, height / scale, 0.01, 1000);
}
onRender = (delta) => {
this.renderer.render(this.scene, this.camera);
}
render(){
return(<View>
<Text> The Text </Text>
<ExpoGraphics.View style = {{flex:1}}
onContextCreate= {this.onContextCreate}
onRender = {this.onRender}
arEnabled={true}/>
</View>
);
}
}
I intend to display the camera input using this component but I get nothing. just the white screen.