React Native responsive font-size - react-native

I am writing react-native app. The font size should be dynamically changed based on the screen resolution. Is there any approach to achieve this? In web world I am using rem values but in this case is not possible.
To get some help? It's very important.

You can create some helper function that will update the font size based on the device screen size using the standard device width and height as base to resize from. Or use this library https://www.npmjs.com/package/react-native-responsive-fontsize which is doing something similar.
import {Dimensions} from 'react-native';
const screenWidth = Dimensions.get('window').width;
const screenHeight = Dimensions.get('window').height;
const GuidelineBaseHeight = 844;
const GuidelineBaseWidth = 390;
const verticalScale = (size, floor = true, setMax = false) => {
size = parseFloat(size);
let result = Dimensions.common.WINDOW_HEIGHT / GuidelineBaseHeight * size;
let newSize = floor ? Math.floor(result) : result;
return setMax && newSize > size ? size : newSize;
};
const horizontalScale = (size, floor = true, setMax = false) => {
size = parseFloat(size);
let result = Dimensions.common.WINDOW_WIDTH / GuidelineBaseWidth * size;
let newSize = floor ? Math.floor(result) : result;
return setMax && newSize > size ? size : newSize;
};
export {verticalScale, horizontalScale};
<Text fontSize={verticalScale(14)} />
Also, you can create your Text component which will wrap React's text component and apply the vertical scale to the font size style.

Related

Scaling SVG loaded from the web in React Native?

I'm having some trouble getting svgs loaded from an API to work, some svgs seem to have a viewbox property some don't. Some svgs load correctly and fill the container, others are tiny, and others don't display at all (possibly too large).
The JSON data can be found here: https://snapsite.co/output.json each item contains an svg icon.
Here is how I'm currently displaying the svg:
<SvgCssUri
height="100%"
width="100%"
uri={image}
/>
Here is how it looks
I managed to solve my issue by modifying all the svgs using the following script I cobbled together.
const fs = require("fs");
const path = require("path");
// Get list of icons from the icons directory
const icons = fs.readdirSync(path.join(__dirname, "icons"));
const modifySvg = (filepath) => {
// Load the SVG file
let svg = fs.readFileSync(filepath, "utf8");
// Check if svg has viewbox
const hasViewBox = svg.includes("viewBox");
if (!hasViewBox) {
console.log("No viewBox found");
// Check if width and height are set
const hasWidth = svg.includes("width");
const hasHeight = svg.includes("height");
if (!hasWidth || !hasHeight) {
console.log("No width or height found");
} else {
console.log("Width and height found");
console.log("Adding viewBox");
// Get width property
const widthStr = svg.match(/width="([^"]*)"/)[0];
const width = widthStr.replace(/"/g, "").replace("width=", "");
// Get height property
const heightStr = svg.match(/height="([^"]*)"/)[0];
const height = heightStr.replace(/"/g, "").replace("height=", "");
console.log({ width, height });
// Add viewBox to end of svg tag
const viewBox = `viewBox="0 0 ${width} ${height}"`;
svg = svg.replace(/<svg/, `<svg ${viewBox}`);
// Make width and height are 100%
svg = svg.replace(/width="[^"]*"/, `width="100%"`);
svg = svg.replace(/height="[^"]*"/, `height="100%"`);
// Write the file
fs.writeFileSync(filepath, svg);
console.log(`Saved ${filepath}`);
}
}
};
//Loop icons
icons.forEach((icon) => {
// Get file path
const filePath = path.join(__dirname, "icons", icon);
// Modify svg
modifySvg(filePath);
});
Hope this helps someone!

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]];
}

How to update variable 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.

Low quality in PDF converting canvas in PDF using KendoPDF

