How to update variable react native? - react-native

I have an app, where i need to get known ratio of picture for resizing it later. User can take pictures horizontal and vertical. And of course, ratio changes. So i need to get two different ratios.
There is problem with updating let horizontalImageRatio = 0;
How can i solve this, any tips?
my code:
Image.getSize(data.uri, (width, height) => { // Pickuping size of the picture
let imageWidth = width;
let imageHeight = height;
let stringImageWidth = '' + imageWidth; // Make double to string for storing to asyncstorage
let stringImageHeight = '' + imageHeight;
let horizontalImageRatio = 0; // this value should be updated
let verticalImageRatio = 0;
// For updating let horizontalImageRatio, but not working outside of this <-- PROBLEM
const horizontalRatioCalc = () => {
horizontalImageRatio = imageWidth/imageHeight;
console.log('horizontal_update', horizontalImageRatio);
};
const verticalRatioCalc = () => {
verticalImageRatio = imageWidth/imageHeight;
console.log('vertical_update', verticalImageRatio);
};
let stringHorizontalImageRatio = '' + horizontalImageRatio;
let stringVerticalImageRatio = '' + verticalImageRatio;
console.log(`Size of the picture ${imageWidth}x${imageHeight}`); // Tells size of the image for the console
horizontalRatio = async () => {
if (imageHeight>imageWidth) {
verticalRatioCalc();
try {
AsyncStorage.setItem("imageVerticalRatio", stringVerticalImageRatio),
AsyncStorage.setItem("asyncimageWidth", stringImageWidth)
AsyncStorage.setItem("asyncimageHeight", stringImageHeight)
console.log(`Vertical ratio saved! It's ${stringVerticalImageRatio}`)
console.log(`Image Width saved! It's ${stringImageWidth}`)
console.log(`Image height saved! It's ${stringImageHeight}`)
} catch (e) {
console.log(`AsyncStorage saving of image vertical ratio cannot be done.`)
}
}else {
horizontalRatioCalc();
try {
AsyncStorage.setItem("imageHorizontalRatio", stringHorizontalImageRatio),
AsyncStorage.setItem("asyncimageWidth", stringImageWidth)
AsyncStorage.setItem("asyncimageHeight", stringImageHeight)
console.log(`Horizontal ratio saved! It's ${stringHorizontalImageRatio}`)
console.log(`Image Width saved! It's ${stringImageWidth}`)
console.log(`Image height saved! It's ${stringImageHeight}`)
} catch (e) {
console.log(`AsyncStorage saving of image vertical ratio cannot be done.`)
}
}
}
horizontalRatio();

So, apparently, you don't have access to horizontalImageRatio inside of horizontalRatioCalc, the method horizontalRatioCalc has a different scope.
What you can do is change horizontalRatioCalc to receive a parameter and return a value, just like I've done in this example: https://stackblitz.com/edit/react-xiysai
This is good because now you have a function that can be tested independently.
Or you can also do it this way:
https://stackblitz.com/edit/react-variable-scope
This way you have access to both the variable and the method.

Related

How to get bounds of OrthographicView with deck.gl

I'd like to make a minimap of OrthographicView and draw the bounds path.
I can get the viewState which has its width, height, target, and zoom.
But how can I get or compute the bounds (top, right, bottom, left coordinates of current view)?
When you receive a viewState, you can get the bounds with the following code:
const viewportBounds = () => {
const { width, height } = viewState.main;
if (!width) return null;
const view = new OrthographicView(viewState.main);
const viewport = view._getViewport();
const topLeft = viewport.unproject([0, 0]);
const topRight = viewport.unproject([width, 0]);
const bottomLeft = viewport.unproject([0, height]);
const bottomRight = viewport.unproject([width, height]);
return [[topLeft, topRight, bottomRight, bottomLeft, topLeft]];
}

Image ratio using in image drawing react-native

I have an app, where I take a pic and draw it to the pdf file.
I have been trying to get them in right ratio. If I take all picture horizontal, it would be fine. If I take all pictures vertical, it would be fine. Problem is, when I take both vertical and horizontal, last picture's ratio applied to all pictures.
I save image ratio to AsyncStorage, where I get it in other component.
Questions is: How can I keep original ratios when I take pictures both ways?
Camera component -> takePicture function:
takePicture = async() => {
if (this.camera) {
const options = { quality: 0.5, base64: true , fixOrientation: true};
const data = await this.camera.takePictureAsync(options);
console.log(data.uri);
Image.getSize(data.uri, (width, height) => { // Get image height and width
let imageWidth = width;
let imageHeight = height;
let stringImageWidth = '' + imageWidth; // Convert to string for AsyncStorage saving
let stringImageHeight = '' + imageHeight;
const horizontalRatioCalc = () => { // return ratio for own variable
return (imageWidth/imageHeight);
};
const verticalRatioCalc = () => {
return (imageWidth/imageHeight);
};
horizontalImageRatio = horizontalRatioCalc();
verticalImageRatio = verticalRatioCalc();
stringHorizontalImageRatio = '' + horizontalImageRatio;
stringVerticalImageRatio = '' + verticalImageRatio;
console.log(`Size of the picture ${imageWidth}x${imageHeight}`);
horizontalRatio = async () => {
if (imageHeight>imageWidth) {
verticalRatioCalc();
try {
AsyncStorage.setItem("imageVerticalRatio", stringVerticalImageRatio),
AsyncStorage.setItem("asyncimageWidth", stringImageWidth),
AsyncStorage.setItem("asyncimageHeight", stringImageHeight),
console.log(`Vertical ratio saved! It's ${stringVerticalImageRatio}`),
console.log(`Image Width saved! It's ${stringImageWidth}`),
console.log(`Image height saved! It's ${stringImageHeight}`)
} catch (e) {
console.log(`AsyncStorage saving of image vertical ratio cannot be done.`)
}
}if (imageHeight<imageWidth) {
horizontalRatioCalc();
try {
AsyncStorage.setItem("imageHorizontalRatio", stringHorizontalImageRatio),
AsyncStorage.setItem("asyncimageWidth", stringImageWidth),
AsyncStorage.setItem("asyncimageHeight", stringImageHeight),
console.log(`Horizontal ratio saved! It's ${stringHorizontalImageRatio}`),
console.log(`Image Width saved! It's ${stringImageWidth}`),
console.log(`Image height saved! It's ${stringImageHeight}`)
} catch (e) {
console.log(`AsyncStorage saving of image vertical ratio cannot be done.`)
}
}
}
horizontalRatio();
}, (error) => {
console.error(`Cannot size of the image: ${error.message}`);
});
back(data.uri)
//CameraRoll.saveToCameraRoll(data.uri).then((data) => {
// console.log(data)
//back(data);
//}).catch((error) => {
//console.log(error)
//})
}
CreatePdf component -> PDF drawing function:
readData = async () => {
try {
kuvakorkeus = await AsyncStorage.getItem('asyncimageHeight')
kuvaleveys = await AsyncStorage.getItem('asyncimageWidth')
vertikaaliratio = await AsyncStorage.getItem('imageVerticalRatio')
horisontaaliratio = await AsyncStorage.getItem('imageHorizontalRatio')
if (kuvakorkeus !== null) {
return kuvakorkeus;
return kuvaleveys;
return vertikaaliratio;
return horisontaaliratio;
}
} catch (e) {
alert('Failed to fetch the data from storage')
}
}
readData ();
kuvanpiirto = () => {
pdfKuvaKorkeus = 100;
if(kuvakorkeus>kuvaleveys) { // VERTICAL / PYSTYKUVA
page.drawImage(arr[i].path.substring(7),'jpg',{
x: imgX,
y: imgY,
width: pdfKuvaKorkeus*vertikaaliratio,
height: pdfKuvaKorkeus,
})
}
if(kuvakorkeus<kuvaleveys) { // Horizontal / Vaakakuva
page.drawImage(arr[i].path.substring(7),'jpg',{
x: imgX,
y: imgY,
width: pdfKuvaKorkeus*horisontaaliratio,
height: pdfKuvaKorkeus,
})
}
}
kuvanpiirto();

How does Puppeteer handle the click Object / DevTools Protocol Chromium/Chrome

I need to know how puppeteer handles the click object, as well as Chromium DevTools API. I've tried to research it on my own and have found myself not being able to find the actual code that handles it.
The reason why I need to know is I'm developing a wrapper that tests events in code for testing Web Pages, and was looking to see if implementing a event handling routine is beneficial instead of using puppeteers interface of events (clicks and taps an hover, as well as other events that might be needed like touch events, or scrolling)
Here is how far I've gotten:
Puppeteer API uses the Frame Logic of DevTools to contact API:
https://github.com/puppeteer/puppeteer/blob/master/lib/Page.js
/**
* #param {string} selector
* #param {!{delay?: number, button?: "left"|"right"|"middle", clickCount?: number}=} options
*/
click(selector, options = {}) {
return this.mainFrame().click(selector, options);
}
/**
* #return {!Puppeteer.Frame}
*/
/**
* #param {!Protocol.Page.Frame} framePayload`
*/
_onFrameNavigated(framePayload) {
const isMainFrame = !framePayload.parentId;
let frame = isMainFrame ? this._mainFrame : this._frames.get(framePayload.id);
assert(isMainFrame || frame, 'We either navigate top level or have old version of the navigated frame');
// Detach all child frames first.
if (frame) {
for (const child of frame.childFrames())
this._removeFramesRecursively(child);
}
if (isMainFrame) {
if (frame) {
// Update frame id to retain frame identity on cross-process navigation.
this._frames.delete(frame._id);
frame._id = framePayload.id;
} else {
// Initial main frame navigation.
frame = new Frame(this, this._client, null, framePayload.id);
}
this._frames.set(framePayload.id, frame);
this._mainFrame = frame;
}
This is as far as I have gotten because I've tried to look up the Page Protocol but I can't figure out what happens there.
Any help would be appreciated, even in research.
The main parts are happening in JSHandle here:
async click(options) {
await this._scrollIntoViewIfNeeded();
const {x, y} = await this._clickablePoint();
await this._page.mouse.click(x, y, options);
}
It scrolls until the element is in viewport (otherwise it won't click) which is happening here, then it finds the clickable coordinates on the element using DevTools API here:
async _clickablePoint() {
const [result, layoutMetrics] = await Promise.all([
this._client.send('DOM.getContentQuads', {
objectId: this._remoteObject.objectId
}).catch(debugError),
this._client.send('Page.getLayoutMetrics'),
]);
if (!result || !result.quads.length)
throw new Error('Node is either not visible or not an HTMLElement');
// Filter out quads that have too small area to click into.
const {clientWidth, clientHeight} = layoutMetrics.layoutViewport;
const quads = result.quads.map(quad => this._fromProtocolQuad(quad)).map(quad => this._intersectQuadWithViewport(quad, clientWidth, clientHeight)).filter(quad => computeQuadArea(quad) > 1);
if (!quads.length)
throw new Error('Node is either not visible or not an HTMLElement');
// Return the middle point of the first quad.
const quad = quads[0];
let x = 0;
let y = 0;
for (const point of quad) {
x += point.x;
y += point.y;
}
return {
x: x / 4,
y: y / 4
};
}
and finally it moves the mouse to the coordinate here and clicks on it here
async click(x, y, options = {}) {
const {delay = null} = options;
if (delay !== null) {
await Promise.all([
this.move(x, y),
this.down(options),
]);
await new Promise(f => setTimeout(f, delay));
await this.up(options);
} else {
await Promise.all([
this.move(x, y),
this.down(options),
this.up(options),
]);
}
}
which uses DevTools API to interact with mouse here
async down(options = {}) {
const {button = 'left', clickCount = 1} = options;
this._button = button;
await this._client.send('Input.dispatchMouseEvent', {
type: 'mousePressed',
button,
x: this._x,
y: this._y,
modifiers: this._keyboard._modifiers,
clickCount
});
}

How do I restrict a dragging gesture to one direction only in SwiftUI?

I've embarrassingly spent the past 2 weeks trying to solve this.
What I'm trying to do is:
Snap my Slide Over View to the bottom of the screen
Disable dragging up and only allow the card to be dragged down to close
What I've tried:
I've tried messing with the size of the card by setting its height to the height of the screen. You can see this line commented out. After doing this, I've messed around with the offset of the card and set it so that it looks as if the card is actually less than half its size, around 300 in height. The problem with this is when I slide up slowly, I can see the empty space that is hidden out of the screen. This isn't the effect I want.
The next thing I have tried to do is change the height of the card to a desired height. Then adjust the offset so the card is where I want it to be. However, I feel manually adjusting it won't be reliable on different screens. So I'm trying to work out the right math needed to always have it be placed at the very bottom of the screen when it pops up.
Finally, I want to just make it so users can only drag down and not up.
I would really appreciate some help here. I've spent a lot of time message around and reading, learning new things, but I can't solve my specific problem.
Here is my Slide Over Card
import SwiftUI
struct SigninView<Content: View> : View {
#GestureState private var dragState = DragState.inactive
#State var position = CardPosition.top
var content: () -> Content
var body: some View {
let drag = DragGesture()
.updating($dragState) { drag, state, transaction in
state = .dragging(translation: drag.translation)
}
.onEnded(onDragEnded)
return Group {
// Handle()
self.content()
}
.frame(height: 333) //UIScreen.main.bounds.height)
.background(Color.purple)
.cornerRadius(10.0)
.shadow(color: Color(.sRGBLinear, white: 0, opacity: 0.13), radius: 10.0)
.offset(y: self.position.rawValue + self.dragState.translation.height)
.animation(self.dragState.isDragging ? nil : .interpolatingSpring(stiffness: 300.0, damping: 30.0, initialVelocity: 10.0))
.gesture(drag)
}
private func onDragEnded(drag: DragGesture.Value) {
let verticalDirection = drag.predictedEndLocation.y - drag.location.y
let cardTopEdgeLocation = self.position.rawValue + drag.translation.height
let positionAbove: CardPosition
let positionBelow: CardPosition
let closestPosition: CardPosition
if cardTopEdgeLocation <= CardPosition.middle.rawValue {
positionAbove = .top
positionBelow = .middle
} else {
positionAbove = .middle
positionBelow = .bottom
}
if (cardTopEdgeLocation - positionAbove.rawValue) < (positionBelow.rawValue - cardTopEdgeLocation) {
closestPosition = positionAbove
} else {
closestPosition = positionBelow
}
if verticalDirection > 0 {
self.position = positionBelow
} else if verticalDirection < 0 {
self.position = positionAbove
} else {
self.position = closestPosition
}
}
}
enum CardPosition: CGFloat {
case top = 100
case middle = 790
case bottom = 850
}
enum DragState {
case inactive
case dragging(translation: CGSize)
var translation: CGSize {
switch self {
case .inactive:
return .zero
case .dragging(let translation):
return translation
}
}
var isDragging: Bool {
switch self {
case .inactive:
return false
case .dragging:
return true
}
}
}
Here is my ContentView page, where I test it:
import SwiftUI
struct ContentView: View {
#State var show:Bool = false
var body: some View {
SigninView {
VStack {
Text("TESTING")
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.blue)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
First, you should probably not have your SigninView be your content view. Instead, consider presenting your sign in view as an overlay instead.
var body: some View {
ZStack {
Text("Content here!")
}
.overlay(
SigninView()
.offset(...),
alignment: .bottom
)
}
This will automatically place your view at the bottom of the screen at the height of your SigninView, there should be little to no math involved here. The offset, you will define with your gesture and any space you want to exist between the bottom and your overlay.
Next, to only allow down gestures, can't you just clamp your translation?
var translation: CGSize {
switch self {
case .inactive:
return .zero
case .dragging(let translation):
return max(0, translation) // clamp this to the actual translation or 0 so it can't go negative
}
}

move snapshot to images folder

I am building an app for iOS with React-native, and I use my code to capture a screenshot successfully. The problem is that I want to move the snapshot to the Images folder so it is easily accessible by the user.
I use the following code:
snapshot = async () => {
const targetPixelCount = 1080; // If you want full HD pictures
const pixelRatio = PixelRatio.get(); // The pixel ratio of the device
// pixels * pixelratio = targetPixelCount, so pixels = targetPixelCount / pixelRatio
const pixels = targetPixelCount / pixelRatio;
const result = await Expo.takeSnapshotAsync(this, {
result: 'file',
height: pixels,
width: pixels,
quality: 1,
format: 'png',
});
if (result) {
//RNFS.moveFile(result, 'Documents/snapshot.png');
Alert.alert('Snapshot', "Snapshot saved to " + result);
}
else {
Alert.alert('Snapshot', "Failed to save snapshot");
}
}
Does anybody know how to move the image to the Images Folder?
Thank you
Use the RN CameraRoll Module: https://facebook.github.io/react-native/docs/cameraroll