Compass location on react-native Mapbox map - react-native-mapbox-gl

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}
/>

Related

Standardise taking photo's with the react-native vision camera (default wide-angle-lens and zoom 2x)

I'm new in developing with React native and couldn't make my mobile app work.
I want to take a photo with 2 rules:
The camera can't switch to another lens (so only the wide-angle, not the ultra-wide-angle or telelens).
There is a fixed zoom of 2x on the wide-angle lens that can't be changed
Step 1 worked, it now always select the reight lens (wide-angle-camera), only I dont know how to add zooming as const.
function App() {
const devices = useCameraDevices('wide-angle-camera')
const device = devices.back
if (device == null) return <LoadingView />
return (
<Camera
style={StyleSheet.absoluteFill}
device={device}
/>
)
}

React Native App design is different in different IOS Device

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),
},

Expo Three.js OrbitControls

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

Couldn't get the camera to work using expoTHREE and expoGRAPHICS to create an AR scene in a React-native project

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.

React-Native Horizontal Scroll View Pagination: Preview Next Page/Card

I want to to a horizontal ScrollView with pagination enabled with one special requirement: each page (or card) is 90% of the container wide. The remaining 10% should be a preview of the next page.
It is possible to do this with ScrollView? Can I somehow specify the width of the pagination instead of taking the width of the container?
(image taken from this similar question: React Native Card Carousel view?)
I spend a lot of time fighting with this until I figured it out so here is my solution if it helps someone.
https://snack.expo.io/H1CnjIeDb
Problem was all these were required and pagination should be turned off
horizontal={true}
decelerationRate={0}
snapToInterval={width - 60}
snapToAlignment={"center"}
You can absolutely do that with ScrollView or, even better, FlatList. However, the really tricky part is the snapping effect. You can use props snapToInterval and snapToAlignment to achieve it (see Vasil Enchev's answer); unfortunately, these are iOS-only.
A co-worker and I created a plugin that answers this particular need. We ended up open-sourcing it, so it's all yours to try: react-native-snap-carousel.
The plugin is now built on top of FlatList (versions >= 3.0.0), which is great to handle huge numbers of items. It provides previews (the effect you're after), snapping effect for iOS and Android, parallax images, RTL support, and more.
You can take a look at the showcase to get a grasp of what can be achieved with it. Do not hesitate to share your experience with the plugin since we're always trying to improve it.
Edit : two new layouts have been introduced in version 3.6.0 (one with a stack of cards effect and the other with a tinder-like effect). Enjoy!
Use disableIntervalMomentum={ true } in your ScrollView. This will only allow the user to scroll one page at a time horizontally. Check official documents
https://reactnative.dev/docs/scrollview#disableintervalmomentum
<ScrollView
horizontal
disableIntervalMomentum={ true }
snapToInterval={ width }
>
<Child 1 />
<Child 2 />
</ScrollView>
You can pass a horizontal props to your scroll view:
https://facebook.github.io/react-native/docs/scrollview.html#horizontal
And then you can create a view inside to specify your width requirements.
<ScrollView
ref={(snapScroll) => { this.snapScroll = snapScroll; }}
horizontal={true}
decelerationRate={0}
onResponderRelease={()=>{
var interval = 300; // WIDTH OF 1 CHILD COMPONENT
var snapTo = (this.scrollingRight)? Math.ceil(this.lastx / interval) :
Math.floor(this.lastx / interval);
var scrollTo = snapTo * interval;
this.snapScroll.scrollTo(0,scrollTo);
}}
scrollEventThrottle={32}
onScroll={(event)=>{
var nextx = event.nativeEvent.contentOffset.x;
this.scrollingRight = (nextx > this.lastx);
this.lastx = nextx;
}}
showsHorizontalScrollIndicator={false}
style={styles.listViewHorizontal}
>
{/* scroll-children here */}
</ScrollView>
Here is example of simple scrollview pagination for bottom:
<ScrollView
......
onMomentumScrollEnd={event => {
if (isScrollviewCloseToBottom(event.nativeEvent)) {
this.loadMoreData();
}
}}
</ScrollView>
.....
....
function isScrollviewCloseToBottom({
layoutMeasurement,
contentOffset,
contentSize,
}) {
const paddingToBottom = 20;
return (
layoutMeasurement.height + contentOffset.y >=
contentSize.height - paddingToBottom
);
}
......
....
same as we can use this for right pagination:
function isScrollviewCloseToRight({
layoutMeasurement,
contentOffset,
contentSize,
}) {
const paddingToRight = 10;
return (
layoutMeasurement.width + contentOffset.x >=
contentSize.width - paddingToRight
);
}
Hope it will helpful..!!
You can look at contentOffset and scrollTo property of ScrollView . Logically what you can do is whenever the page changes(mostly when moved to next page) you can provide a extra offset of 10% or so as per your need so that the next item in the scrollview becomes visible .
Hope this helps, let me know if you need any extra details .