I've come across quite a few packages and APIs for opening a stream and capturing images, but all of these solutions entail loading the feed in a component, so the 'camera' is an in-browser utility. Is there a way to open the phone's actual camera app outside the DOM?
I've come across quite a few packages and APIs for opening a stream and capturing images, but all of these solutions entail loading the feed in a component, so the 'camera' is an in-browser utility. Is there a way to open the phone's actual camera app outside the DOM?
Share Improve this question asked Jan 31, 2020 at 3:37 struenseestruensee 6061 gold badge10 silver badges18 bronze badges 2 |3 Answers
Reset to default 12Short answer:
<input type="file" accept="image/*" capture="environment">
Modern phone browsers can opt to use the camera app as input for <input type="file">
input, in lieu of a file-selection dialog, when you use the property accept="image/*"
. This will allow users to select their preferred input, but if you use the property capture
on the input element, the browser sees a hint to automatically use the camera without giving a choice at all. capture
can have a value as well, to hint which camera should be used:
Adding the
capture
attribute without a value let's the browser decide which camera to use, while the"user"
and"environment"
values tell the browser to prefer the front and rear cameras, respectively.The
capture
attribute works on Android and iOS, but is ignored on desktop. Be aware, however, that on Android this means that the user will no longer have the option of choosing an existing picture. The system camera app will be started directly, instead.
Once you have an input image, you can read it as you would any input file, e.g., with FileReader
.
Thanks to @apsillers for the answer. Here's a React-specific implementation for those who are trying to create a button that prompts actual camera load for photo-taking and not a video feed capture in-browser:
The button:
<div >
<label>
<input
style={{display: 'none'}}
type='file'
accept="image/*"
capture="environment"
onChange={this.handleImageChange}
/>
<YourCustomButton/>
</label>
</div>
Handler:
handleImageChange = (event) => {
this.setState({
image: URL.createObjectURL(event.target.files[0])
})
}
Thank you @apsillers and @struensee for the answers, I managed to do what I was looking for with both answers. However, there was something missing on @struensee answer, and I would like to contribute with my React solution:
import React, { useState, useRef } from "react";
const UploadImageComponent = () => {
const [imageObject, setImageObject] = useState(null);
const handleFileInput = useRef(null);
const handleClick = () => {
handleFileInput.current.click();
};
const handleImageChange = (event) => {
setImageObject({
imagePreview: URL.createObjectURL(event.target.files[0]),
imageFile: event.target.files[0],
});
};
return (
<div>
<button onClick={handleClick}>Upload Photo</button>
<label>
<input
style={{ display: "none" }}
type="file"
accept="image/*"
capture="environment"
ref={handleFileInput}
onChange={handleImageChange}
/>
</label>
{imageObject && <img src={imageObject.imagePreview} />}
</div>
);
};
export default UploadImageComponent;
The use of ref will ensure clicking on the button will trigger the onChange in the hidden input. The <img>
tag is there to display the image currently being uploaded.
<input type="file" accept="image/*" capture>
(then use FileReader in the usual way to read the file input) – apsillers Commented Jan 31, 2020 at 4:19