JSFiddle - React, Tailwind, and code Playground

HTML

<!doctype html>
<html>
    <head>
        <title>Perpective distort of path in SVG</title>
        <meta charset="utf-8" />
        <script src="http://code.jquery.com/jquery-1.8.2.js"></script>
        <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js"></script>
        <script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
    </head>
    <body>
        <svg style="position: absolute; left: 0px; top: 0px; pointer-events: fill; " xmlns="http://www.w3.org/2000/svg" version="1.1" width="2000" height="2000">
            <path id="path_1" style="stroke-width: 1px; stroke-opacity: 1; fill-opacity: 0.5; cursor: auto; pointer-events: fill; " fill="#70ff00" stroke="#000000"...

CSS

svg {position:absolute;}

JavaScript

var path_source = $("#path_1").attr("d");
// Get bounding box of text path
var bounds = $("#path_1")[0].getBoundingClientRect();

// Make array of coordinates, every array member represent corner of text path
var source = new Array(
{x:bounds.left,y:bounds.top},
{x:bounds.right,y:bounds.top},
{x:bounds.right,y:bounds.bottom},
{x:bounds.left,y:bounds.bottom}
);

// Create SVG with circles and joining lines
var R = Raphael("canvas", 2000, 2000);    
var l0 = R.path("M10 10L100 100").attr({stroke:"blue","stroke-width":2});
var l1 = R.path("M10 10L100 110").attr({stroke:"blue","stroke-width":2});
var l2 = R.path("M10 10L100 120").attr({stroke:"blue","stroke-width":2});
var l3 = R.path("M10 10L100 130").attr({stroke:"blue","stroke-width":2});
var dl0 = R.path("M10 10L100 130").attr({stroke:"red","stroke-width":2});
var dl1 = R.path("M10 10L100 130").attr({stroke:"red","stroke-width":2});
var c0 = R.circle(100, 100, 10).attr({fill: "blue",stroke: "none"});
var c1 = R.circle(100, 110, 10).attr({fill: "blue",stroke: "none"});
var c2 = R.circle(100, 120, 10).attr({fill: "blue",stroke: "none"});
var c3 = R.circle(100, 130, 10).attr({fill: "blue",stroke: "none"});

// Corner drag functions (start, move, up)
var start = function () {
    // storing original coordinates
    this.ox = this.attr("cx");
    this.oy = this.attr("cy");
},
move = function (dx, dy) {
    // move will be called with dx and dy
    this.attr({cx: this.ox + dx, cy: this.oy + dy});
    updatelines();
    update_text();
},
up = function () {
    // restoring state
};

// Function updates lines between corner circles
function updatelines()
{
    $(l0.node).attr({d:"M"+c0.attr("cx")+","+c0.attr("cy")+"L"+c1.attr("cx")+","+c1.attr("cy")});
    $(l1.node).attr({d:"M"+c1.attr("cx")+","+c1.attr("cy")+"L"+c2.attr("cx")+","+c2.attr("cy")});
    $(l2.node).attr({d:"M"+c2.attr("cx")+","+c2.attr("cy")+"L"+c3.attr("cx")+","+c3.attr("cy")});
   ...