I created a chart using html canvas. The result would like it to be printed as a PDF file using Kendo. It works, but the graphic quality is very poor. For the solution I need I can't use kendo chart for limitation reasons
report.html
<div class="width-100-perc text-center">
<canvas id="canvas" width="100" height="100"></canvas>
<br />
</div>
report.ts
drawChart() {
console.log( 'foi');
const canvas: HTMLCanvasElement = (<HTMLCanvasElement>document.getElementById('canvas'));
console.log(this.series);
if (canvas) {
const ctx = canvas.getContext('2d');
// Base offset distance of 10
const offset = 0;
let beginAngle = 0;
let endAngle = 0;
// Used to calculate the X and Y offset
let offsetX, offsetY, medianAngle;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fill();
for (let i = 0; i < this.angles.length; i = i + 1) {
beginAngle = endAngle;
endAngle = endAngle + this.angles[i];
// The medium angle is the average of two consecutive angles
medianAngle = (endAngle + beginAngle) / 2;
// X and Y calculations
offsetX = Math.cos(medianAngle) * offset;
offsetY = Math.sin(medianAngle) * offset;
ctx.beginPath();
ctx.fillStyle = this.series[0].data[i].color;
// Adding the offsetX and offsetY to the center of the arc
ctx.moveTo(50 + offsetX, 50 + offsetY);
ctx.arc(50 + offsetX, 50 + offsetY, 40, beginAngle, endAngle);
ctx.lineTo(50 + offsetX, 50 + offsetY);
ctx.fill();
}
if (this.angles.length > 0) {
ctx.beginPath();
ctx.fillStyle = '#FFFFFF';
ctx.arc(50, 50, 15, 0, 2 * Math.PI);
ctx.fill();
}
}
}
This is not a problem with kendo's pdf export. Rather, it's inherent to the way the HTML canvas works. Your export looks distorted and pixelated because, at the end of the day, it's just a 100x100 image, which is rather low resolution. I'm assuming you want it to be that small since it is made to fit a specific part of the page. If you just directly export this canvas, that pixelated image is what you should expect.
I can propose this workaround. You need to refactor your drawChart() method to take into account a scale (number). This would mean multiplying all x,y coordinates and dimensions by this value. By default, the scale is 1. When exporting to pdf, you will follow these steps:
Change the scale to higher value, let's say 10
Draw
Export to pdf
Change scale to 1 again
Draw
This way, the chart is temporarily redrawn using a higher resolution canvas. In it's high(er) resolution state, it's exported and then it's redrawn with its original dimensions.
If you provide some example values of your this.angles and this.series I can refactor your drawChart() function to take this into account. As it stands, I can't. But I've prepared a similar example here. This is the ReportComponent I've created.
report.component.html
<button (click)="savePdf(false)">bad pdf</button>
<button (click)="savePdf(true)">good pdf</button>
<br/>
<kendo-pdf-export #pdf>
<canvas #canvas [width]="baseWidth" [height]="baseHeight"></canvas>
</kendo-pdf-export>
report.component.ts
export class ReportComponent implements AfterViewInit {
#ViewChild("canvas", { static: false })
public canvasRef: ElementRef<HTMLCanvasElement>;
#ViewChild("pdf", { static: false })
public pdf: PDFExportComponent;
#Input() public title: string = "";
public scale: number = 1;
public baseWidth: number = 100;
public baseHeight: number = 100;
constructor() {}
ngAfterViewInit() {
this.draw();
}
draw() {
const canvas = this.canvasRef.nativeElement;
canvas.width = this.baseWidth * this.scale; // scaled
canvas.height = this.baseHeight * this.scale; // scaled
const context = canvas.getContext("2d");
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const radius = 31.4 * this.scale; // scaled
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = "green";
context.fill();
context.lineWidth = 5 * this.scale; // scaled
context.strokeStyle = "#003300";
context.stroke();
}
savePdf(good: boolean) {
if (good) {
// scale 10x and re-draw
this.scale = 10;
this.draw();
this.pdf.saveAs("good.pdf");
this.scale = 1;
this.draw();
} else {
// just draw as is
this.pdf.saveAs("bad.pdf");
}
}
}
Bad PDF
Good PDF

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