@nuralogix.ai/anura-web-core-sdk
Version:
Anura Web Core SDK
734 lines (731 loc) • 43 kB
JavaScript
const objectFit = {
CONTAIN: "contain",
COVER: "cover",
NONE: "none"
};
class TeleMask {
version = "1.0.0";
#scaleX = 1;
#scaleY = 1;
#offsetX = 0;
#offsetY = 0;
objectFit = objectFit.COVER;
#frameInfo = {
faceTrackerHeight: 0,
faceTrackerWidth: 0,
mediaStreamHeight: 0,
mediaStreamWidth: 0
};
#svg;
#isMaskAnimationEnded = false;
#lightBulbs;
#facialLandmarks;
#ovalAnimation;
#facialGuides;
#intermediateResults;
#defs;
#background;
#ovalBorder;
#foreheadGuide;
#forehead;
#chin;
#faceBorder;
#chinGuide;
#ovalBorderAnimation;
#swooshContainer;
#swooshGroupAnimateTransform;
#progressbar;
#heartRateText;
#bloodPressureText;
#renderSettings = {
drawBorder: false,
drawPosePoints: false,
drawSilhouette: false,
drawChinForehead: true,
mask: {
width: 0,
arcHeight: 0,
rectHeight: 0,
left: 0,
top: 0
},
lightBulbs: {
left: 0,
top: 0,
scale: 1
},
intermediateResults: {
left: 0,
top: 0,
scale: 1
}
};
constructor() {
this.#svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
this.#background = this.#getBackground();
this.#faceBorder = this.#getFaceBorder("yellow");
this.#forehead = this.#getForehead("white");
this.#chin = this.#getChin("white");
this.#heartRateText = this.#getHeartRateText();
this.#bloodPressureText = this.#getBloodPressureText();
this.#ovalBorderAnimation = this.#getOvalBorderAnimation();
this.#swooshContainer = this.#getSwooshContainer();
this.#progressbar = this.#getProgressbar();
this.#swooshGroupAnimateTransform = this.#getSwooshGroupAnimateTransform();
this.#ovalBorder = this.#getOvalBorder();
this.#foreheadGuide = this.#getForeheadGuide("white");
this.#chinGuide = this.#getChinGuide("white");
this.#lightBulbs = this.#getLightBulbs();
this.#facialLandmarks = this.#getFacialLandmarks();
this.#ovalAnimation = this.#getOvalAnimation();
this.#facialGuides = this.#getFacialGuides();
this.#intermediateResults = this.#getIntermediateResults();
this.#defs = this.#getSVGDefs();
this.#appendChilds();
}
#appendChilds() {
this.#svg.appendChild(this.#defs);
this.#svg.appendChild(this.#facialLandmarks);
this.#svg.appendChild(this.#ovalAnimation);
this.#svg.appendChild(this.#facialGuides);
this.#svg.appendChild(this.#lightBulbs);
this.#svg.appendChild(this.#intermediateResults);
this.#svg.appendChild(this.#progressbar);
this.#svg.style.position = "absolute";
this.#svg.style.top = "0";
this.#svg.style.left = "0";
this.#svg.style.zIndex = "11";
}
#getSVGDefs() {
const defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
const linearGradient = document.createElementNS("http://www.w3.org/2000/svg", "linearGradient");
linearGradient.setAttribute("id", "mask_linear_gradient");
linearGradient.setAttribute("x1", "0");
linearGradient.setAttribute("x2", "0");
linearGradient.setAttribute("y1", "0");
linearGradient.setAttribute("y2", "0");
const stop1 = document.createElementNS("http://www.w3.org/2000/svg", "stop");
stop1.setAttribute("offset", "0%");
stop1.setAttribute("stop-color", "#ffffff");
const stop2 = document.createElementNS("http://www.w3.org/2000/svg", "stop");
stop2.setAttribute("offset", "1%");
stop2.setAttribute("stop-color", "#ffffff");
stop2.setAttribute("stop-opacity", "0");
const stop3 = document.createElementNS("http://www.w3.org/2000/svg", "stop");
stop3.setAttribute("offset", "99%");
stop3.setAttribute("stop-color", "#ffffff");
stop3.setAttribute("stop-opacity", "0.8");
const stop4 = document.createElementNS("http://www.w3.org/2000/svg", "stop");
stop4.setAttribute("offset", "100%");
stop4.setAttribute("stop-color", "#ffffff");
stop4.setAttribute("stop-opacity", "1");
const animateMaskLinearGradient = document.createElementNS("http://www.w3.org/2000/svg", "animate");
animateMaskLinearGradient.setAttribute("attributeName", "y2");
animateMaskLinearGradient.setAttribute("dur", "1.3s");
animateMaskLinearGradient.setAttribute("begin", "animate_face_mask_border.end");
animateMaskLinearGradient.setAttribute("from", "0");
animateMaskLinearGradient.setAttribute("to", "1");
animateMaskLinearGradient.setAttribute("fill", "freeze");
linearGradient.appendChild(stop1);
linearGradient.appendChild(stop2);
linearGradient.appendChild(stop3);
linearGradient.appendChild(stop4);
linearGradient.appendChild(animateMaskLinearGradient);
defs.appendChild(linearGradient);
return defs;
}
#getFaceBorder(color) {
const faceBorder = document.createElementNS("http://www.w3.org/2000/svg", "path");
faceBorder.setAttribute("d", "");
faceBorder.setAttribute("fill", "none");
faceBorder.setAttribute("stroke", color);
faceBorder.setAttribute("stroke-width", "5");
faceBorder.setAttribute("id", "faceborder");
return faceBorder;
}
#getForehead(color) {
const forehead = document.createElementNS("http://www.w3.org/2000/svg", "path");
forehead.setAttribute("d", "");
forehead.setAttribute("fill", "none");
forehead.setAttribute("stroke", color);
forehead.setAttribute("stroke-width", "5");
forehead.setAttribute("id", "forehead");
return forehead;
}
#getChin(color) {
const chin = document.createElementNS("http://www.w3.org/2000/svg", "path");
chin.setAttribute("d", "");
chin.setAttribute("fill", "none");
chin.setAttribute("stroke", color);
chin.setAttribute("stroke-width", "5");
chin.setAttribute("id", "chin");
return chin;
}
#getFacialLandmarks() {
const landmarks = document.createElementNS("http://www.w3.org/2000/svg", "g");
landmarks.setAttribute("id", "facial_landmarks");
landmarks.appendChild(this.#faceBorder);
landmarks.appendChild(this.#forehead);
landmarks.appendChild(this.#chin);
return landmarks;
}
#getBackground() {
const maskColor = "white";
const background = document.createElementNS("http://www.w3.org/2000/svg", "path");
background.setAttribute("fill", maskColor);
background.setAttribute("id", "mask_background");
return background;
}
#getOvalBorder() {
const ovalBorder = document.createElementNS("http://www.w3.org/2000/svg", "path");
ovalBorder.setAttribute("d", "");
ovalBorder.setAttribute("fill", "url(#mask_linear_gradient)");
ovalBorder.setAttribute("stroke", "#c7c7c7");
ovalBorder.setAttribute("stroke-width", "10");
ovalBorder.setAttribute("id", "face_mask_border");
ovalBorder.setAttribute("transform", "scale(1.003)");
ovalBorder.setAttribute("style", "transform-origin: center;");
return ovalBorder;
}
#getOvalBorderAnimation() {
const ovalBorderAnimation = document.createElementNS("http://www.w3.org/2000/svg", "animate");
ovalBorderAnimation.setAttribute("id", "animate_face_mask_border");
ovalBorderAnimation.setAttribute("attributeName", "stroke-dashoffset");
ovalBorderAnimation.setAttribute("begin", "0.2s");
ovalBorderAnimation.setAttribute("values", "0;0");
ovalBorderAnimation.setAttribute("dur", "0.6s");
ovalBorderAnimation.setAttribute("calcMode", "linear");
ovalBorderAnimation.setAttribute("fill", "freeze");
return ovalBorderAnimation;
}
#getSwooshContainer() {
const swooshContainer = document.createElementNS("http://www.w3.org/2000/svg", "g");
swooshContainer.setAttribute("id", "swoosh_container");
return swooshContainer;
}
#getSwooshGroupAnimateTransform() {
const swooshGroupAnimateTransform = document.createElementNS("http://www.w3.org/2000/svg", "animateTransform");
swooshGroupAnimateTransform.setAttribute("id", "swoosh_group_animate_transform");
swooshGroupAnimateTransform.setAttribute("attributeName", "transform");
swooshGroupAnimateTransform.setAttribute("type", "translate");
swooshGroupAnimateTransform.setAttribute("from", "0 0");
swooshGroupAnimateTransform.setAttribute("begin", "animate_face_mask_border.end");
swooshGroupAnimateTransform.setAttribute("dur", "1.35");
swooshGroupAnimateTransform.setAttribute("repeatCount", "1");
swooshGroupAnimateTransform.addEventListener("endEvent", () => {
this.#ovalBorder.removeAttribute("transform");
this.#ovalBorder.setAttribute("fill-opacity", "0");
this.#isMaskAnimationEnded = true;
});
return swooshGroupAnimateTransform;
}
#getOvalAnimation() {
const faceMaskOvalAnimation = document.createElementNS("http://www.w3.org/2000/svg", "g");
faceMaskOvalAnimation.setAttribute("id", "face_mask_oval_animation");
this.#ovalBorder.appendChild(this.#ovalBorderAnimation);
const swooshGroup = document.createElementNS("http://www.w3.org/2000/svg", "g");
const swooshContainerPath = document.createElementNS("http://www.w3.org/2000/svg", "path");
swooshContainerPath.setAttribute("d", "M 0,70 A 65,70 0 0,0 65,0 5,5 0 0,1 75,0 75,70 0 0,1 0,70Z");
swooshContainerPath.setAttribute("fill", "#ebebeb");
swooshContainerPath.setAttribute("opacity", "0");
const pathAnimateTransform = document.createElementNS("http://www.w3.org/2000/svg", "animateTransform");
pathAnimateTransform.setAttribute("attributeName", "transform");
pathAnimateTransform.setAttribute("type", "rotate");
pathAnimateTransform.setAttribute("from", "360 0 0");
pathAnimateTransform.setAttribute("to", "0 0 0");
pathAnimateTransform.setAttribute("begin", "animate_face_mask_border.end");
pathAnimateTransform.setAttribute("dur", "0.45s");
pathAnimateTransform.setAttribute("repeatCount", "3");
const pathAnimate = document.createElementNS("http://www.w3.org/2000/svg", "animate");
pathAnimate.setAttribute("attributeName", "opacity");
pathAnimate.setAttribute("begin", "animate_face_mask_border.end");
pathAnimate.setAttribute("values", "1;0");
pathAnimate.setAttribute("dur", "1.35s");
pathAnimate.setAttribute("fill", "freeze");
swooshContainerPath.appendChild(pathAnimateTransform);
swooshContainerPath.appendChild(pathAnimate);
this.#swooshContainer.appendChild(swooshContainerPath);
swooshGroup.appendChild(this.#swooshContainer);
swooshGroup.appendChild(this.#swooshGroupAnimateTransform);
faceMaskOvalAnimation.appendChild(this.#ovalBorder);
faceMaskOvalAnimation.appendChild(this.#background);
faceMaskOvalAnimation.appendChild(swooshGroup);
return faceMaskOvalAnimation;
}
#getForeheadGuide(color) {
const foreheadGuide = document.createElementNS("http://www.w3.org/2000/svg", "path");
foreheadGuide.setAttribute("d", "");
foreheadGuide.setAttribute("fill", "none");
foreheadGuide.setAttribute("stroke", color);
foreheadGuide.setAttribute("stroke-width", "5");
foreheadGuide.setAttribute("id", "forehead_guide");
return foreheadGuide;
}
#getChinGuide(color) {
const chinGuide = document.createElementNS("http://www.w3.org/2000/svg", "path");
chinGuide.setAttribute("d", "");
chinGuide.setAttribute("fill", "none");
chinGuide.setAttribute("stroke", color);
chinGuide.setAttribute("stroke-width", "5");
chinGuide.setAttribute("id", "chin_guide");
return chinGuide;
}
#getFacialGuides() {
const guides = document.createElementNS("http://www.w3.org/2000/svg", "g");
guides.setAttribute("opacity", "0.5");
guides.setAttribute("id", "facial_guides");
guides.appendChild(this.#foreheadGuide);
guides.appendChild(this.#chinGuide);
return guides;
}
#getLightBulbs() {
const lightBulbs = document.createElementNS("http://www.w3.org/2000/svg", "g");
lightBulbs.setAttribute("id", "light_bulbs");
let x = 10;
for (let i = 1; i < 6; i += 1) {
lightBulbs.appendChild(this.#createSVGLightBulb(0.3, x, 0, i.toString()));
x += 40;
}
return lightBulbs;
}
#createSVGLightBulb(scale, x, y, id) {
const bulb = document.createElementNS("http://www.w3.org/2000/svg", "g");
const bulbOff = document.createElementNS("http://www.w3.org/2000/svg", "path");
const fillBulbOn = document.createElementNS("http://www.w3.org/2000/svg", "path");
const bulbOn = document.createElementNS("http://www.w3.org/2000/svg", "path");
bulbOff.setAttribute("id", `bulb_off_${id}`);
bulbOff.setAttribute("visibility", "visible");
bulbOff.setAttribute("fill", "black");
bulbOff.setAttribute(
"d",
"M84.84 31.1C88.0639 32.9974 90.9694 35.39 93.45 38.19C95.8786 40.9297 97.8261 44.0605 99.21 47.45C99.9963 49.3937 100.615 51.401 101.06 53.45C102.092 58.0517 102.174 62.8157 101.3 67.45C100.826 69.9549 100.106 72.4068 99.15 74.77L99.03 75.02C97.0667 79.7853 93.7682 84.4234 90.5109 89.0035L90.03 89.68C88.28 92.1 86.55 94.5 85.09 96.83C84.1556 98.3104 82.4744 99.1471 80.73 99L53.17 103.1C50.8355 103.42 48.6249 101.962 48 99.69C47.3082 97.6861 46.4588 95.74 45.46 93.87C44.6261 92.2688 43.6201 90.7633 42.46 89.38C41.03 87.75 39.58 86.09 38.17 84.18C36.5512 82.0121 35.1542 79.6871 34 77.24C32.7899 74.6774 31.8482 71.9965 31.19 69.24C30.5391 66.471 30.2202 63.6344 30.24 60.79C30.2403 57.8251 30.6133 54.872 31.35 52C32.1495 48.9295 33.2969 45.9603 34.77 43.15L34.97 42.8C36.876 39.5649 39.2825 36.6521 42.1 34.17C44.9092 31.7169 48.106 29.7468 51.56 28.34L51.84 28.24C54.4138 27.2163 57.0988 26.498 59.84 26.1C62.7456 25.693 65.6888 25.6259 68.61 25.9C71.4642 26.1608 74.2811 26.7342 77.01 27.61C79.7282 28.4806 82.341 29.6511 84.8 31.1H84.84ZM83.25 104.21V105.86V106.44C83.3301 107.522 83.3301 108.608 83.25 109.69L82.76 112.08L52.12 116.64L51.58 115.41L50.39 110.51V109.09L83.18 104.21H83.25ZM80.84 118.36L80.8343 118.37L55.61 122.13C56.8619 123.478 58.3497 124.587 60 125.4C62.2891 126.504 64.8231 127.004 67.36 126.85C69.8977 126.683 72.3622 125.93 74.56 124.65C77.1602 123.135 79.3222 120.971 80.8343 118.37L80.9 118.36H80.84ZM40 74.56C41.8807 78.339 44.3178 81.8144 47.23 84.87C49.9622 88.2499 52.0409 92.109 53.36 96.25L79.44 92.4C79.661 92.3548 79.889 92.3548 80.11 92.4C81.5201 90.1662 83.1885 87.8592 84.8775 85.5238C88.0274 81.1683 91.2489 76.7138 93 72.45C95.975 65.3317 95.975 57.3184 93 50.2C90.6829 44.6455 86.6033 40.0072 81.39 37C77.3193 34.623 72.775 33.1719 68.08 32.75C63.3435 32.2891 58.5655 32.9751 54.15 34.75C48.5089 37.0603 43.7954 41.1794 40.75 46.46C40.7374 46.4952 40.7206 46.5288 40.7 46.56C38.2981 51.0013 36.9919 55.952 36.89 61C36.8929 65.6965 37.956 70.3317 40 74.56Z"
);
bulbOff.setAttribute("transform", `matrix(${scale}, 0, 0, ${scale}, ${x}, ${y})`);
fillBulbOn.setAttribute("id", `fill_bulb_on_${id}`);
fillBulbOn.setAttribute("visibility", "hidden");
fillBulbOn.setAttribute("fill", "#f5ed0f");
fillBulbOn.setAttribute(
"d",
"M 0 -27.90881 C 15.40566 -27.90881 27.90881 -15.40566 27.90881 0 C 27.90881 15.40566 15.40566 27.90881 0 27.90881 C -15.40566 27.90881 -27.90881 15.40566 -27.90881 0 C -27.90881 -15.40566 -15.40566 -27.90881 0 -27.90881 z"
);
fillBulbOn.setAttribute("transform", `matrix(${1.133802738 * scale}, 0, 0, ${1.267605583 * scale}, ${64.9 * scale + x}, ${63.8 * scale + y})`);
bulbOn.setAttribute("id", `bulb_on_${id}`);
bulbOn.setAttribute("visibility", "hidden");
bulbOn.setAttribute("fill", "black");
bulbOn.setAttribute(
"d",
"M64.34 7.76997C64.3783 5.65698 66.1168 3.97211 68.23 3.99997H68.5C70.5063 4.17803 72.0341 5.87605 72 7.88997C72.0053 7.95654 72.0053 8.02341 72 8.08997L71.79 16.3C71.7953 16.3866 71.7953 16.4734 71.79 16.56C71.6323 18.5744 69.9404 20.1219 67.92 20.1H67.65C65.6357 19.937 64.0924 18.2407 64.12 16.22C64.1145 16.1568 64.1145 16.0932 64.12 16.03L64.32 7.77997L64.34 7.76997ZM83.84 31.1C87.0639 32.9973 89.9694 35.3899 92.45 38.19C94.8786 40.9296 96.8261 44.0605 98.21 47.45C98.9963 49.3937 99.6152 51.401 100.06 53.45C101.092 58.0517 101.174 62.8156 100.3 67.45C99.8262 69.9548 99.1061 72.4068 98.15 74.77L98.03 75.02C96.0667 79.7852 92.7683 84.4233 89.511 89.0034L89.5109 89.0035L89.03 89.68C87.28 92.1 85.55 94.5 84.09 96.83C83.1556 98.3103 81.4744 99.147 79.73 99L52.17 103.1C49.8355 103.42 47.6249 101.962 47 99.69C46.3082 97.686 45.4588 95.7399 44.46 93.87C43.6261 92.2688 42.6201 90.7632 41.46 89.38C40.03 87.75 38.58 86.09 37.17 84.18C35.5512 82.012 34.1542 79.687 33 77.24C31.7899 74.6774 30.8482 71.9964 30.19 69.24C29.5391 66.471 29.2202 63.6344 29.24 60.79C29.2403 57.825 29.6133 54.8719 30.35 52C31.1495 48.9294 32.2969 45.9602 33.77 43.15L33.97 42.8C35.876 39.5648 38.2825 36.652 41.1 34.17C43.9092 31.7169 47.106 29.7468 50.56 28.34L50.84 28.24C53.4138 27.2162 56.0988 26.498 58.84 26.1C61.7456 25.693 64.6888 25.6259 67.61 25.9C70.4642 26.1607 73.2811 26.7341 76.01 27.61C78.7282 28.4805 81.341 29.651 83.8 31.1H83.84ZM79.84 118.36L79.8343 118.37L54.61 122.13C55.8619 123.478 57.3497 124.587 59 125.4C61.2891 126.504 63.8231 127.004 66.36 126.85C68.8977 126.683 71.3622 125.93 73.56 124.65C76.1602 123.135 78.3222 120.971 79.8343 118.37L79.9 118.36H79.84ZM82.25 105.86V104.21H82.18L49.39 109.09V110.51L50.58 115.41L51.12 116.64L81.76 112.08L82.25 109.69C82.3301 108.608 82.3301 107.522 82.25 106.44V105.86ZM21.0035 17.9924C20.4621 19.4521 20.8557 21.0943 22 22.15L28.18 27.88C28.9289 28.5696 29.9232 28.9298 30.94 28.88C31.9559 28.8408 32.9154 28.4024 33.61 27.66C34.2976 26.9099 34.6576 25.9164 34.61 24.9C34.5681 23.8818 34.1304 22.9202 33.39 22.22L27.23 16.49C26.4793 15.8033 25.4863 15.4435 24.47 15.49C22.914 15.5442 21.5449 16.5326 21.0035 17.9924ZM11.92 64.48C9.81471 64.5139 8.07064 62.8544 8 60.75C7.95677 59.7229 8.32713 58.7214 9.02818 57.9696C9.72923 57.2178 10.7024 56.7785 11.73 56.75L20.14 56.47C21.1654 56.4267 22.1654 56.7957 22.9169 57.4946C23.6684 58.1935 24.1088 59.1642 24.14 60.19V60.25V60.39C24.1034 62.4413 22.4608 64.1015 20.41 64.16H20.26L11.96 64.43L11.92 64.48ZM118 52.56H117.92L117.84 52.54C115.424 52.7729 113.001 53.0431 110.589 53.312L110.589 53.312L110.589 53.312L109.44 53.44C107.9 53.6088 106.612 54.6869 106.174 56.1736C105.737 57.6603 106.236 59.2641 107.44 60.24C108.227 60.8853 109.238 61.1911 110.25 61.09L118.62 60.2C120.671 59.9893 122.189 58.1972 122.06 56.14C122.066 56.0968 122.066 56.0531 122.06 56.01C121.959 54.9939 121.455 54.0608 120.66 53.42C119.913 52.8093 118.963 52.5022 118 52.56ZM101.33 19.09C101.889 18.2378 102.765 17.6437 103.763 17.4391C104.762 17.2345 105.801 17.4364 106.65 18C107.504 18.5565 108.093 19.4381 108.28 20.44C108.476 21.4389 108.267 22.4748 107.7 23.32L103.02 30.32C102.467 31.187 101.587 31.7931 100.58 32C99.5824 32.1945 98.5483 31.9899 97.7 31.43C96.8596 30.8626 96.2718 29.9916 96.06 29C95.8639 28.001 96.0726 26.9651 96.64 26.12L101.33 19.12V19.09ZM39 74.56C40.8807 78.339 43.3178 81.8143 46.23 84.87C48.9622 88.2498 51.0409 92.1089 52.36 96.25L78.44 92.4C78.661 92.3547 78.889 92.3547 79.11 92.4C80.5201 90.1661 82.1885 87.8592 83.8775 85.5238C87.0274 81.1683 90.2489 76.7138 92 72.45C94.975 65.3316 94.975 57.3183 92 50.2C89.6829 44.6454 85.6033 40.0071 80.39 37C76.3193 34.6229 71.775 33.1719 67.08 32.75C62.3434 32.2891 57.5655 32.9751 53.15 34.75C47.5089 37.0603 42.7954 41.1794 39.75 46.46C39.7374 46.4952 39.7206 46.5287 39.7 46.56C37.2981 51.0012 35.9919 55.9519 35.89 61C35.8929 65.6964 36.956 70.3317 39 74.56Z"
);
bulbOn.setAttribute("transform", `matrix(${scale}, 0, 0, ${scale}, ${x}, ${y})`);
bulb.appendChild(bulbOff);
bulb.appendChild(bulbOn);
bulb.appendChild(fillBulbOn);
const animateBulb = document.createElementNS("http://www.w3.org/2000/svg", "animate");
animateBulb.setAttribute("attributetype", "CSS");
animateBulb.setAttribute("attributeName", "opacity");
animateBulb.setAttribute("begin", `animate_face_mask_border.end+${parseInt(id) * 0.2}s`);
animateBulb.setAttribute("from", "0");
animateBulb.setAttribute("to", "1");
animateBulb.setAttribute("dur", "0.2s");
animateBulb.setAttribute("fill", "freeze");
const bulbGroup = document.createElementNS("http://www.w3.org/2000/svg", "g");
bulbGroup.setAttribute("opacity", "0");
bulbGroup.appendChild(bulb);
bulbGroup.appendChild(animateBulb);
return bulbGroup;
}
#getBloodPressureIcon(fill) {
const icon = document.createElementNS("http://www.w3.org/2000/svg", "g");
icon.setAttribute("fill", fill);
icon.setAttribute("id", "blood-pressure-icon");
const p1 = document.createElementNS("http://www.w3.org/2000/svg", "path");
p1.setAttribute("d", "M36.9228 21C37.4751 21 37.9228 21.4477 37.9228 22C37.9228 23.3228 37.9425 24.692 37.962 26.0465C37.9843 27.5925 38.0062 26.1193 37.9983 27.536C37.9831 30.2549 37.8624 32.8418 37.4203 35.0818C36.9793 37.3163 36.1986 39.3134 34.7794 40.7537C33.3307 42.2238 31.3311 43 28.7032 43C24.3102 43 21.8273 41.3632 20.4727 39.5782C19.8121 38.7078 19.4478 37.8388 19.2478 37.1859C19.1476 36.8585 19.0876 36.582 19.0522 36.3816C19.0344 36.2813 19.0227 36.1995 19.0152 36.1395C19.0115 36.1095 19.0087 36.0849 19.0068 36.066L19.0045 36.042L19.0037 36.0334L19.0035 36.0299L19.0033 36.0284C19.0033 36.0284 19.0032 36.027 20 35.9474L19.0032 36.027L18.9236 35.0302L20.9172 34.8709L20.9963 35.8615L20.9965 35.8635C20.9969 35.8675 20.9979 35.8769 20.9997 35.8912C21.0033 35.9198 21.0101 35.9681 21.0216 36.0333C21.0447 36.1638 21.0867 36.3602 21.1602 36.6003C21.3078 37.0822 21.578 37.7264 22.0658 38.3692C23.0079 39.6105 24.8765 41 28.7032 41C30.9103 41 32.3556 40.3639 33.3548 39.3499C34.3833 38.3061 35.0531 36.7473 35.4582 34.6945C35.8622 32.6473 35.9833 30.2155 35.9984 27.5248C36.0065 26.071 35.9849 27.6161 35.9628 26.122C35.943 24.7884 35.9228 23.4235 35.9228 22C35.9228 21.4477 36.3705 21 36.9228 21Z");
p1.setAttribute("fill-rule", "evenodd");
p1.setAttribute("clip-rule", "evenodd");
icon.appendChild(p1);
const p2 = document.createElementNS("http://www.w3.org/2000/svg", "path");
p2.setAttribute("d", "M23.0033 11.4695C23.0036 11.4695 23.0032 11.4729 23.0011 11.4797C23.0019 11.4729 23.003 11.4695 23.0033 11.4695ZM22.9934 11.5C22.9726 11.4519 22.9117 11.3471 22.7451 11.186C22.4319 10.883 21.8739 10.5181 21.0209 10.1691C19.3247 9.47522 16.8435 9 14 9C11.1565 9 8.67526 9.47522 6.97909 10.1691C6.12611 10.5181 5.5681 10.883 5.25487 11.186C5.08832 11.3471 5.02743 11.4519 5.0066 11.5C5.02743 11.5481 5.08832 11.6529 5.25487 11.814C5.5681 12.117 6.12611 12.4819 6.97909 12.8309C8.67526 13.5248 11.1565 14 14 14C16.8435 14 19.3247 13.5248 21.0209 12.8309C21.8739 12.4819 22.4319 12.117 22.7451 11.814C22.9117 11.6529 22.9726 11.5481 22.9934 11.5ZM4.9967 11.4695C4.99702 11.4695 4.99807 11.4729 4.99891 11.4797C4.9968 11.4729 4.99638 11.4695 4.9967 11.4695ZM4.9967 11.5305C4.99638 11.5305 4.9968 11.5271 4.99891 11.5203C4.99807 11.5271 4.99702 11.5305 4.9967 11.5305ZM23.0011 11.5203C23.0032 11.5271 23.0036 11.5305 23.0033 11.5305C23.003 11.5305 23.0019 11.5271 23.0011 11.5203ZM14 16C20.0751 16 25 13.9853 25 11.5C25 9.01472 20.0751 7 14 7C7.92487 7 3 9.01472 3 11.5C3 13.9853 7.92487 16 14 16Z");
p2.setAttribute("fill-rule", "evenodd");
p2.setAttribute("clip-rule", "evenodd");
icon.appendChild(p2);
const p3 = document.createElementNS("http://www.w3.org/2000/svg", "path");
p3.setAttribute("d", "M4 14L13 16.3158V36L4 33.6842V14Z");
icon.appendChild(p3);
const p4 = document.createElementNS("http://www.w3.org/2000/svg", "path");
p4.setAttribute("d", "M25 12C25 12 24.306 12.5138 23 13.1161C21.1501 13.9692 18.0724 15 14 15C9.84407 15 6.815 13.9958 5 13.1494C3.6779 12.5328 3 12 3 12V34C3 34 6.47368 37 14 37C21.5263 37 25 34 25 34V31.9381C24.6724 31.979 24.3387 32 24 32C23.6613 32 23.3276 31.979 23 31.9381V32.9432C22.651 33.1473 22.1712 33.3976 21.5565 33.6525C19.9799 34.306 17.4896 35 14 35C10.5104 35 8.02005 34.306 6.44352 33.6525C5.82878 33.3976 5.34902 33.1473 5 32.9432V15.3312L5.05561 15.3538C7.11934 16.1895 10.1236 17 14 17C17.7658 17 20.7672 16.1864 22.8458 15.3578C22.8978 15.3371 22.9492 15.3164 23 15.2957V16.0619C23.3276 16.021 23.6613 16 24 16C24.3387 16 24.6724 16.021 25 16.0619V12Z");
p4.setAttribute("fill-rule", "evenodd");
p4.setAttribute("clip-rule", "evenodd");
icon.appendChild(p4);
const p5 = document.createElementNS("http://www.w3.org/2000/svg", "path");
p5.setAttribute("d", "M24 30C27.3137 30 30 27.3137 30 24C30 20.6863 27.3137 18 24 18C20.6863 18 18 20.6863 18 24C18 27.3137 20.6863 30 24 30ZM24 32C28.4183 32 32 28.4183 32 24C32 19.5817 28.4183 16 24 16C19.5817 16 16 19.5817 16 24C16 28.4183 19.5817 32 24 32Z");
p5.setAttribute("fill-rule", "evenodd");
p5.setAttribute("clip-rule", "evenodd");
icon.appendChild(p5);
const p6 = document.createElementNS("http://www.w3.org/2000/svg", "path");
p6.setAttribute("d", "M26 24C26 25.1046 25.1046 26 24 26C22.8954 26 22 25.1046 22 24C22 22.8954 22.8954 22 24 22C25.1046 22 26 22.8954 26 24Z");
icon.appendChild(p6);
const p7 = document.createElementNS("http://www.w3.org/2000/svg", "path");
p7.setAttribute("d", "M23 20C23 19.4477 23.4477 19 24 19C24.5523 19 25 19.4477 25 20V23C25 23.5523 24.5523 24 24 24C23.4477 24 23 23.5523 23 23V20Z");
icon.appendChild(p7);
const p8 = document.createElementNS("http://www.w3.org/2000/svg", "path");
p8.setAttribute("d", "M38.0396 19.7624C38.5973 18.6469 39 16.966 39 15C39 13.034 38.5973 11.3531 38.0396 10.2376C37.761 9.68039 37.4809 9.33804 37.2653 9.15562C37.1621 9.06834 37.0881 9.02968 37.0486 9.01352C37.0291 9.00555 37.0168 9.00248 37.0109 9.00128C37.0052 9.00013 37.0021 9 37 9C36.9979 9 36.9948 9.00013 36.9891 9.00128C36.9832 9.00248 36.9709 9.00555 36.9514 9.01352C36.9119 9.02968 36.8379 9.06834 36.7347 9.15562C36.5191 9.33804 36.239 9.68039 35.9604 10.2376C35.4027 11.3531 35 13.034 35 15C35 16.966 35.4027 18.6469 35.9604 19.7624C36.239 20.3196 36.5191 20.662 36.7347 20.8444C36.8379 20.9317 36.9119 20.9703 36.9514 20.9865C36.9709 20.9945 36.9832 20.9975 36.9891 20.9987C36.9948 20.9999 36.9979 21 37 21C37.0021 21 37.0052 20.9999 37.0109 20.9987C37.0168 20.9975 37.0291 20.9945 37.0486 20.9865C37.0881 20.9703 37.1621 20.9317 37.2653 20.8444C37.4809 20.662 37.761 20.3196 38.0396 19.7624ZM37 23C39.2091 23 41 19.4183 41 15C41 10.5817 39.2091 7 37 7C34.7909 7 33 10.5817 33 15C33 19.4183 34.7909 23 37 23Z");
p8.setAttribute("fill-rule", "evenodd");
p8.setAttribute("clip-rule", "evenodd");
icon.appendChild(p8);
return icon;
}
#getHeartRateIcon(fill) {
const icon = document.createElementNS("http://www.w3.org/2000/svg", "path");
icon.setAttribute("d", "M2 9.1371C2 14 6.01943 16.5914 8.96173 18.9109C10 19.7294 11 20.5 12 20.5C13 20.5 14 19.7294 15.0383 18.9109C17.9806 16.5914 22 14 22 9.1371C22 4.27416 16.4998 0.825464 12 5.50063C7.50016 0.825464 2 4.27416 2 9.1371Z");
icon.setAttribute("fill", fill);
icon.setAttribute("id", "heart-rate-icon");
return icon;
}
#getHeartRateText() {
const heartRateText = document.createElementNS("http://www.w3.org/2000/svg", "text");
heartRateText.setAttribute("transform", "translate(60 35)");
heartRateText.setAttribute("font-size", "1.7rem");
heartRateText.setAttribute("font-weight", "bold");
heartRateText.setAttribute("fill", "black");
heartRateText.setAttribute("id", "heart-rate-value");
return heartRateText;
}
#getBloodPressureText() {
const bloodPressureText = document.createElementNS("http://www.w3.org/2000/svg", "text");
bloodPressureText.setAttribute("transform", "translate(60 90)");
bloodPressureText.setAttribute("font-size", "1.7rem");
bloodPressureText.setAttribute("font-weight", "bold");
bloodPressureText.setAttribute("fill", "black");
bloodPressureText.setAttribute("id", "blood-pressure-value");
return bloodPressureText;
}
#getIntermediateResults() {
const intermediateResults = document.createElementNS("http://www.w3.org/2000/svg", "g");
intermediateResults.setAttribute("visibility", "hidden");
intermediateResults.setAttribute("id", "intermediate_results");
const bloodPressureIcon = this.#getBloodPressureIcon("#5E05CF");
bloodPressureIcon.setAttribute("transform", "translate(5, 50)");
const heartRateIcon = this.#getHeartRateIcon("#FF7B77");
heartRateIcon.setAttribute("transform", "scale(2)");
const heartRateUnit = document.createElementNS("http://www.w3.org/2000/svg", "text");
heartRateUnit.setAttribute("transform", "translate(115 35)");
heartRateUnit.setAttribute("font-size", "1.5rem");
heartRateUnit.setAttribute("fill", "black");
heartRateUnit.textContent = "bpm";
const bloodPressureUnit = document.createElementNS("http://www.w3.org/2000/svg", "text");
bloodPressureUnit.setAttribute("transform", "translate(175 90)");
bloodPressureUnit.setAttribute("font-size", "1.5rem");
bloodPressureUnit.setAttribute("fill", "black");
bloodPressureUnit.textContent = "mmHg";
intermediateResults.appendChild(bloodPressureIcon);
intermediateResults.appendChild(this.#heartRateText);
intermediateResults.appendChild(heartRateUnit);
intermediateResults.appendChild(this.#bloodPressureText);
intermediateResults.appendChild(bloodPressureUnit);
intermediateResults.appendChild(heartRateIcon);
return intermediateResults;
}
/* url: SVG Circle Arc http://xahlee.info/js/svg_circle_arc.html */
#getArc(centerX, centerY, rx, ry, sweepStart, sweepDelta, rotation, trunc) {
const { cos, sin, PI } = Math;
const f_matrix_times = ([[a, b], [c, d]], [x, y]) => [a * x + b * y, c * x + d * y];
const t = (x) => Math.trunc(x);
const f_rotate_matrix = (x) => {
const cosx = cos(x);
const sinx = sin(x);
return [[cosx, -sinx], [sinx, cosx]];
};
const f_vec_add = ([a1, a2], [b1, b2]) => [a1 + b1, a2 + b2];
const f_svg_ellipse_arc = ([cx, cy], [rx2, ry2], [t1, I], II) => {
I = I % (2 * PI);
const rotMatrix = f_rotate_matrix(II);
const [sX, sY] = f_vec_add(f_matrix_times(rotMatrix, [rx2 * cos(t1), ry2 * sin(t1)]), [
cx,
cy
]);
const [eX, eY] = f_vec_add(f_matrix_times(rotMatrix, [rx2 * cos(t1 + I), ry2 * sin(t1 + I)]), [cx, cy]);
const fA = I > PI ? 1 : 0;
const fS = I > 0 ? 0 : 1;
return trunc ? ["M", t(sX), "", t(sY), "A", t(rx2), t(ry2), t(II / PI * 180), t(fA), t(fS), t(eX), t(eY)] : ["M", sX, "", sY, "A", rx2, ry2, II / PI * 180, fA, fS, eX, eY];
};
const params = f_svg_ellipse_arc([
centerX,
centerY
], [
rx,
ry
], [
sweepStart / 180 * PI,
sweepDelta / 180 * PI
], rotation / 180 * PI);
return params.join(" ");
}
#getSvgPoint(x, y) {
const point = this.#svg.createSVGPoint();
point.x = x;
point.y = y;
return point;
}
#getProgressbar() {
const x = "10";
const y = "2";
const height = "6";
const r = "3";
const progressbar = document.createElementNS("http://www.w3.org/2000/svg", "g");
progressbar.setAttribute("id", "progressbar");
const background = document.createElementNS("http://www.w3.org/2000/svg", "rect");
background.setAttribute("x", x);
background.setAttribute("y", y);
background.setAttribute("width", "0");
background.setAttribute("height", height);
background.setAttribute("rx", r);
background.setAttribute("ry", r);
background.setAttribute("fill", "#e0e0e0");
background.setAttribute("visibility", "hidden");
const progress = document.createElementNS("http://www.w3.org/2000/svg", "rect");
progress.setAttribute("x", x);
progress.setAttribute("y", y);
progress.setAttribute("width", "0");
progress.setAttribute("height", height);
progress.setAttribute("rx", r);
progress.setAttribute("ry", r);
progress.setAttribute("fill", "#4caf50");
progress.setAttribute("visibility", "hidden");
progressbar.appendChild(background);
progressbar.appendChild(progress);
return progressbar;
}
#setProgressbarWidth(width) {
this.#progressbar.children[0].setAttribute("width", `${Math.trunc(width - 20)}px`);
}
#isFaceInsideOval(topX, topY, bottomX, bottomY) {
const topLeft = this.#getSvgPoint(topX, topY);
const topRight = this.#getSvgPoint(bottomX, topY);
const bottomLeft = this.#getSvgPoint(topX, bottomY);
const bottomRight = this.#getSvgPoint(bottomX, bottomY);
const isInside = this.#ovalBorder.isPointInFill(topLeft) && this.#ovalBorder.isPointInFill(topRight) && this.#ovalBorder.isPointInFill(bottomLeft) && this.#ovalBorder.isPointInFill(bottomRight);
this.#ovalBorder.setAttribute("stroke", isInside ? "#c7c7c7" : "#ff0000");
}
#setFrameInfo(frameInfo, videoElementSize) {
this.#frameInfo = frameInfo;
const { faceTrackerHeight, faceTrackerWidth, mediaStreamHeight, mediaStreamWidth } = frameInfo;
const { width, height, offsetX, offsetY } = videoElementSize;
this.#offsetX = offsetX;
this.#offsetY = offsetY;
if (this.objectFit === objectFit.NONE) {
this.#scaleX = mediaStreamWidth / faceTrackerWidth;
this.#scaleY = mediaStreamHeight / faceTrackerHeight;
} else {
this.#scaleX = width / faceTrackerWidth;
this.#scaleY = height / faceTrackerHeight;
}
}
getSvg() {
return this.#svg;
}
#toggleLightBulb(bulbIndex, status) {
const lightBulbs = this.#lightBulbs.childNodes[bulbIndex].childNodes[0];
const bulbOff = lightBulbs.childNodes[0];
const bulbOn = lightBulbs.childNodes[1];
const fillBulbOn = lightBulbs.childNodes[2];
bulbOff.setAttribute("visibility", status ? "hidden" : "visible");
fillBulbOn.setAttribute("visibility", status ? "visible" : "hidden");
bulbOn.setAttribute("visibility", status ? "visible" : "hidden");
}
#setRenderSettings(maskSettings, lightBulbSettings, intermediateResults) {
this.#renderSettings.mask = maskSettings;
this.#renderSettings.lightBulbs = lightBulbSettings;
this.#renderSettings.intermediateResults = intermediateResults;
}
draw({ face, annotations, starRating, percentCompleted }) {
if (this.#isMaskAnimationEnded) {
if (percentCompleted > 0) {
const progressWidth = parseFloat(this.#progressbar.children[0].getAttribute("width"));
this.#progressbar.children[0].setAttribute("visibility", "visible");
this.#progressbar.children[1].setAttribute("visibility", "visible");
this.#progressbar.children[1].setAttribute("width", `${Math.trunc(percentCompleted * progressWidth / 100)}px`);
} else {
this.#progressbar.children[0].setAttribute("visibility", "hidden");
this.#progressbar.children[1].setAttribute("visibility", "hidden");
}
const isObjectFitNone = this.objectFit === objectFit.NONE;
const { faceRect } = face;
const interPupillaryDistance = this.getInterPupillaryDistance(annotations, face);
for (let i = 0; i < 5; i += 1) {
this.#toggleLightBulb(i, starRating >= i);
}
const { width, arcHeight } = this.#renderSettings.mask;
const borderColor = `hsl(${interPupillaryDistance / 10 * 120},100%,50%)`;
const { x, y, width: w, height: h } = faceRect;
const strokeWidth = Math.trunc(width / 100).toString();
const topX = this.#offsetX + this.#scaleX * x;
const topY = this.#offsetY + this.#scaleY * y;
const bottomX = this.#offsetX + (w + x) * this.#scaleX;
const bottomY = this.#offsetY + (y + h) * this.#scaleY;
const centerX = (topX + bottomX) / 2;
const arcX = isObjectFitNone ? w : width / 2 * 0.7;
const foreHeadHeight = h / 5 * this.#scaleY;
const chinHeight = h / 2 * this.#scaleY;
const arcBottom = isObjectFitNone === true ? bottomY + chinHeight : bottomY + arcHeight * 0.8;
const arcTop = isObjectFitNone === true ? topY - foreHeadHeight : topY - arcHeight * 0.8;
const arcYChin = isObjectFitNone === true ? chinHeight : arcHeight;
const arcYForeHead = isObjectFitNone === true ? foreHeadHeight : arcHeight;
this.#isFaceInsideOval(topX, topY, bottomX, bottomY);
if (this.#renderSettings.drawBorder) this.#faceBorder.setAttribute(
"d",
`M ${topX} ${topY} V ${bottomY} H ${bottomX} V ${topY} z`
// top right
);
this.#chin.setAttribute("d", `${this.#getArc(centerX, arcBottom, arcX, arcYChin, 72, 35, 180, true)}`);
this.#chin.setAttribute("stroke", borderColor);
this.#chin.setAttribute("stroke-width", strokeWidth);
this.#forehead.setAttribute("d", `${this.#getArc(centerX, arcTop, arcX, arcYForeHead, 45, 90, 0, true)}`);
this.#forehead.setAttribute("stroke", borderColor);
this.#forehead.setAttribute("stroke-width", strokeWidth);
this.#foreheadGuide.setAttribute("stroke-width", strokeWidth);
this.#chinGuide.setAttribute("stroke-width", strokeWidth);
this.#setFacialGuidesVisibility(interPupillaryDistance < 7);
}
}
getInterPupillaryDistance(annotations, face) {
let interPupillaryDistance = 0;
if (annotations.silhouette && annotations.silhouette.length && face.posePoints && face.posePoints["3.11"] && face.posePoints["3.8"]) {
interPupillaryDistance = Math.floor(
face.posePoints["3.11"].point[0] - face.posePoints["3.8"].point[0]
);
const minValue = 20;
const maxValue = 30;
if (interPupillaryDistance < minValue)
interPupillaryDistance = minValue;
if (interPupillaryDistance > maxValue)
interPupillaryDistance = maxValue;
interPupillaryDistance -= minValue;
}
return interPupillaryDistance;
}
#setSize(width, height) {
this.#svg.setAttribute("viewbox", `0 0 ${Math.trunc(width)} ${Math.trunc(height)}`);
this.#svg.setAttribute("width", `${Math.trunc(width)}px`);
this.#svg.setAttribute("height", `${Math.trunc(height)}px`);
}
#setMaskPosition({ w, h, x, y }) {
const { left, width, top, arcHeight, rectHeight } = this.#renderSettings.mask;
if (this.#lightBulbs && this.#intermediateResults && this.#background) {
const lightBulbX = this.#renderSettings.lightBulbs.left - (this.#lightBulbs.getBBox().width + 25) * this.#renderSettings.lightBulbs.scale / 2;
const lightBulbY = this.#renderSettings.lightBulbs.top;
this.#lightBulbs.setAttribute(
"transform",
`translate(${lightBulbX} ${lightBulbY}) scale(${this.#renderSettings.lightBulbs.scale})`
);
const intermediateResultsX = this.#renderSettings.intermediateResults.left;
const intermediateResultsY = this.#renderSettings.intermediateResults.top - this.#intermediateResults.getBBox().height * this.#renderSettings.intermediateResults.scale;
this.#intermediateResults.setAttribute(
"transform",
`translate(${intermediateResultsX} ${intermediateResultsY}) scale(${this.#renderSettings.intermediateResults.scale})`
);
const faceMaskPath = {
top: `${this.#getArc(left, top + arcHeight, width / 2, arcHeight, 0, 180, 0, false)}`,
// top half circle
bottom: `${this.#getArc(left, top + arcHeight + rectHeight, width / 2, arcHeight, 0, 180, 180, false)}`
// bottom half circle
};
this.#background.setAttribute(
"d",
`M0,0 h${w + x * 2} v${h + y * 2} h-${w + x * 2} z ${faceMaskPath.top} z M${left - width / 2},${top + arcHeight} v${rectHeight} h${width} v-${rectHeight} z ${faceMaskPath.bottom} z `
);
this.#ovalBorder.setAttribute(
"d",
`${faceMaskPath.top} v${rectHeight} ${faceMaskPath.bottom.substring(faceMaskPath.bottom.indexOf("A"))} v -${rectHeight}`
// right line
);
this.#swooshContainer.setAttribute("transform", `matrix(0.866, -0.5, 0.55, 0.433, ${left}, ${top + arcHeight}), scale(4.7, 1.2)`);
this.#swooshGroupAnimateTransform.setAttribute("to", `0 ${rectHeight}`);
const pathLength = this.#ovalBorder.getTotalLength();
this.#ovalBorder.setAttribute("stroke-dashoffset", pathLength.toString());
this.#ovalBorder.setAttribute("stroke-dasharray", pathLength.toString());
this.#ovalBorderAnimation.setAttribute("values", `${pathLength};0`);
this.#foreheadGuide.setAttribute("d", `${this.#getArc(left, top + arcHeight * 0.25, width / 2 * 0.7, arcHeight, 45, 90, 0, true)}`);
this.#chinGuide.setAttribute("d", `${this.#getArc(left, top + rectHeight + arcHeight * 2.2, width / 2 * 0.7, arcHeight, 72, 35, 180, true)}`);
}
}
setFacialLandmarksVisibility(isVisible) {
this.#facialLandmarks.setAttribute("opacity", isVisible ? "1" : "0");
}
#setFacialGuidesVisibility(isVisible) {
this.#facialGuides.setAttribute("opacity", isVisible ? "0.5" : "0");
}
setIntermediateResults(points) {
let heartRate = "";
let bpSystolic = "";
let bpdiastolic = "";
let bloodPressure = "";
const pointList = Object.keys(points);
if (pointList.includes("BP_SYSTOLIC")) bpSystolic = points.BP_SYSTOLIC.value;
if (pointList.includes("BP_DIASTOLIC")) bpdiastolic = points.BP_DIASTOLIC.value;
if (pointList.includes("HR_BPM")) heartRate = parseInt(points.HR_BPM.value, 10).toString();
if (bpSystolic && bpdiastolic) bloodPressure = `${bpSystolic}/${bpdiastolic}`;
this.#intermediateResults.setAttribute("visibility", heartRate ? "visible" : "hidden");
this.#heartRateText.textContent = heartRate;
this.#bloodPressureText.textContent = bloodPressure;
}
setMaskVisibility(isVisible) {
this.#svg.style.display = isVisible ? "block" : "none";
}
// TODO: update resize
resize(resizeInfo) {
const { mediaElementSize, videoElementSize, frameInfo } = resizeInfo;
this.#setSize(mediaElementSize.width, mediaElementSize.height);
this.#setProgressbarWidth(mediaElementSize.width);
this.#setFrameInfo(frameInfo, videoElementSize);
const { width, height } = mediaElementSize;
const availableWidth = width;
let scale = 1;
if (availableWidth < 601) {
scale = 0.8;
}
if (availableWidth > 600) {
scale = 0.95;
}
if (availableWidth > 767) {
scale = 1.1;
}
if (availableWidth > 992) {
scale = 1.25;
}
const arcHeight = height / 6.6;
const rectHeight = arcHeight * 2.5;
const w = arcHeight * 2.8;
const l = availableWidth / 2;
const lightBulbTop = 20;
const lightBulbBottom = lightBulbTop + scale * 40;
this.#setRenderSettings(
// mask
{
width: w,
arcHeight,
rectHeight,
top: lightBulbBottom + 30,
left: l
},
// light bulbs
{
left: l,
top: lightBulbTop,
scale
},
//intermediate results
{
top: height - 10,
left: 5,
scale: scale - 0.25
}
);
this.#setMaskPosition({
w: videoElementSize.width,
h: videoElementSize.height,
x: videoElementSize.offsetX,
y: videoElementSize.offsetY
});
}
}
export { TeleMask, objectFit };