React Leaflet map to PDF - reactjs

I can generate PNG file by using
https://www.npmjs.com/package/react-leaflet-easyprint
I need to generate PDF from PNG file.
How can I prevent download of the file and use this content to generate PDF file before download PNG file?
Is there maybe better library for this purpose?
There is also an option to use nodeJs and phantomJs, but in this case there will be code duplication.

The leaflet-easyprint library leverages the dom-to-image library.
https://github.com/rowanwins/leaflet-easyPrint/blob/gh-pages/src/index.js#L127
I suggest copying a bit of the code from there and using dom-to-image + filesaver to convert the dom to a base64 blob export as a pdf.
https://github.com/tsayen/dom-to-image#usage

For reference:
I used a combination of dom-to-image library and https://react-pdf.org/
Got a reference of the map, got its container. And passed it into dom-to-image and used the result in the reactPdf. I used an A4 landscape size and orientation.
const _a4PageSize= { height: 715, width: 1045 }
domtoimage
.toPng(mapRef.current.leafletElement.getContainer(), _a4PageSize)
.then(dataUrl => {
//pass dataUrl to reactpdf document here
})
.catch(err => console.log("to img err", err));
// reactpdf document
<Document >
<Page size="A4" orientation="landscape">
<Image src={{uri: dataUrl}}/>
</Page>
</Document>

Related

Why can I get an image from public folder but not a json file

I learn Reactjs and came across this
I have an images folder in the public React project created with create-react-app.
I place a json file and a jpg in it and I can use the jpg but not the json.
let photo = "./images/some.jpg";
let file = "./images/somejson.json";
The image works out of the box like
<img alt="image" src={photo} />
But the json cant be read I get Cannot read property 'label' of undefined
<h1 className="title">{file.basics.label}</h1>
And this is the json
{
"basics": {
"name": "Foo Bar",
"label": "Some label"
}
}
Please advice what is wrong?
You should import JSON file before use its properties, your file variable is just a path to a JSON file. If you are using create-react-app it has json-loader, if not you have to install it and configure your Webpack, I can assume you already use it, and then you can import JSON file and use it.
import json from "./images/somejson.json"
...
<img src={json.someSrc} />
you have to replace .json from public to src folder. And also you should export your variable file in the somejson.json file. and also you should import this variable too.
In your JS file, import your json file with correct path.
import file from './somejson.json';
If you need to retain this file in public/ and also use it in React app, add this library.
https://github.com/oklas/react-app-rewire-alias
import file from '../public/images/somejson.json';

How to reduce/compress three.js GLTF model size (with .bin and textures)?

I am loading a 3d model of a globe for my website and it takes forever to download.
I am using the GLTFLoader to load the model inside React.
loadModals() {
const loader = new GLTFLoader()
loader.load(
"/models/scene.gltf",
gltf => {
object = gltf.scene.children[0]
scene.add(object)
console.log("Model loaded")
},
xhr => {
console.log("Model loading...")
},
error => {
console.log("Model failed to load", error)
}
)
}
The files relevant to the 3d model include:
a textures folder of images (58.7MB)
scene.bin (1.2MB)
scene.gltf (10KB)
From research, it seems like if the model comes with a .bin file, it means the gltf isnt in compressed binary format. However, looking at tools such as gltf-pipeline online, I am not sure how to implement the compression when there are separate files like the textures folder and the scene.bin.
I am very new to three.js and implementation in the web, so any advice would be greatly appreciated.
Thanks!
If you just need to compress your texture there are multiple image compression website.
Why not used .glb format ? GLB file format is a binary form of GLTF that includes textures instead of referencing them as external images.
Sorry if I don't help you.
Since I haven't received any answers yet, my temporary solution is to use Photoshop to optimise the images in the textures folder first.
But this comes at a cost for a lower quality appearing model.

How to encode/compress gltf to draco

I want to compress/encode gltf file using draco programatically in threejs with reactjs. I dont want to use any commandline tool, I want it to be done programatically. Please suggest me a solution.
I tried using gltf-pipeline but its not working in client side. Cesium library was showing error when I used it in reactjs.
Yes, this is can be implemented with glTF-Transform. There's also an open feature request on three.js, not yet implemented.
First you'll need to download the Draco encoder/decoder libraries (the versions currently published to NPM do not work client side), host them in a folder, and then load them as global script tags. There should be six files, and two script tags (which will load the remaining files).
Files:
draco_decoder.js
draco_decoder.wasm
draco_wasm_wrapper.js
draco_encoder.js
draco_encoder.wasm
draco_encoder_wrapper.js
<script src="assets/draco_encoder.js"></script>
<script src="assets/draco_decoder.js"></script>
Then you'll need to write code to load a GLB file, apply compression, and do something with the compressed result. This will require first installing the two packages shown below, and then bundling the web application with your tool of choice (I used https://www.snowpack.dev/ here).
import { WebIO } from '#gltf-transform/core';
import { DracoMeshCompression } from '#gltf-transform/extensions';
const io = new WebIO()
.registerExtensions([DracoMeshCompression])
.registerDependencies({
'draco3d.encoder': await new DracoEncoderModule(),
'draco3d.decoder': await new DracoDecoderModule(),
});
// Load an uncompressed GLB file.
const document = await io.read('./assets/Duck.glb');
// Configure compression settings.
document.createExtension(DracoMeshCompression)
.setRequired(true)
.setEncoderOptions({
method: DracoMeshCompression.EncoderMethod.EDGEBREAKER,
encodeSpeed: 5,
decodeSpeed: 5,
});
// Create compressed GLB, in an ArrayBuffer.
const arrayBuffer = io.writeBinary(document); // ArrayBuffer
In the latest version of 1.5.0, what are these two files? draco_decoder_gltf.js and draco_encoder_gltf.js. Does this means we no longer need the draco_encoder and draco_decoder files? and how do we invoke the transcoder interface without using MeshBuilder. A simpler API would be musth better.

