JSFiddle - React, Tailwind, and code Playground

by Vladimir

HTML

<div class="wrapper">
  <div class="block1"></div>
  <div class="block2"></div>
  <div class="key"></div>
</div>

CSS

.wrapper {
  width: 960px;
  height: 720px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto;
  background-image: url(http://beerhold.it/960/722);
  background-repeat: no-repeat;
  backgorund-position: center center;
  position: relative;
}
.key {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 10em;
  height: 10em;
  border: 2em solid rgba(255, 255, 255, .3);
  border-radius: 10em;
}
.block1,
.block2 {
  position: absolute;
  top: 0;
  width: 100%;
  height: 720px;
}
.block1 {
  left: 0;
  background-color: rgba(255, 0, 0, .2);
}
.block2 {
  right: 0;
   background: rgba(0, 0, 0, 0.7);
}

JavaScript

var r = 16; // радиус круга в %
var steps = 36; // количество точек полигона, чем больше - тем точнее окружность
var rezArray = [];

var startY = 50 - r;
var pathY = 2*r;
var stepY = pathY/steps;

for(var i = 0; i < steps; i++) {
	var dotY = startY + stepY*i;
  var dotX = i==0? 0: Math.pow((r*r - (r-stepY*i)*(r-stepY*i)), 0.5);
  dotX = dotX * 720/960; // коэф. соотношения сторон (т.к. полигон задается в процентах, а картинка не квадратная)
  dotX = 50 - dotX;
  rezArray.push(dotX + "% " + dotY +"%");
}
rezArray.push("50% " + (startY+pathY) +"%");

var clipPath = "polygon(100% 0%, 50% 0%, " + rezArray.join(", ") + ", 50% 100%, 100% 100%)";
console.log(clipPath);
$(".block2").css("clip-path", clipPath);

var clipPath2 = "polygon(0% 0%, 50% 0%, " + rezArray.join(", ") + ", 50% 100%, 0% 100%)";
console.log(clipPath2);
$(".block1").css("clip-path", clipPath2);