JSFiddle - React, Tailwind, and code Playground

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="product-images-container">
    <label for="curve">Curve</label><input size="80" type="text" id="curve" name="curve" value="40,228,100,260,270,260,330,240">
    <label for="text">Text</label><input size="80" type="text" id="text" name="text" value="testing 1234567890">
    <label for="offset">Y offset</label><input size="80" type="number" id="offset" name="offset" value="5">
    <label for="fontsize">Font size</label><input size="80" type="number" id="fontsize" name="fontsize" value="20">
<div class="engravingArea">
<div id="canvasDiv"></div>
</div>
    
<img class="productImage" src="https://i.imgur.com/BaoChJT.jpeg"> 
</div>

CSS

.product-images-container {
  
    width:100%;
  position:relative;
}
canvas {
  position: absolute;
  top: 0;
}
.productImage {
  
  width: 100%
  
}
.engravingArea {
    position: relative;
}

#canvasDiv > canvas {
    width:100%;
    height: auto;
}

JavaScript

var first = true;

var productImage = document.getElementsByClassName('productImage')[0];
var curveOffset = document.getElementById('offset');
var fontSize = document.getElementById('fontsize');

$(productImage).on('load', function() {
	startIt();
});


function startIt()
{
    canvasDiv = document.getElementById('canvasDiv');
    canvasDiv.innerHTML = '<canvas id="layer0" width="' + productImage.naturalWidth + '" height="' + productImage.naturalHeight + '"></canvas>'; //for IE
    canvas = document.getElementById('layer0');
    ctx = canvas.getContext('2d');
    ctx.fillStyle = "green";
    curve = document.getElementById('curve');
    curveText = document.getElementById('text');
    scale = productImage.naturalWidth/400;
    $(curve).keyup(function(e) {changeCurve();});
    $(curveText).keyup(function(e) {changeCurve();});
    
    
    $(curveOffset).on('change', changeCurve);
    $(fontSize).on('change', changeCurve);
    
       
    if (first)
    {
        changeCurve();
        first = false;
    }
    
}

function changeCurve()
{
points = curve.value.split(',');  
offset = (parseInt(curveOffset.value) || 0);
ctx.font = (parseInt(fontSize.value) || 20)*scale + "px Courier New";

    if (points.length == 8)
        drawStack();
        
    
  
}

function drawStack()
{
    Ribbon = {maxChar: 50, startX: points[0]*scale, startY: (points[1] - offset)*scale, 
              control1X: points[2]*scale, control1Y: (points[3] - offset)*scale, 
              control2X: points[4]*scale, control2Y: (points[5] - offset)*scale, 
              endX: points[6]*scale, endY: (points[7] - offset)*scale};
    
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.save();
    ctx.beginPath();
    
    ctx.moveTo(Ribbon.startX,Ribbon.startY);
    ctx.bezierCurveTo(Ribbon.control1X,Ribbon.control1Y,
                   Ribbon.control2X,Ribbon.control2Y,
                   Ribbon.endX,Ribbon.endY);
    
    ctx.stroke();
    ctx.restore();
    
  ...