JSFiddle - React, Tailwind, and code Playground
HTML
<div id="page">
<div class="tbc-grids">
<div class="tbc-grid"></div>
<div class="tbc-grid"></div>
<div class="tbc-grid"></div>
<div class="tbc-grid"></div>
<div class="tbc-grid"></div>
<div class="tbc-grid"></div>
<div class="tbc-grid"></div>
<div class="tbc-grid"></div>
<div class="tbc-grid"></div>
<div class="tbc-grid"></div>
</div>
<div class="tbc-axes">
<div class="tbc-x-axis">
<ul class="tbc-ticks">
<li class="tbc-tick">Cost Efficiency</li>
<li class="tbc-tick">Cost First Installation</li>
<li class="tbc-tick">Performance</li>
<li class="tbc-tick">Quality</li>
<li class="tbc-tick">New Solution / New Feature</li>
</ul>
</div>
<div class="tbc-y-axis">
<ul class="tbc-ticks">
<li class="tbc-tick">Incremental</li>
<li class="tbc-tick">Significant</li>
</ul>
</div>
</div>
<div id="technology-benefit-chart"></div>
<div id="tbc-scope-wrapper">
<ul>
<li>
<div class="tbc-scope-marker ext very-broad" data-scope="1"></div> Very broad
</li>
<li>
<div class="tbc-scope-marker ext middle" data-scope="2"></div> Middle
</li>
<li>
<div class="tbc-scope-marker ext very-narrow" data-scope="3"></div> Very Narrow
</li>
</ul>
</div>
</div>
CSS
#page {
width: 720px;
margin:10px auto;
border:1px solid;
position: relative;
height: 247px;
}
#tbc-scope-wrapper li {
height: 60px;
}
#technology-benefit-chart {
position:absolute;
width: 500px;
height: 200px;
border: 1px solid #ccc;
top: 0;
left: 30px;
}
.tbc-grids{
position:absolute;
width: 500px;
height: 200px;
border: 1px solid #f00;
top: 0;
left: 30px;
}
.tbc-grid{
width: 99px;
height: 99px;
border-right: 1px dashed #ccc;
border-bottom: 1px dashed #ccc;
float:left;
}
#tbc-scope-wrapper {
position: absolute;
width: 186px;
height: 200px;
border: 1px solid #ccc;
right: 0;
top: 0;
}
ul, li {
list-style: none;
text-align: center;
}
.tbc-scope-marker.in-canvas {
position: absolute;
}
.tbc-scope-marker {
position: relative;
width:1px;
height:1px;
background: black;
}
.tbc-scope-marker::after {
content:" ";
position: absolute;
width:10px;
height:10px;
background: black;
left: -5px;
top: -5px;
opacity: 0.1;
}
.tbc-scope-marker.middle::after {
width:20px;
height:20px;
left: -10px;
top: -10px;
}
.tbc-scope-marker.very-narrow::after {
width:30px;
height:30px;
left: -15px;
top: -15px;
}
.tbc-axes {
height: 230px;
width: 530px;
position: absolute;
left: 0;
top: 0;
}
.tbc-x-axis {
position: absolute;
bottom: 0;
width: 500px;
height: 30px;
right: 0;
}
.tbc-y-axis {
position: absolute;
left: -85px;
width: 200px;
height: 30px;
-ms-transform: rotate(-90deg);
-webkit-transform: rotate(-90deg);
transform: rotate(-90deg);
top: 85px;
}
.tbc-ticks {
margin: 0;
padding: 0;
}
.tbc-axes .tbc-tick {
float: left;
font-size: 11px;
padding: 7px;
width: 85px;
}
JavaScript
var tbcCanvas = jQuery('#technology-benefit-chart');
jQuery('.tbc-scope-marker').draggable({
helper: 'clone',
});
tbcCanvas.droppable({
accept: '.tbc-scope-marker.ext',
drop: function (event, ui) {
tbcCanvas.find('.tbc-scope-marker').remove();
ui.draggable.clone().addClass('in-canvas').css({
left: Math.round((ui.offset.left - tbcCanvas.offset().left - 50)/100)*100 + 50,
top: Math.round((ui.offset.top - tbcCanvas.offset().top - 50)/100)*100 + 50
})
.removeClass('ext')
.draggable({
containment: tbcCanvas,
stop: tbcUpdateRating,
grid: [ 100, 100 ]
})
.appendTo(tbcCanvas);
tbcUpdateRating()
}
});
function tbcUpdateRating() {
var inCanvasMarker = jQuery('.tbc-scope-marker.in-canvas');
var x = (inCanvasMarker.position().left + 50)/100;
var y = (200 - inCanvasMarker.position().top+50)/100;
var rating = {
scope: inCanvasMarker.data('scope'),
x: x,
y: y
}
console.log(rating);
}