@glair/web-components
Version:
A collection of GLAIR's web components
229 lines (228 loc) • 7.27 kB
JavaScript
import { html as u } from "lit";
import { query as B, property as m, state as y, customElement as R } from "lit/decorators.js";
import { TailwindElement as _ } from "./tailwind.element.js";
const v = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGIAAABiCAYAAACrpQYOAAABBklEQVR4Ae3TUQ2EQBTAwH2XE4wvdKFj8UBI6MeMhaaz974Wn/stEoSIECJCiAghIoSIECJCiAghIoSIECJCiIj/euaYmXPxGkdECBEhRIQQEUJECBEhRIQQEUJECBEhRIQQEUJECBEhRIQQEUJECBEhRIQQEUJECBEhRIQQEUJECBEhRIQQEUJECBEhRIQQEUJECBEhRIQQEUJECBEhRIQQEUJECBEhRIQQEUJECBEhRIQQEUJECBEhRIQQEUJECBEhRIQQEUJECBEhRIQQEUJECBEhRIQQEUJECBEhRIQQEUJECBEhRIQQEUJECBEhRIQQEUJECBEhRIQQEUJECBEhRIQQETcExQXG6zjxjAAAAABJRU5ErkJggg==";
function J(e) {
const t = x(e);
return t && t.toDataURL("image/jpeg", 0.92);
}
function x(e) {
const {
ref: t,
width: s = 480,
height: i = 480,
mirrored: r = !1,
screenshotArea: h
} = e;
let p = s * h.width / 100, Q = i * h.height / 100, c = document.createElement("canvas");
c.width = p, c.height = Q;
let g = c.getContext("2d");
if (g && c) {
r && (g.translate(c.width, 0), g.scale(-1, 1));
const b = () => {
let n, d, l, E;
const A = s / i, I = t.videoWidth / t.videoHeight;
return A > I ? (n = t.videoWidth, d = t.videoWidth * (1 / A), l = 0, E = (t.videoHeight - d) / 2) : (n = t.videoHeight * A, d = t.videoHeight, l = (t.videoWidth - n) / 2, E = 0), { takeWidth: n, takeHeight: d, translateX: l, translateY: E } = (() => (l = l + Math.round(h.x / 100 * n), E = E + Math.round(h.y / 100 * d), n = n * h.width / 100, d = d * h.height / 100, r && (l = t.videoWidth - (l + n)), {
takeWidth: n,
takeHeight: d,
translateX: l,
translateY: E
}))(), {
takeWidth: n,
takeHeight: d,
translateX: l,
translateY: E
};
}, { takeWidth: f, takeHeight: C, translateX: w, translateY: U } = b();
g.drawImage(
t,
w,
U,
f,
C,
0,
0,
p,
Q
), r && (g.scale(-1, 1), g.translate(-c.width, 0));
}
return c;
}
var O = Object.defineProperty, M = Object.getOwnPropertyDescriptor, o = (e, t, s, i) => {
for (var r = i > 1 ? void 0 : i ? M(t, s) : t, h = e.length - 1, p; h >= 0; h--)
(p = e[h]) && (r = (i ? p(t, s, r) : p(r)) || r);
return i && r && O(t, s, r), r;
};
let a = class extends _ {
constructor() {
super(...arguments), this.width = 480, this.height = 480, this.facingMode = "user", this.mirrored = !1, this.screenshotArea = JSON.stringify({
x: 0,
y: 0,
width: 100,
height: 100,
enableOverlay: !1
}), this._isUserMedia = !1, this._stream = null, this._screenshotAreaObj = {
x: 0,
y: 0,
width: 100,
height: 100,
enableOverlay: !1
}, this._isMounted = !0;
}
async connectedCallback() {
super.connectedCallback(), await this.requestUserMedia(), this._screenshotAreaObj = this.preProcessScreenshotArea();
}
async disconnectedCallback() {
super.disconnectedCallback(), this._isMounted = !1, this.stopStream();
}
async requestUserMedia() {
try {
const e = await navigator.mediaDevices.getUserMedia({
video: { facingMode: this.facingMode }
});
this._stream = e, this.videoEl.srcObject = e, this._isUserMedia = !0, this._isMounted || this.stopStream();
} catch (e) {
console.log("Error occured", e);
}
}
preProcessScreenshotArea() {
const e = JSON.parse(this.screenshotArea);
function t(s, i) {
return s + i > 100;
}
return t(e.x, e.width) && (e.width = 100 - e.x), t(e.y, e.height) && (e.height = 100 - e.y), e;
}
stopStream() {
var e;
(e = this._stream) == null || e.getTracks().forEach((t) => {
var s;
(s = this._stream) == null || s.removeTrack(t), t.stop();
});
}
async screenshot() {
return J({
ref: this.videoEl,
width: this.width,
height: this.height,
mirrored: this.mirrored,
screenshotArea: this._screenshotAreaObj
});
}
// https://stackoverflow.com/questions/4000818/scale-html5-video-and-break-aspect-ratio-to-fill-whole-site
render() {
return u`
<div class="relative bg-gray-200">
<video
autoplay
muted
playsinline
class="object-cover"
style="width: ${this.width}px; height: ${this.height}px; transform: scaleX(${this.mirrored ? "-1" : "1"});"
></video>
${this.userMediaError()} ${this.userMedia()} ${this.screenshotOverlay()}
</div>
`;
}
userMediaError() {
return u`
<div style="${this._isUserMedia ? "display: none" : "display: revert"}">
<slot name="user-media-error">
<div
class="absolute top-[50%] left-[50%] flex w-[300px] translate-y-[-50%] translate-x-[-50%] flex-col rounded-sm border bg-white py-4 px-8"
>
<p class="text-[20px]">Camera blocked</p>
<p class="my-4">
Please allow camera access in your browser settings and try again.
</p>
<div class="flex flex-col items-end">
<button
type="button"
class="text-md text-[#009CDE]"
.onclick=${() => location.reload()}
>
Try Again
</button>
</div>
</div>
</slot>
</div>
`;
}
userMedia() {
return u`
<div style="${this._isUserMedia ? "display: revert" : "display: none"}">
<slot name="user-media">
<img
src=${v}
alt="overlay"
width="50"
class="absolute top-12 left-12"
/>
<img
src=${v}
alt="overlay"
width="50"
class="absolute bottom-12 left-12 -rotate-90"
/>
<img
src=${v}
alt="overlay"
width="50"
class="absolute top-12 right-12 rotate-90"
/>
<img
src=${v}
alt="overlay"
width="50"
class="absolute bottom-12 right-12 rotate-180"
/>
</slot>
</div>
`;
}
screenshotOverlay() {
var e, t, s, i, r;
return (e = this._screenshotAreaObj) != null && e.enableOverlay ? u`
<div
class="absolute border border-dashed border-red-500"
style="top: ${(t = this._screenshotAreaObj) == null ? void 0 : t.y}%; left: ${(s = this._screenshotAreaObj) == null ? void 0 : s.x}%; width: ${(i = this._screenshotAreaObj) == null ? void 0 : i.width}%; height: ${(r = this._screenshotAreaObj) == null ? void 0 : r.height}%"
></div>
` : u``;
}
};
o([
B("video")
], a.prototype, "videoEl", 2);
o([
m({ type: Number })
], a.prototype, "width", 2);
o([
m({ type: Number })
], a.prototype, "height", 2);
o([
m({ type: String })
], a.prototype, "facingMode", 2);
o([
m({ type: Boolean })
], a.prototype, "mirrored", 2);
o([
m({ type: String })
], a.prototype, "screenshotArea", 2);
o([
y()
], a.prototype, "_isUserMedia", 2);
o([
y()
], a.prototype, "_stream", 2);
o([
y()
], a.prototype, "_screenshotAreaObj", 2);
o([
y()
], a.prototype, "_isMounted", 2);
a = o([
R("glair-webcam")
], a);
export {
a as Webcam
};