Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions dist/components/Camera/styles.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ export declare const Container: import("styled-components").StyledComponent<"div
export declare const ErrorMsg: import("styled-components").StyledComponent<"div", any, {}, never>;
export declare const Cam: import("styled-components").StyledComponent<"video", any, {
mirrored: boolean;
objectFit?: string | undefined;
}, never>;
export declare const Canvas: import("styled-components").StyledComponent<"canvas", any, {}, never>;
6 changes: 5 additions & 1 deletion dist/components/Camera/types.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/// <reference types="react" />
export declare type FacingMode = 'user' | 'environment';
export declare type AspectRatio = 'cover' | number;
export declare type ObjectFit = React.CSSProperties['objectFit'];
export declare type Stream = MediaStream | null;
export declare type SetStream = React.Dispatch<React.SetStateAction<Stream>>;
export declare type SetNumberOfCameras = React.Dispatch<React.SetStateAction<number>>;
Expand All @@ -9,6 +10,7 @@ export declare type SetPermissionDenied = React.Dispatch<React.SetStateAction<bo
export interface CameraProps {
facingMode?: FacingMode;
aspectRatio?: AspectRatio;
cameraObjectFit?: ObjectFit;
numberOfCamerasCallback?(numberOfCameras: number): void;
videoSourceDeviceId?: string | undefined;
errorMessages: {
Expand All @@ -20,7 +22,9 @@ export interface CameraProps {
videoReadyCallback?(): void;
}
export declare type CameraType = React.ForwardRefExoticComponent<CameraProps & React.RefAttributes<unknown>> & {
takePhoto(): string;
takePhoto(type?: 'base64url' | 'imgData'): string | ImageData;
switchCamera(): FacingMode;
getNumberOfCameras(): number;
toggleTorch(): boolean;
torchSupported: boolean;
};
263 changes: 203 additions & 60 deletions dist/index.cjs.js

Large diffs are not rendered by default.

263 changes: 203 additions & 60 deletions dist/index.esm.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ const App = () => {
<Camera
ref={camera}
aspectRatio="cover"
cameraObjectFit="contain"
facingMode="environment"
numberOfCamerasCallback={(i) => setNumberOfCameras(i)}
videoSourceDeviceId={activeDeviceId}
Expand Down
1 change: 1 addition & 0 deletions example/src/Camera/components/Camera/styles.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ export declare const Container: import("styled-components").StyledComponent<"div
export declare const ErrorMsg: import("styled-components").StyledComponent<"div", any, {}, never>;
export declare const Cam: import("styled-components").StyledComponent<"video", any, {
mirrored: boolean;
objectFit?: string | undefined;
}, never>;
export declare const Canvas: import("styled-components").StyledComponent<"canvas", any, {}, never>;
2 changes: 2 additions & 0 deletions example/src/Camera/components/Camera/types.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/// <reference types="react" />
export declare type FacingMode = 'user' | 'environment';
export declare type AspectRatio = 'cover' | number;
export declare type ObjectFit = React.CSSProperties['objectFit'];
export declare type Stream = MediaStream | null;
export declare type SetStream = React.Dispatch<React.SetStateAction<Stream>>;
export declare type SetNumberOfCameras = React.Dispatch<React.SetStateAction<number>>;
Expand All @@ -9,6 +10,7 @@ export declare type SetPermissionDenied = React.Dispatch<React.SetStateAction<bo
export interface CameraProps {
facingMode?: FacingMode;
aspectRatio?: AspectRatio;
cameraObjectFit?: ObjectFit;
numberOfCamerasCallback?(numberOfCameras: number): void;
videoSourceDeviceId?: string | undefined;
errorMessages: {
Expand Down
48 changes: 30 additions & 18 deletions example/src/Camera/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,31 +68,41 @@ var Container = styled.div(templateObject_2 || (templateObject_2 = __makeTemplat
: "\n position: relative;\n padding-bottom: " + 100 / aspectRatio + "%;";
});
var ErrorMsg = styled.div(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n padding: 40px;\n"], ["\n padding: 40px;\n"])));
var Cam = styled.video(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n width: 100%;\n height: 100%;\n object-fit: cover;\n z-index: 0;\n transform: rotateY(", ");\n"], ["\n width: 100%;\n height: 100%;\n object-fit: cover;\n z-index: 0;\n transform: rotateY(", ");\n"])), function (_a) {
var Cam = styled.video(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n width: 100%;\n height: 100%;\n object-fit: ", ";\n z-index: 0;\n transform: rotateY(", ");\n"], ["\n width: 100%;\n height: 100%;\n object-fit: ", ";\n z-index: 0;\n transform: rotateY(", ");\n"])), function (_a) {
var objectFit = _a.objectFit;
return objectFit || 'cover';
}, function (_a) {
var mirrored = _a.mirrored;
return (mirrored ? '180deg' : '0deg');
});
var Canvas = styled.canvas(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n display: none;\n"], ["\n display: none;\n"])));
var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5;

var Camera = React.forwardRef(function (_a, ref) {
var _b = _a.facingMode, facingMode = _b === void 0 ? 'user' : _b, _c = _a.aspectRatio, aspectRatio = _c === void 0 ? 'cover' : _c, _d = _a.numberOfCamerasCallback, numberOfCamerasCallback = _d === void 0 ? function () { return null; } : _d, _e = _a.videoSourceDeviceId, videoSourceDeviceId = _e === void 0 ? undefined : _e, _f = _a.errorMessages, errorMessages = _f === void 0 ? {
var _b = _a.facingMode, facingMode = _b === void 0 ? 'user' : _b, _c = _a.aspectRatio, aspectRatio = _c === void 0 ? 'cover' : _c, _d = _a.cameraObjectFit, cameraObjectFit = _d === void 0 ? 'cover' : _d, _e = _a.numberOfCamerasCallback, numberOfCamerasCallback = _e === void 0 ? function () { return null; } : _e, _f = _a.videoSourceDeviceId, videoSourceDeviceId = _f === void 0 ? undefined : _f, _g = _a.errorMessages, errorMessages = _g === void 0 ? {
noCameraAccessible: 'No camera device accessible. Please connect your camera or try a different browser.',
permissionDenied: 'Permission denied. Please refresh and give camera permission.',
switchCamera: 'It is not possible to switch camera to different one because there is only one video device accessible.',
canvas: 'Canvas is not supported.',
} : _f, _g = _a.videoReadyCallback, videoReadyCallback = _g === void 0 ? function () { return null; } : _g;
} : _g, _h = _a.videoReadyCallback, videoReadyCallback = _h === void 0 ? function () { return null; } : _h;
var player = useRef(null);
var canvas = useRef(null);
var context = useRef(null);
var container = useRef(null);
var _h = useState(0), numberOfCameras = _h[0], setNumberOfCameras = _h[1];
var _j = useState(null), stream = _j[0], setStream = _j[1];
var _k = useState(facingMode), currentFacingMode = _k[0], setFacingMode = _k[1];
var _l = useState(false), notSupported = _l[0], setNotSupported = _l[1];
var _m = useState(false), permissionDenied = _m[0], setPermissionDenied = _m[1];
var _o = useState(false), torchSupported = _o[0], setTorchSupported = _o[1];
var _p = useState(false), torch = _p[0], setTorch = _p[1];
var _j = useState(0), numberOfCameras = _j[0], setNumberOfCameras = _j[1];
var _k = useState(null), stream = _k[0], setStream = _k[1];
var _l = useState(facingMode), currentFacingMode = _l[0], setFacingMode = _l[1];
var _m = useState(false), notSupported = _m[0], setNotSupported = _m[1];
var _o = useState(false), permissionDenied = _o[0], setPermissionDenied = _o[1];
var _p = useState(false), torchSupported = _p[0], setTorchSupported = _p[1];
var _q = useState(false), torch = _q[0], setTorch = _q[1];
var mounted = useRef(false);
useEffect(function () {
mounted.current = true;
return function () {
mounted.current = false;
};
}, []);
useEffect(function () {
numberOfCamerasCallback(numberOfCameras);
}, [numberOfCameras]);
Expand All @@ -103,7 +113,7 @@ var Camera = React.forwardRef(function (_a, ref) {
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!(stream && (navigator === null || navigator === void 0 ? void 0 : navigator.mediaDevices))) return [3 /*break*/, 4];
if (!(stream && (navigator === null || navigator === void 0 ? void 0 : navigator.mediaDevices) && !!mounted.current)) return [3 /*break*/, 4];
supportedConstraints = navigator.mediaDevices.getSupportedConstraints();
track = stream.getTracks()[0];
if (!(supportedConstraints && 'torch' in supportedConstraints && track)) return [3 /*break*/, 4];
Expand Down Expand Up @@ -195,7 +205,7 @@ var Camera = React.forwardRef(function (_a, ref) {
torchSupported: torchSupported,
}); });
useEffect(function () {
initCameraStream(stream, setStream, currentFacingMode, videoSourceDeviceId, setNumberOfCameras, setNotSupported, setPermissionDenied);
initCameraStream(stream, setStream, currentFacingMode, videoSourceDeviceId, setNumberOfCameras, setNotSupported, setPermissionDenied, !!mounted.current);
}, [currentFacingMode, videoSourceDeviceId]);
useEffect(function () {
switchTorch(false).then(function (success) { return setTorchSupported(success); });
Expand All @@ -214,7 +224,7 @@ var Camera = React.forwardRef(function (_a, ref) {
React.createElement(Wrapper, null,
notSupported ? React.createElement(ErrorMsg, null, errorMessages.noCameraAccessible) : null,
permissionDenied ? React.createElement(ErrorMsg, null, errorMessages.permissionDenied) : null,
React.createElement(Cam, { ref: player, id: "video", muted: true, autoPlay: true, playsInline: true, mirrored: currentFacingMode === 'user' ? true : false, onLoadedData: function () {
React.createElement(Cam, { ref: player, id: "video", muted: true, objectFit: cameraObjectFit, autoPlay: true, playsInline: true, mirrored: currentFacingMode === 'user' ? true : false, onLoadedData: function () {
videoReadyCallback();
} }),
React.createElement(Canvas, { ref: canvas }))));
Expand Down Expand Up @@ -247,7 +257,7 @@ var shouldSwitchToCamera = function (currentFacingMode) { return __awaiter(void
}
});
}); };
var initCameraStream = function (stream, setStream, currentFacingMode, videoSourceDeviceId, setNumberOfCameras, setNotSupported, setPermissionDenied) { return __awaiter(void 0, void 0, void 0, function () {
var initCameraStream = function (stream, setStream, currentFacingMode, videoSourceDeviceId, setNumberOfCameras, setNotSupported, setPermissionDenied, isMounted) { return __awaiter(void 0, void 0, void 0, function () {
var cameraDeviceId, switchToCamera, constraints, getWebcam;
var _a;
return __generator(this, function (_b) {
Expand All @@ -273,15 +283,15 @@ var initCameraStream = function (stream, setStream, currentFacingMode, videoSour
video: {
deviceId: cameraDeviceId,
facingMode: currentFacingMode,
width: { ideal: 1920 },
height: { ideal: 1920 },
},
};
if ((_a = navigator === null || navigator === void 0 ? void 0 : navigator.mediaDevices) === null || _a === void 0 ? void 0 : _a.getUserMedia) {
navigator.mediaDevices
.getUserMedia(constraints)
.then(function (stream) {
setStream(handleSuccess(stream, setNumberOfCameras));
if (isMounted) {
setStream(handleSuccess(stream, setNumberOfCameras));
}
})
.catch(function (err) {
handleError(err, setNotSupported, setPermissionDenied);
Expand All @@ -296,7 +306,9 @@ var initCameraStream = function (stream, setStream, currentFacingMode, videoSour
if (getWebcam) {
getWebcam(constraints, function (stream) { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
setStream(handleSuccess(stream, setNumberOfCameras));
if (isMounted) {
setStream(handleSuccess(stream, setNumberOfCameras));
}
return [2 /*return*/];
});
}); }, function (err) {
Expand Down
2 changes: 2 additions & 0 deletions src/components/Camera/Camera.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const Camera = React.forwardRef<unknown, CameraProps>(
{
facingMode = 'user',
aspectRatio = 'cover',
cameraObjectFit = 'cover',
numberOfCamerasCallback = () => null,
videoSourceDeviceId = undefined,
errorMessages = {
Expand Down Expand Up @@ -185,6 +186,7 @@ export const Camera = React.forwardRef<unknown, CameraProps>(
ref={player}
id="video"
muted={true}
objectFit={cameraObjectFit}
autoPlay={true}
playsInline={true}
mirrored={currentFacingMode === 'user' ? true : false}
Expand Down
4 changes: 2 additions & 2 deletions src/components/Camera/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ export const ErrorMsg = styled.div`
padding: 40px;
`;

export const Cam = styled.video<{ mirrored: boolean }>`
export const Cam = styled.video<{ mirrored: boolean; objectFit?: string }>`
width: 100%;
height: 100%;
object-fit: cover;
object-fit: ${({ objectFit }) => objectFit || 'cover'};
z-index: 0;
transform: rotateY(${({ mirrored }) => (mirrored ? '180deg' : '0deg')});
`;
Expand Down
2 changes: 2 additions & 0 deletions src/components/Camera/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export type FacingMode = 'user' | 'environment';
export type AspectRatio = 'cover' | number; // for example 16/9, 4/3, 1/1
export type ObjectFit = React.CSSProperties['objectFit'];
export type Stream = MediaStream | null;
export type SetStream = React.Dispatch<React.SetStateAction<Stream>>;
export type SetNumberOfCameras = React.Dispatch<React.SetStateAction<number>>;
Expand All @@ -8,6 +9,7 @@ export type SetPermissionDenied = React.Dispatch<React.SetStateAction<boolean>>;
export interface CameraProps {
facingMode?: FacingMode;
aspectRatio?: AspectRatio;
cameraObjectFit?: ObjectFit;
numberOfCamerasCallback?(numberOfCameras: number): void;
videoSourceDeviceId?: string | undefined;
errorMessages: {
Expand Down