I have seen this line of code:
import { Dimensions, Platform } from 'react-native';
const { height, width } = Dimensions.get('window');
const deviceUtils = (function () {
const iPhone6Height = 667,
iphoneSEHeight = 568,
iPhoneXHeight = 812,
iPhoneXWidth = 375;
return {
dimensions: {
height,
width,
},
iPhone6Height,
iphoneSEHeight,
iPhoneXHeight,
iPhoneXWidth,
isIOS14: ios && parseFloat(Platform.Version as string) >= 14,
isLargePhone: width >= iPhoneXWidth,
isNarrowPhone: width < iPhoneXWidth,
isSmallPhone: height <= iPhone6Height,
isTallPhone: height >= iPhoneXHeight,
isTinyPhone: height <= iphoneSEHeight,
};
})();
export default deviceUtils;
I want to ask you why People need this exact height of iPhones ?
It seems someone plans to write different code for “wide” and “narrow” and “wide”, and for three different classes of heights. They use the exact width / height of an iPhone X for example to make sure that an iPhone X falls into the wide and tall categories.
This is not usually what you should do. Decide what you want to be on a screen. Use constraints to fit everything. If you have problems fitting everything use a smaller font or an adjustable font, or put everything in a scroll view. Anyway, with notch and things at the bottom of the screen, things are more complicated than just “width” and “height”.
Related
I am using react native expo and trying to make a app. But as the window size increase my each view get distorted i am using
marginTop:'33%'
but as i am expanding browser in right hand size then all my views starts going down. How can i manage responsive ness
I have also tried
import { Dimensions } from "react-native";
const { width, height } = Dimensions.get("window");
//Guideline sizes are based on standard ~5" screen mobile device
const guidelineBaseWidth = 390;
const guidelineBaseHeight = 844;
const screenSize = Math.sqrt(width * height) / 100;
const scale = size => (width / guidelineBaseWidth) * size;
const verticalScale = size => (height / guidelineBaseHeight) * size;
const moderateScale = (size, factor = 0.5) =>
size + (scale(size) - size) * factor;
export { scale, verticalScale, moderateScale, screenSize };
In this i am using moderateScale but not getting any good benefit from it. So please check and let me how can i make apps to show on web as well as mobile size.
Does pdf.js allow to render a PDF page only partially? More specifically, is it possible to tell pdf.js to render a selected "rectangle of pixels" out of an entire PDF page?
Assuming a resolution of 144 dpi, a typical page (DIN A4) would have approx. 684 (width) by 1190 (height) pixels. I would like to render (for example) a rectangle like [100, 100] (top left coordinate in pixels) and [400, 400] (bottom right coordinate in pixels).
A typical use case could be a scanned document with several handwritten notes that I would like to display and further process individually.
I do understand that a "workaround" could be to save the entire page as jpg (or any other suitable bitmap format) and apply some clipping function. But this would for sure be a less performant approach than selected rendering.
pdfs.js uses a viewport object (presumably containing parameters) for rendering. This object contains
height
width
offsetX
offsetY
rotation
scale
transform
viewBox (by default [0, 0, width / scale, height / scale])
One might think that manipulating the viewBox inside it might lead to the desired outcome, but I have found that changing the viewBox parameters does not do anything at all. The entire page is rendered every time that I apply the render method.
What might I have done wrong? Does pdf.js offer the desired functionality? And if so, how can I get it to work? Thank you very much!
Here is a very simple React component demonstrating my approach (that does not work):
import React, { useRef } from 'react';
import { pdfjs } from 'react-pdf';
pdfjs.GlobalWorkerOptions.workerSrc = 'pdf.worker.js';
function PdfTest() {
// useRef hooks
const myCanvas: React.RefObject<HTMLCanvasElement> = useRef(null);
const test = () => {
const loadDocument = pdfjs.getDocument('...');
loadDocument.promise
.then((pdf) => {
return pdf.getPage(1);
})
.then((page) => {
const viewport = page.getViewport({ scale: 2 });
// Here I modify the viewport object on purpose
viewport.viewBox = [100, 100, 400, 400];
if (myCanvas.current) {
const context = myCanvas.current.getContext('2d');
if (context) {
page.render({ canvasContext: context, viewport: viewport });
myCanvas.current.height = viewport.height;
myCanvas.current.width = viewport.width;
}
}
});
};
// Render function
return (
<div>
<button onClick={test}>Test!</button>
<canvas ref={myCanvas} />
</div>
);
}
export default PdfTest;
My initial thought was also to modify a viewBox of page Viewport. This was not the right guess (I hope that you already figured it out).
What do you need really to do to project only a part of a page to canvas is to prepare correctly the transformation of Viewport.
So it will look more or less like following:
const scale = 2
const viewport = page.getViewport({
scale,
offsetX: -100 * scale,
offsetY: - 100 * scale
})
This will move your your box section to the beginning of the canvas coordinates.
What probably you would like to do next is to make a canvas equal to the selected rectangle size (in your case is 300x300 scaled by your scale) and this solved the issue in my case.
I have a FlatList that has 2 potential heights on a screen depending on what is being shown. There are top and bottom bars that show by default and when the FlatList is scrolled down, the bars are hidden and the FlatList expands to take up the full screen.
The problem is when the FlatList shifts between the 2 different heights, the content inside will shift slightly. I have already figured out that I need to apply a scroll offset of the height of the top bar (54), however i'm having issues doing that.
const [scrollOffset, setScrollOffset] = useState(0);
const [scrollDir, setScrollDir] = useState("neutral");
<FlatList ...
onScroll={(event) => {
const screenHeight = Dimensions.get('window').height - SAFE_AREA_INSETS.top - SAFE_AREA_INSETS.bottom;
const currentOffset = event.nativeEvent.contentOffset.y;
const diff = currentOffset - (scrollOffset || 0);
if (Math.abs(diff) < 3 || currentOffset < 0 || currentOffset > (event.nativeEvent.contentSize.height - screenHeight)) {
setScrollDir("neutral");
}
else if (diff < 0 && currentOffset <= (event.nativeEvent.contentSize.height - screenHeight)) {
// Top and bottom bars are shown and flatlist height is adjusted ...
if(scrollDir !== 'up') {
flatlistRef.current.scrollToOffset({ animated:false, offset:currentOffset + 54 }); // Not working as intended
}
setScrollDir('up');
}
else {
// Top and bottom bars are hidden and flatlist height is adjusted ...
if(scrollDir !== 'down') {
flatlistRef.current.scrollToOffset({ animated:false, offset:currentOffset - 54 }); // Not working as intended
}
setScrollDir('down');
}
setScrollOffset(currentOffset);
}}
The scrollToOffset method seems to trigger onScroll to think its going in the opposite direction which causes oscillations, which from the code makes sense. Any ideas to make this work correctly?
Edit:
Here is a link to a video of this happening
When I scroll up/down to unhide/hide the top and bottom bar, you'll see the content in the center jump up/down. It makes sense why this is happening, the height of the center content changes which causes the jump. I want the content to stay scrolled in the same position when changing the height.
I want to query for data based on the H3 hexagons that are visible on the viewport (and for new data on each viewport change). Is there anyway to achieve this with react-map-gl and deck.gl?
To get the hexagons inside the viewport, you need to get the bounding box of the current viewport. If you have the current viewport as {latitude, longitude, zoom, width, height} (which you probably have in your component state if you're using react-map-gl), you can get the viewport using viewport-mercator-project:
import WebMercatorViewport from 'viewport-mercator-project';
function bboxFromViewport(viewport) {
const {width, height} = viewport;
const projection = new WebMercatorViewport(viewport);
const [west, north] = projection.unproject([0, 0]);
const [east, south] = projection.unproject([width, height]);
return {north, south, east, west};
}
Then you can use the bounding box with h3.polyfill to get the list of contained hexagons at a given resolution:
const nw = [north, west];
const ne = [north, east];
const sw = [south, west];
const se = [south, east];
const hexes = h3.polyfill([nw, ne, se, sw], resolution);
Depending on your use case, you might want to expand the bounding box before calling polyfill, to get additional data outside the immediate viewport.
You also probably want to bound this on the viewport extent somehow, or you could end up with millions of hexagons on zoom out. One cheap hack I've used for this is to take a very rough estimate of the number of hexagons we'll get, and avoid calling polyfill if it's too high:
// Inexact, but it doesn't matter for our purposes
const KM_PER_DEGREE_LAT = 111.2;
function estimateHexagonsInBBox(bbox, width, height, res) {
// This is an extremely rough estimate, but we're just trying
// to get a reasonable order of magnitude
const aspect = width / height;
const latKm = (bbox.north - bbox.south) * KM_PER_DEGREE_LAT;
const lonKm = latKm * aspect;
return (latKm * lonKm) / h3.hexArea(res, h3.UNITS.km2);
}
I'm trying to make an SVG element draggable inside but PanResponder doesn't account for the SVG viewBox causing the dragged element to not follow the touch around the screen.
I've tried utilizing the X and Y values of the touch event to affect the X and Y value of the SVG element, but get a worse effect than when I use the PanResponder. When I switched to using just the X and Y values of the touch event I tried to convert the touch event X and Y to the SVG coordinates by using an equation I found on svgwg.org.
viewBox: "0 0 960.1 1856.51"
Code used when I was converting X Y values to SVG cordinates
svgXYConvert = (eX, eY) =>{
let eW = this.props.width;
let eH = this.props.height;
let [vbX, vbY, vbW, vbH] = this.props.viewBox.split(" ");
// Calculate the scale of elements and vb
let scaleX = eW/vbW;
let scaleY = eH/vbH;
// translation points
let translateX = eX - (vbX * scaleX);
let translateY = eY - (vbY * scaleY);
return [translateX, translateY];
}
PanResponder component
import React from 'react';
import {PanResponder, Animated} from 'react-native';
import {Image, G, Rect} from 'react-native-svg';
const AnimatedG = Animated.createAnimatedComponent(G);
class DragImg extends React.Component {
constructor(props) {
super(props)
this.state = {
pan: new Animated.ValueXY({x: this.props.x, y: this.props.y}),
x: this.props.x,
y: this.props.y,
}
}
componentWillMount() {
this._panResponder = PanResponder.create({
onPanResponderTerminationRequest: () => false,
onStartShouldSetPanResponder: (e, gesture) => true,
onPanResponderGrant: (e, gesture) => {
this.state.pan.setOffset(this.state.pan.__getValue());
},
onPanResponderMove: Animated.event([
null, { dx: this.state.pan.x, dy: this.state.pan.y}
])
},
onPanResponderRelease: (e) => {
this.state.pan.flattenOffset();
}
})
}
render(){
let imgStyle = {transform: this.state.pan.getTranslateTransform()};
return <AnimatedG style={imgStyle} {...this._panResponder.panHandlers} x={this.state.x} y={this.state.y}>
<Image href={this.props.href} height={this.props.height} width={this.props.width} />
<Rect fill="transparent" height={this.props.height} width={this.props.width}/>
</AnimatedG>
}
}
export default DragImg;
When this is rendered inside of an SVG that is 100% height of the device, I am forcing landscape on an iPad, I allow them to zoom the SVG that is being used to see the details clearer. If they zoom in where the SVG takes up the entire screen the element moves at the right speed with the PanResponder and follows the touch perfectly almost, but if they are zoomed out or at the default screen we show them where the entire SVG is visible the dragged element moves slowly and doesn't track well.
I'm not sure what I should be doing differently to get the SVG element to track well regardless of if they are zoomed in or out on the SVG.
I made some similar code. I added an Animated.View with position: absolute so I move it and in the same time the SVG Circleis moved inside of the SVG area. To do it, I scaled the SVG size to have a perfect size with the maxWidth and minWidth. Also, the SVG must have this property: preserveAspectRatio="xMinYMin"its because it need to start in (0,0) as start point.
You can see it working here: https://snack.expo.io/#albertcito/svg-pan-responder