React Avatar Editor

I have a react component which uses DropZone.
Actions are like this:
Add image to DropZone Area.
Image added is uploaded using PHP and a URL is sent back to next step.
This step show the React Avatar Editor holding the URL to the uploaded image.
I have set up the Avatar area/component like this:
setEditorRef = (editor) => this.editor = editor
<AvatarEditor
ref={this.setEditorRef}
image={this.state.image} // URL to uploaded image
scale={this.state.scale}
position={this.state.position}
onPositionChange={this.handlePositionChange}
style={{width: '310px', height: '263px'}}
border={10}
color={[255, 255, 255, 0.8]} // RGBA
rotate={this.state.rotate}
/>
What I need (AFTER dragging the image around, scaling it or rotating) is to send the image within the canvas to a php script, and save it. I know how to do this, but I cannot figure out how to access the image "constrained" by the canvas?
I've tried Avatar Editor's solutions (mentioned on the github).
this.editor.getImageScaledToCanvas().toDataURL('image/jpeg', 1);
and
this.editor.getImage();
But using axios and
let formData = new FormData();
formData.append('file', linkToCanvas);
does not work. (LinkToCanvas) should be the image held by the Avatar Canvas.
I also have the following issue after Image upload (solving this one enables me to solve the first issue as well, as I know the orientation of the image shown):
When uploading (4mb+) image files, I strip the EXIF information, save the image and returns a URL to Avatar Editor pointing to the new image.
If the image is vertical - Avatar shows the image horizontally (even when removing the EXIF info from the jpegs). Any way to force React to load an image 1-to-1, as it is stored on my server?
Any help is HIGHLY appreciated, as I've been struggling with this for a week now :-(
I know it's a long question. But I'm hoping for a short answer.
Thanks
The problem is that editor is not added to references.
To fix this, declare editor before constructor
...
import AvatarEditor from 'react-avatar-editor';
class YourClassName extends React.Component<any, any> {
editor: AvatarEditor;
constructor(props: Props) {
...
change setEditorFunction to this
setEditorRef = (editor: any) => {
if (editor) {
this.editor = editor;
const img = this.editor.getImageScaledToCanvas().toDataURL();
console.log(img);
}
}
And the last step change reference in component
<AvatarEditor
image={this.state.image}
width={this.state.width}
height={this.state.height}
color={[0, 0, 0, 0.6]}
scale={this.state.scale}
rotate={this.state.rotate}
position={this.state.position}
borderRadius={this.state.borderRadius}
ref={(ref) => this.setEditorRef(ref)}
onLoadSuccess={this.loadSuccess}
/>
A workaround but maybe not the best solution to Avatar Editor forcing rotate on jpgs. I use php to detect EXIF data. Rotate if this is needed. Then create a png from the jpg. Then save it and unlink “old jpg”. And finally return its location to my react script.
This solves the rotation problem. So now I can crop/rotate the image on the canvas and using the
getCroppingRect()
I can retrieve x, y, width and height and handle crop serverside. Finally enabling me to store the crop area.
However a new problem is now issued, as the editor rotates the image around its canvas center, so even if I can retrieve coordinates for the cropscript, as well as the rotation angle, its still misplaced, as php’s rotateimage rotates on the image center.
Anyone know how to rotate an image on a canvas around the image center?

How do I use a captured image with react-native-camera

I can get the react-native-camera module to access the camera and save an image. However, I can't figure out how to display this image to the user.
What I'm trying:
Here I take the picture. This generates what looks to be a .jpg file in assets-library://....
_takePicture() {
var self = this;
this.refs.cam.capture(function(err, data) {
this.setState({photo: data});
console.log(err, data);
// data is "assets-library://asset/asset.JPG?id=########-####-####-####-##########&ext=JPG"
console.log('just took a picture');
});
}
However, If I try to render the image:
render: function() {
return(
<Image style={styles.image} source={{uri: this.state.photo}}/>
);
}
I get this error:
No suitable image URL loader found for assets-library://asset/asset.JPG?id=.......
How can I take a photo, save it to the current state of my application, and render it?
The solution was to enable the save to disk option vs. the save to cameraRoll option:
<Camera
captureTarget={Camera.constants.CaptureTarget.disk}
// Rest of Camera options here
/>
So, I was using the #YPCrumble answer for some time.
But now I have to save the image in my camera roll.
If anyone want to continue saving in camera roll, you have to manually link RTCCameraRoll library.
Documentation to link library here:
https://facebook.github.io/react-native/docs/linking-libraries-ios.html#manual-linking
It is so simple:
You can find the RCTImage.xcodeproj in your
node_modules/react-native/Libraries/CameraRoll
Drag and drop this file inside Libraries folder in your XCode project.
After that, click in your main project, and find in the right pane
"Build Phases".
Inside "Link Binary With Libraries", drag and drop the file called
"libRCTCameraRoll.a" from left pane -> Libraries ->
RTCCameraRoll.xcodeproj -> Products

Resources