JSFiddle - React, Tailwind, and code Playground

by Michael Prosser

HTML

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div class="ui-clippath">
  <div class="ui-clippath-points">
    <div class="ui-clippath-cropper">
    </div>
  </div>
</div>
<div class="ui-clippath-menu">
</div>
<img class="ui-clippath-realtarget" src="http://aninoob.com/gamemaker/image.library/themes/spacecraft/spacecraftbg.jpg" height="264" style="position:absolute;left:212px;top:0px;" />

CSS

body{
  margin:0px;
}
.ui-clippath{
  width:200px;
  height:200px;
  position:relative;
  background-color:#333;
  padding:6px;
  user-select:none;
}
.ui-clippath-points{
  width: 212px;
    height: 212px;
    position: relative;
}
.ui-clippath-menu{
  width:194px;
  height:24px;
  position:relative;
  background-color:#111;
  border-top:solid 10px #111;
  padding:9px;
}
.ui-clippath-menu li{
  width:20px;
  height:20px;
  margin:2px;
  position:relative;
  display:inline-block;
  background-color:#999;
  cursor:pointer;
  user-select:none;
}
.ui-clippath-cropper{
  width:200px;
  height:200px;
  position:relative;
  background-color:#000;
}
.ui-clippath-points>.path-point{
  position:absolute !important;
  left:0px;
  top:0px;
  margin-left:-6px;
  margin-top:-6px;
  width:12px;
  height:12px;
  background-color:rgba(255,255,255,1);
  z-index:10;
  border-radius:50%;
  text-align:center;
  font-size:8px;
  font-family:helvetica;
  line-height:12px;
  cursor:move;
}

JavaScript

var noobshapes = {
	
  clippath_target: $('.ui-clippath-cropper'),
  clippath_realtarget: $('.ui-clippath-realtarget'),
  clippath_ui: $('.ui-clippath-points'),
  clippath_menu: $('.ui-clippath-menu'),
  
	clippath_points: Array(),
  
  clippath_shapes: Array(
  	{ name: 'triangle', path: 'polygon(50% 0%, 0% 100%, 100% 100%)' },
    { name: 'trapezoid', path: 'polygon(20% 0%, 80% 0%, 100% 100%, 0% 100%)' },
    { name: 'parallelogram', path: 'polygon(25% 0%, 100% 0%, 75% 100%, 0% 100%)' },
    { name: 'rhombus', path: 'polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)' },
    { name: 'pentagon', path: 'polygon(50% 0%, 100% 38%, 82% 100%, 18% 100%, 0% 38%)' },
    { name: 'hexagon', path: 'polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%)' },
    { name: 'heptagon', path: 'polygon(50% 0%, 90% 20%, 100% 60%, 75% 100%, 25% 100%, 0% 60%, 10% 20%)' },
    { name: 'octogon', path: 'polygon(30% 0%, 70% 0%, 100% 30%, 100% 70%, 70% 100%, 30% 100%, 0% 70%, 0% 30%)' }
  ),
  
  clippath_addpoint: function(x,y){
  
  console.log("X: " + x + " y: " + y);
  
  	var point = $('<div class="path-point">' + parseInt(noobshapes.clippath_points.length+1) + '</div>');
    point.css('left',x +'px').css('top',y +'px');
  	point[0].properties = { x: x, y: y };
    point.draggable({
      containment: "parent",
      drag: function( event, ui ) {
      	
      	noobshapes.calculate_clippath();
      
      }
      
    });
    
    point.mousedown(function(e){
    
    	e.stopPropagation();
      
    }).click(function(e){
    
    	e.stopPropagation();
      
    }).mouseup(function(e){
    
    	e.stopPropagation();
      
    });
    
    noobshapes.clippath_ui.append(point);
    
    noobshapes.clippath_points.push(point);
    
    noobshapes.calculate_clippath();
    
  },
  
  calculate_clippath: function(){
  	
    var coords = Array();
    
    $('.path-point').each(function(index,element){
    
    	coords.push(parseInt(parseInt($(this).css('left'))/2) + '% ' +...