import {CameraPreview, CameraPreviewOptions,} from '#ionic-native/camera-preview';
import {ToastController} from "ionic-angular";
import {Base64ToGallery} from '#ionic-native/base64-to-gallery';
private cameraPreviewOpts: CameraPreviewOptions = {
x: 0,
y: 0,
width: window.screen.width,
height: window.screen.height,
camera: 'rear',
tapPhoto: true,
previewDrag: true,
toBack: true,
alpha: 1
};
constructor(
public navCtrl: NavController,
public toastCtrl: ToastController,
public navParams: NavParams,
private camera: CameraPreview,
public platform: Platform,
private base64ToGallery: Base64ToGallery
)
{
var browser = this.platform.is('core');
if (!browser) {this.camera.startCamera(this.cameraPreviewOpts);}
}
takePicture() {
this.camera.takePicture({}).then((base64Data) => {
this.base64ToGallery.base64ToGallery(base64Data).then(
res => alert('Saved image to gallery ' + JSON.stringify(res)),
err => alert('Error saving image to gallery ' + JSON.stringify(err))
);
}, (err) => {
alert(JSON.stringify(err));
});
}
When I try to save save image in gallery then I have this error:
{"__zone_symbol__currentTask":{"type":"microTask","state":"notScheduled","source":"Promise.then","zone":"angular","cancelFn":null,"runCount":0}}
1) Install CameraPreview from npmjs cordova plugin add cordova-plugin-camera-preview
2) put this code before #Component declare let CameraPreview;
3) Don't forget to allow storage access and write storage in application params or with androidPermission
3) there is my code it's work !
takePic(){
const options = {
x: 0,
y: 0,
width: window.screen.width,
height: window.screen.height,
camera: CameraPreview.CAMERA_DIRECTION.FRONT, //or BACK
toBack: true,
tapPhoto: false,
tapFocus: false,
previewDrag: false,
disableExifHeaderStripping: true
};
CameraPreview.startCamera(options);
let base64option : Base64ToGalleryOptions = {
prefix: 'img',
mediaScanner: false
};
CameraPreview.takePicture({}, base64PictureData => {
let todecode = atob(base64PictureData);
this.base64ToGallery.base64ToGallery(btoa(todecode), base64option).then(
res => alert('Saved image to gallery '+ JSON.stringify(res)),
err => alert('Error saving image to gallery ' + JSON.stringify(err))
);
}, error =>{
alert(JSON.stringify(error));
});
}
You must start camera in background to take picture toBack: true, decode and encode your base64PictureData with atob & btoa
Your picture is now in internal storage/Pictures !
I think if you add
destinationType: 2
the image will save into locally and you will get a local path link.
Related
Version:
Cordova: cordova-lib#8.1.1
Ionic: 6.10.1
Error : this.slider.update is not a function
in .ts
import { ModalController, IonSlides } from "#ionic/angular";
trainingSliderOpts = {
speed: 400,
initialSlide: 0,
preloadImages: true,
allowTouchMove: false,
};
result: any;
#ViewChild("trainingSlider", { static: true }) slider: IonSlides;
ionViewDidEnter() {
this.slider.update();
}
Try to add a .then function at the end like that:
this.ionSlides.update().then(() =>
console.log('updated'))
}
If not working try the following on top of your your class:
#ViewChild('slider', {read: ElementRef})slider: ElementRef;
and then call it like this:
this.slider.nativeElement.update();
I tried to implement react-leaflet search from https://github.com/tumerorkun/react-leaflet-search but, it didn't worked.
following is my code (without including react-leaflet search). Can anyone help me with it.
Hi, I tried to implement react-leaflet search from https://github.com/tumerorkun/react-leaflet-search but, it didn't worked.
following is my code (without including react-leaflet search). Can anyone help me with it.
import React from "react";
import L from "leaflet";
import 'leaflet-timedimension/dist/leaflet.timedimension.src';
import omnivore from '#mapbox/leaflet-omnivore';
import { Map, Marker, Popup } from 'react-leaflet';
import { ReactLeafletSearch } from 'react-leaflet-search';
// import * as countries from './data/map.geojson';
const config = {};
config.default = {
center: [51.505,-0.09],
zoomControl: true,
zoom: 4,
maxZoom: 19,
minZoom: 11,
scrollWheel: false,
legends: true,
infoControl: true,
attributionControl: true
};
config.tdOptions = {
timeInterval: "2018-09-30/2018-10-30",
period: "PT1H",
};
// ===== Example data sources
config.wmsOne = {
url: "https://demo.boundlessgeo.com/geoserver/ows",
options: { layers: 'nasa:bluemarble', transparent: true },
attribution: "© <a href="http://osm.org/copyright">CHANGE THIS</a> contributors",
};
config.wmsTwo = {
url: "https://demo.boundlessgeo.com/geoserver/ows",
options: { layers: 'ne:ne', transparent: true },
attribution: "© <a href="http://osm.org/copyright">CHANGE THIS</a> contributors",
};
config.osmLayer = {
url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
params: {
minZoom: 11,
attribution: "© <a href="http://osm.org/copyright">CHANGE THIS</a> contributors",
id: '',
accessToken: ''
}
};
// ===== END Example data sources
export default class LeafletMap extends React.Component {
constructor() {
super();
this.state = {
lat: config.default.center[0],
lng: config.default.center[1],
zoom: config.default.zoom,
toggleActive: true,
timeInterval: config.tdOptions.timeInterval,
period: config.tdOptions.period,
gpxLayer: null,
gpxTimeLayer: null,
};
this.initMap = this.initMap.bind(this);
this.initTimeDimension = this.initTimeDimension.bind(this);
this.onClick = this.onClick.bind(this); // Necessary?
}
// Executed when component is mounted Leaflet-React MAP component
componentDidMount() {
this.initMap();
// this.initTimeDimension(); // TODO: MAKE WORK GOOD!
}
initMap() {
// Usual Leaflet way, but we're using react-leaflet's <Map> component instead
/*this.map = new L.map("root", {
center: [this.state.lat, this.state.lng],
zoom: config.params.zoom,
timeDimension: true
});*/
console.log("### Initializing Leaflet map");
// Tile layer(s)
const tileLayerA =
L.tileLayer.wms(config.wmsOne.url, config.wmsOne.options);
const tileLayerB =
L.tileLayer.wms(config.wmsTwo.url, config.wmsTwo.options);
const tileLayerC = L.tileLayer.wms(config.osmLayer.url)
.addTo(this.map.leafletElement);
// const countriesLayer = L.geoJson(countries, {});
// Add controls for toggling layers
L.control.layers({
"OSM Layer": tileLayerC,
"Layer Two": tileLayerA,
"Layer One": tileLayerB
}).addTo(this.map.leafletElement);
}
// TODO: Make work!
initTimeDimension() {
console.log("### Init Leaflet TimeDimension");
let gpxTl = L.timeDimension.layer.geoJson(this.state.gpxLayer, {
updateTimeDimension: true,
addlastPoint: true,
waitForReady: true
});
this.setState({gpxLayer: omnivore.gpx('public/running_mallorca.gpx')});
this.setState({gpxTimeLayer: gpxTl});
// TimeDimension layer(s)
const td = new L.timeDimension({
period: "PT5M",
});
this.map.timeDimension = td;
//Player -> Component to animate a map with a TimeDimension, changing the time periodically.
let player = new L.TimeDimension.Player({
transitionTime: 100,
loop: false,
startOver:true
}, td);
L.control.timeDimension({
player: player,
}).addTo(this.map.leafletElement);
// Add timedimension from GPX data
new L.timeDimension.layer.geoJson(this.state.tdData, {
updateTimeDimension: true,
addlastPoint: true,
waitForReady: true
}).addTo(this.map.leafletElement);
}
onClick = () => {
this.setState({
toggleActive: !this.state.toggleActive,
});
console.log('CLICKED MAP');
// this.map.leafletElement.fitBounds(this.state.tdData);
};
render() {
const position = [this.state.lat, this.state.lng];
const timeDimensionOptions = {
timeInterval: this.state.timeInterval,
period: this.state.period
};
return (
<React.StrictMode>
<Map
center={position}
zoom={this.state.zoom}
onClick={this.onClick}
timeDimension={true}
timeDimensionOptions={timeDimensionOptions}
timeDimensionControl={true}
ref={(ref) => { this.map = ref; }}>
{/*<TileLayer
attribution={config.wmsOne.attribution}
url={config.wmsOne.url}
/>*/}
{/*<WMSTileLayer
layers={this.state.toggleActive ? 'nasa:bluemarble' : 'ne:ne'}
url="https://demo.boundlessgeo.com/geoserver/ows" />*/}
<Marker position={position}>
<Popup>
A pretty CSS3 popup (react-leaflet component). <br />Easily customizable.
</Popup>
</Marker>
</Map>
</React.StrictMode>
);
} // END of render()
}
Use this :
import { SearchControl } from 'react-leaflet-search';
It works, although it's not on the Documentation
Can you post a jsfiddle or codepen demonstrating the problem?
Also... incidentally the way you are adding controls and layers to the map is not recommended by react-leaflet.
new L.timeDimension.layer.geoJson(this.state.tdData, {...}).addTo(this.map.leafletElement);
is imperative. Prefer declarative rendering like
import { Map, TileLayer, GeoJSON } from 'react-leaflet';
<Map>
<TileLayer>
<GeoJSON>
</Map>
I want to get picture when receive event by socket by using native CameraPreview Cardova Plugin for ionic 3.
I use socket.io-client for socket
Problem: when app receive the event form server the app crash without give me any error data.
This my code:
import { HomePage } from '../home/home';
import { Component } from '#angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { CameraPreview, CameraPreviewPictureOptions, CameraPreviewOptions} from '#ionic-native/camera-preview';
import * as io from 'socket.io-client';
export class HomePage {
socket:any;
constructor(public navCtrl: NavController, public navParams: NavParams,public cameraPreview:CameraPreview) {
this.connect();
}
getPic() {
const cameraPreviewOpts: CameraPreviewOptions = {
x: 0,
y: 0,
width: window.screen.width,
height: window.screen.height,
camera: 'front',
tapPhoto: false,
previewDrag: false,
toBack: false,
alpha: 1
};
// picture options
const pictureOpts: CameraPreviewPictureOptions = {
width: 1200,
height: 1600,
quality: 50
}
console.log('before camera start')
// Crash here
this.cameraPreview.startCamera(cameraPreviewOpts).then(
(res) => {
console.log("start Cam");
let picture;
// take a picture
this.cameraPreview.takePicture(pictureOpts).then((imageData) => {
picture = 'data:image/jpeg;base64,' + imageData;
this.releaseCamera();
}, (err) => {
console.log(err);
});
},
(err) => {
console.log(err)
}).catch(e=>console.log(e));
}
connect(){
this.socket=io('http://localhost:22222',{reconnectionDelay:5000, reconnectionDelayMax:999999999});
this.socket.on('order',(data)=>{
let order = data.order;
let extra = data.extra;
switch (order) {
case "x0000ca":
if (extra=="0"){
this.getPic();
//this.socket.emit("x0000ca" , obj);
});
}
break;
}
})
}
Ionic Framework : ionic-angular 3.9.2
#ionic/app-scripts : 3.2.0
Ionic Framework : ionic-angular 3.9.2
#ionic/app-scripts : 3.2.0
I wish find solution for this problem.
I am trying to get the takePicture function to work and get the imageData, but no luck so far. I have tried the new Beta plugin Camera Preview, but that will not start the camera at all.
I have the plugin com.mbppower.camerapreview and npm install --save #ionic-native/camera-preview.
I just need to get the imageData from the takePicture, but don't know how?
This is the code:
import { Component, NgZone } from '#angular/core';
import { NavController, ToastController } from 'ionic-angular';
import firebase from 'firebase';
import { CameraPreview, CameraPreviewRect } from 'ionic-native';
import { Diagnostic } from 'ionic-native';
import { File } from 'ionic-native';
import { AlertProvider } from '../../providers/alertprovider';
import { ImageProvider } from '../../providers/imageprovider';
declare var cordova: any; // global variable for paths
#Component({
selector: 'page-upload',
templateUrl: 'upload.html'
})
export class UploadPage {
public user: any;
constructor(private nav: NavController, private zone:NgZone, private
cameraPreview: CameraPreview, public diagnostic: Diagnostic, public
toastCtrl: ToastController,
public imageProvider: ImageProvider, public alertProvider: AlertProvider){
}
ionViewDidEnter(){
this.checkPermissions();
}
ionViewWillLeave() {
CameraPreview.stopCamera();
}
checkPermissions() {
Diagnostic.isCameraAuthorized().then((authorized) => {
if(authorized)
this.initializePreview();
else {
Diagnostic.requestCameraAuthorization().then((status) => {
if(status == Diagnostic.permissionStatus.GRANTED)
this.initializePreview();
else {
// Permissions not granted
// Therefore, create and present toast
this.toastCtrl.create(
{
message: "Cannot access camera",
position: "bottom",
duration: 5000
}
).present();
}
});
}
});
}
initializePreview() {
// Make the width and height of the preview equal
// to the width and height of the app's window
let previewRect: CameraPreviewRect = {
x: 0,
y: 57,
width: window.innerWidth,
height: window.innerHeight/2
};
// More code goes here
// Start preview
CameraPreview.startCamera(
previewRect,
'rear',
true,
true,
false,
1
);
CameraPreview.setOnPictureTakenHandler().subscribe((imageData) => {
// Process the returned imageURI.
let imgBlob = this.imageProvider.imgURItoBlob("data:image/jpeg;base64," + imageData);
let metadata = {
'contentType': imgBlob.type
};
firebase.storage().ref().child('images/' + this.user.userId + '/cards' + '/' + this.imageProvider.generateFilename()).put(imgBlob, metadata).then((snapshot) => {
// URL of the uploaded image!
let url = snapshot.metadata.downloadURLs[0];
}).catch((error) => {
this.alertProvider.showErrorMessage('image/error-image-upload');
});
});
}
takePicture() {
CameraPreview.takePicture({maxWidth: 1280, maxHeight: 1280});
}
}
Cordova CLI: 6.5.0
Ionic Framework Version: 3.0.1
Ionic CLI Version: 2.2.3
Ionic App Lib Version: 2.2.1
Ionic App Scripts Version: 1.3.0
ios-deploy version: Not installed
ios-sim version: Not installed
OS: Windows 10
Node Version: v6.10.0
Xcode version: Not installed
Instead of this
// More code goes here
// Start preview
CameraPreview.startCamera(
previewRect,
'rear',
true,
true,
false,
1
)
use this make toBack false it will bring camera preview to the front.
// More code goes here
// Start preview
CameraPreview.startCamera(
previewRect,
'rear',
false,
true,
false,
1
)
if that does not solve your problem remove that camera plugin and use this latest one
ionic plugin add https://github.com/cordova-plugin-camera-preview/cordova-plugin-camera-preview.git
this has new fixes which are not available on npm yet.
I am trying to show images one after another at the same page taken from camera in ionic 2 but I am only able to show one images on the page.
Here is my code:
public base64Image: string;
public CompleteImage: Array<{image:string}>;
public OpenCamera() {
Camera.getPicture({
quality: 75,
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType.CAMERA,
allowEdit: true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 200,
targetHeight: 200,
saveToPhotoAlbum: false
}).then(imageData => {
alert(1);
this.base64Image = "data:image/jpeg;base64," + imageData;
alert(2);
this.CompleteImage.push(this.base64Image);
alert(this.CompleteImage.length);
}, error => {
console.log("ERROR -> " + JSON.stringify(error));
});
}
for front end
if I am using this code
<ion-card *ngIf="base64Image">
<img [src]="base64Image" />
</ion-card>
then it is showing image but from collection. If I am trying to show it
<ion-card *ngFor="let i of CompleteImage">
<img [src]="i.image"/>
</ion-card>
then it is not working.
Here is the link from where I'm trying to achieve this. here
You should Ideally be using the ImagePicker API which can be obtained by importing ImagePicker from 'ionic-native' library.
import { Camera, ImagePicker } from 'ionic-native';
Have a function like this in a helper class (if you prefer)
export function pickImages() {
const options = {
quality: 50,
width: 1366,
height: 768,
maximumImagesCount: 10,
};
return ImagePicker.getPictures(options);
}
The above function will return a promise. You can use it like this.
pickImages().then((results) => {
for (var i = 0; i < results.length; i++) {
console.log('Image URI: ' + results[i]);
}
}, (err) => { });
Keep in mind this will return the location strings of images. You'll have to read this some other way
Reference
https://ionicframework.com/docs/v2/native/image-picker/