Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
xurban42 authored May 30, 2024
2 parents ebe20b4 + 0a51356 commit 36648f6
Show file tree
Hide file tree
Showing 8 changed files with 647 additions and 399 deletions.
217 changes: 106 additions & 111 deletions example/package-lock.json

Large diffs are not rendered by default.

29 changes: 28 additions & 1 deletion example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,21 @@ const TakePhotoButton = styled(Button)`
}
`;

const TorchButton = styled(Button)`
background: url('https://img.icons8.com/ios/50/000000/light.png');
background-position: center;
background-size: 50px;
background-repeat: no-repeat;
width: 80px;
height: 80px;
border: solid 4px black;
border-radius: 50%;
&.toggled {
background-color: rgba(0, 0, 0, 0.3);
}
`;

const ChangeFacingCameraButton = styled(Button)`
background: url(https://img.icons8.com/ios/50/000000/switch-camera.png);
background-position: center;
Expand Down Expand Up @@ -133,6 +148,7 @@ const App = () => {
const camera = useRef<CameraType>(null);
const [devices, setDevices] = useState<MediaDeviceInfo[]>([]);
const [activeDeviceId, setActiveDeviceId] = useState<string | undefined>(undefined);
const [torchToggled, setTorchToggled] = useState<boolean>(false);

useEffect(() => {
(async () => {
Expand All @@ -155,6 +171,7 @@ const App = () => {
<Camera
ref={camera}
aspectRatio="cover"
facingMode="environment"
numberOfCamerasCallback={(i) => setNumberOfCameras(i)}
videoSourceDeviceId={activeDeviceId}
errorMessages={{
Expand Down Expand Up @@ -192,10 +209,20 @@ const App = () => {
if (camera.current) {
const photo = camera.current.takePhoto();
console.log(photo);
setImage(photo);
setImage(photo as string);
}
}}
/>
{camera.current?.torchSupported && (
<TorchButton
className={torchToggled ? 'toggled' : ''}
onClick={() => {
if (camera.current) {
setTorchToggled(camera.current.toggleTorch());
}
}}
/>
)}
<ChangeFacingCameraButton
disabled={numberOfCameras <= 1}
onClick={() => {
Expand Down
4 changes: 3 additions & 1 deletion example/src/Camera/components/Camera/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,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;
};
231 changes: 181 additions & 50 deletions example/src/Camera/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,43 @@ See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */

function __awaiter(thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}

function __generator(thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
}

function __makeTemplateObject(cooked, raw) {
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
return cooked;
Expand Down Expand Up @@ -47,18 +84,50 @@ var Camera = React.forwardRef(function (_a, ref) {
} : _f, _g = _a.videoReadyCallback, videoReadyCallback = _g === void 0 ? function () { return null; } : _g;
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];
useEffect(function () {
numberOfCamerasCallback(numberOfCameras);
}, [numberOfCameras]);
var switchTorch = function (on) {
if (on === void 0) { on = false; }
return __awaiter(void 0, void 0, void 0, function () {
var supportedConstraints, track, _a;
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];
supportedConstraints = navigator.mediaDevices.getSupportedConstraints();
track = stream.getTracks()[0];
if (!(supportedConstraints && 'torch' in supportedConstraints && track)) return [3 /*break*/, 4];
_b.label = 1;
case 1:
_b.trys.push([1, 3, , 4]);
return [4 /*yield*/, track.applyConstraints({ advanced: [{ torch: on }] })];
case 2:
_b.sent();
return [2 /*return*/, true];
case 3:
_a = _b.sent();
return [2 /*return*/, false];
case 4: return [2 /*return*/, false];
}
});
});
};
useEffect(function () {
switchTorch(torch);
}, [torch]);
useImperativeHandle(ref, function () { return ({
takePhoto: function () {
var _a, _b, _c, _d;
takePhoto: function (type) {
var _a, _b, _c, _d, _e;
if (numberOfCameras < 1) {
throw new Error(errorMessages.noCameraAccessible);
}
Expand All @@ -69,7 +138,7 @@ var Camera = React.forwardRef(function (_a, ref) {
var canvasWidth = ((_c = container === null || container === void 0 ? void 0 : container.current) === null || _c === void 0 ? void 0 : _c.offsetWidth) || 1280;
var canvasHeight = ((_d = container === null || container === void 0 ? void 0 : container.current) === null || _d === void 0 ? void 0 : _d.offsetHeight) || 1280;
var canvasAR = canvasWidth / canvasHeight;
var sX = void 0, sY = void 0, sW = void 0, sH = void 0;
var sX = void 0, sY = void 0, sW = void 0, sH = void 0, imgData = void 0;
if (playerAR > canvasAR) {
sH = playerHeight;
sW = playerHeight * canvasAR;
Expand All @@ -84,11 +153,20 @@ var Camera = React.forwardRef(function (_a, ref) {
}
canvas.current.width = sW;
canvas.current.height = sH;
var context = canvas.current.getContext('2d');
if (context && (player === null || player === void 0 ? void 0 : player.current)) {
context.drawImage(player.current, sX, sY, sW, sH, 0, 0, sW, sH);
if (!context.current) {
context.current = canvas.current.getContext('2d', { willReadFrequently: true });
}
if (context.current && (player === null || player === void 0 ? void 0 : player.current)) {
context.current.drawImage(player.current, sX, sY, sW, sH, 0, 0, sW, sH);
}
switch (type) {
case 'imgData':
imgData = (_e = context.current) === null || _e === void 0 ? void 0 : _e.getImageData(0, 0, sW, sH);
break;
default: /* base64url */
imgData = canvas.current.toDataURL('image/jpeg');
break;
}
var imgData = canvas.current.toDataURL('image/jpeg');
return imgData;
}
else {
Expand All @@ -109,11 +187,18 @@ var Camera = React.forwardRef(function (_a, ref) {
getNumberOfCameras: function () {
return numberOfCameras;
},
toggleTorch: function () {
var torchVal = !torch;
setTorch(torchVal);
return torchVal;
},
torchSupported: torchSupported,
}); });
useEffect(function () {
initCameraStream(stream, setStream, currentFacingMode, videoSourceDeviceId, setNumberOfCameras, setNotSupported, setPermissionDenied);
}, [currentFacingMode, videoSourceDeviceId]);
useEffect(function () {
switchTorch(false).then(function (success) { return setTorchSupported(success); });
if (stream && player && player.current) {
player.current.srcObject = stream;
}
Expand All @@ -135,51 +220,97 @@ var Camera = React.forwardRef(function (_a, ref) {
React.createElement(Canvas, { ref: canvas }))));
});
Camera.displayName = 'Camera';
var initCameraStream = function (stream, setStream, currentFacingMode, videoSourceDeviceId, setNumberOfCameras, setNotSupported, setPermissionDenied) {
var _a;
// stop any active streams in the window
if (stream) {
stream.getTracks().forEach(function (track) {
track.stop();
});
}
var constraints = {
audio: false,
video: {
deviceId: videoSourceDeviceId ? { exact: videoSourceDeviceId } : undefined,
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));
})
.catch(function (err) {
handleError(err, setNotSupported, setPermissionDenied);
});
}
else {
var getWebcam = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia;
if (getWebcam) {
getWebcam(constraints, function (stream) {
setStream(handleSuccess(stream, setNumberOfCameras));
}, function (err) {
handleError(err, setNotSupported, setPermissionDenied);
});
var shouldSwitchToCamera = function (currentFacingMode) { return __awaiter(void 0, void 0, void 0, function () {
var cameras;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
cameras = [];
if (!(currentFacingMode === 'environment')) return [3 /*break*/, 2];
return [4 /*yield*/, navigator.mediaDevices.enumerateDevices().then(function (devices) {
var videoDevices = devices.filter(function (i) { return i.kind == 'videoinput'; });
videoDevices.forEach(function (device) {
var capabilities = device.getCapabilities();
if (capabilities.facingMode && capabilities.facingMode.indexOf('environment') >= 0 && capabilities.deviceId) {
cameras.push(capabilities.deviceId);
}
});
})];
case 1:
_a.sent();
_a.label = 2;
case 2:
if (cameras.length > 1) {
return [2 /*return*/, cameras.pop()];
}
return [2 /*return*/, undefined];
}
else {
setNotSupported(true);
});
}); };
var initCameraStream = function (stream, setStream, currentFacingMode, videoSourceDeviceId, setNumberOfCameras, setNotSupported, setPermissionDenied) { return __awaiter(void 0, void 0, void 0, function () {
var cameraDeviceId, switchToCamera, constraints, getWebcam;
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
// stop any active streams in the window
if (stream) {
stream.getTracks().forEach(function (track) {
track.stop();
});
}
return [4 /*yield*/, shouldSwitchToCamera(currentFacingMode)];
case 1:
switchToCamera = _b.sent();
if (switchToCamera) {
cameraDeviceId = switchToCamera;
}
else {
cameraDeviceId = videoSourceDeviceId ? { exact: videoSourceDeviceId } : undefined;
}
constraints = {
audio: false,
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));
})
.catch(function (err) {
handleError(err, setNotSupported, setPermissionDenied);
});
}
else {
getWebcam = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia;
if (getWebcam) {
getWebcam(constraints, function (stream) { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
setStream(handleSuccess(stream, setNumberOfCameras));
return [2 /*return*/];
});
}); }, function (err) {
handleError(err, setNotSupported, setPermissionDenied);
});
}
else {
setNotSupported(true);
}
}
return [2 /*return*/];
}
}
};
});
}); };
var handleSuccess = function (stream, setNumberOfCameras) {
navigator.mediaDevices
.enumerateDevices()
Expand Down
Loading

0 comments on commit 36648f6

Please sign in to comment.