JSFiddle - React, Tailwind, and code Playground
by Jesse M
HTML
<script src="https://jessemorgan.me/html2canvas/html2canvas.js"></script>
<link href="https://fonts.googleapis.com/css?family=Mali|Roboto&display=swap" rel="stylesheet">
<div class="one-third">
<label>First box text<br />
<input type="text" data-element="elem2" value="" placeholder="Enter custom text" />
</label>
</div>
<div class="one-third">
<label>Second box text<br />
<input type="text" data-element="elem1" value="" placeholder="Enter custom text" />
</label>
</div>
<div class="one-third">
<label class="rotate">Rotate</label><br />
<!-- button class="left">↺</button -->
<button class="right">↻ 45°</button> OR <input class="degrees" type="number" max="359" min="0" value="0" />
</div>
<div class="one-third">
<label>Font<br />
<select id="font">
<option value="Roboto">Roboto</option>
<option value="Helvetica">Helvetica</option>
<option value="Mali">Mali</option>
</select>
</label>
</div>
<div class="one-third">
<label>Font size<br />
<select id="font-size">
<option value="10px">10px</option>
<option value="11px">11px</option>
<option value="12px">12px</option>
<option value="13px">13px</option>
<option value="14px">14px</option>
<option value="15px">15px</option>
<option value="16px">16px</option>
</select>
</label>
</div>
<div class="one-third">
<label>Alignment<br />
<select id="align">
<option value="left">Left</option>
<option value="right">Right</option>
<option value="center">Center</option>
</select>
</label>
</div>
<div class="one-third">
<label>Opacity<br />
<input id="opacity" type="number" min="1" max="100" value="100" />
</label>
</div>
<div class="one-third">
<label>Letter Spacing<br />
<input id="letter-spacing" type="number" min="0" max="100" value="0" />
</label>
</div>
<div class="one-third">
<label>Choose an image for the green box<br />
<input id="image" type="file" />
</label>
</div>
<div class="message-container">
<p...
CSS
body {
font-family: 'Roboto', sans-serif;
}
.one-third {
width: 33%;
display: inline-block;
margin: 0;
padding: 0;
}
label {
display: inline-block;
padding: 5px;
}
#container {
position: relative;
background-color: blue;
margin: 10px auto;
}
#container > div {
position: absolute;
cursor: move;
-webkit-user-select: none;
-moz-user-select: none;
-o-user-select: none;
-ms-user-select: none;
-khtml-user-select: none;
user-select: none;
transition: outline 0.2s ease-in-out, opacity 0.2s ease-in-out;
}
#elem1 {
background-color: green;
z-index: 1;
background-size: contain !important;
}
#gripY, #gripX {
position: absolute;
text-align: center;
}
#gripY {
top: -10px;
left: calc(50% - 10px);
cursor: ns-resize;
}
#gripX {
left: -10px;
top: calc(50% - 10px);
cursor: ew-resize;
}
#elem2 {
background: rgba(255, 0, 0, 0.75);
z-index: 2;
}
#image-container {
z-index: 3;
background: rgba(255, 255, 255, 0.3);
}
.selected {
outline: 3px solid #fff;
}
.layer button {
display: none;
position: absolute;
bottom: 0;
outline: none;
border: none;
width: 20px;
height: 20px;
cursor: pointer;
transition: width 0.1s ease-in-out, height 0.1s ease-in-out;
}
.backward {
left: 0;
border-radius: 0 5px 0 0;
}
.forward {
right: 0;
border-radius: 5px 0 0 0;
}
.backward:hover, .forward:hover {
width: 28px;
height: 28px;
}
.message-container {
min-height: 30px;
}
.message {
display: none;
color: #000;
}
JavaScript
$('#container > div').mousedown(function(){
$('#container div').removeClass('selected');
$('label:not(.rotate)').css('background', 'none');
var id = $(this).attr('id');
$(this).addClass('selected');
$('[data-element="' + id + '"]').closest('label').css('background', '#4d4d4d');
$('#font').val($(this).find('p').css('font-family'));
$('.degrees').val(parseInt(getRotationDegrees($(this))));
$('#letter-spacing').val($(this).find('p').css('letter-spacing').replace('px', ''));
$('#font-size').val($(this).find('p').css('font-size'));
});
$('input[type="text"]').on('keyup', function(){
$('#' + $(this).data('element') + ' > p').text($(this).val());
});
$('.layer').hover(function(){
$(this).find('button').fadeIn();
}, function(){
$(this).find('button').delay(300).fadeOut();
});
function getRotationDegrees(obj) {
var matrix = obj.css('transform');
if(matrix !== 'none') {
var values = matrix.split('(')[1].split(')')[0].split(',');
var a = values[0];
var b = values[1];
var angle = Math.round(Math.atan2(b, a) * (180/Math.PI));
} else { var angle = 0; }
return (angle < 0) ? angle + 360 : angle;
}
$('.right').click(function(){
var degrees = parseInt(getRotationDegrees($('#container').find('.selected')));
if(degrees === 360){
degrees = 0;
}
degrees = degrees + 45;
$('#container').find('.selected').css('transform', 'rotate(' + degrees + 'deg)');
$('.degrees').val(degrees);
});
$('.degrees').on('change keyup', function(){
$('#container').find('.selected').css('transform', 'rotate(' + $(this).val() + 'deg)');
});
$('.forward').click(function(e){
e.preventDefault();
var currentLayer = parseInt($(this).closest('div').css('z-index'));
if(currentLayer === 5){
$('.message').text('the element is at the highest layer').fadeIn(function(){
$(this).delay(1500).fadeOut(function(){
$(this).empty();
});
});
}else{
$(this).closest('div').css('z-index', currentLayer +...