JSFiddle - React, Tailwind, and code Playground

HTML

<!DOCTYPE html>
<html>
<head>
	<script type='text/javascript' src='jquery-2.1.0.js'></script>
	<script type='text/javascript' src='squareProgress.js'></script>
	<script type='text/javascript'>
	</script>
	<style type='text/css'>
		canvas
		{
			transform: rotateZ(45deg);
			padding: 40px;
		}
	</style>
</head>
<body>

	<canvas id="canvas" width="200" height="200"></canvas>

</body>
</html>

JavaScript

var SquareProgress = function(canvas, pct){
	this.canvas = canvas;
	this.context = this.canvas.getContext("2d");

	this.pct = pct;

	this.x = 0;
	this.y = 0;
	this.width = 200;
	this.height = 200;

	this.innerWidth = 170;
	this.innerHeight = 170;
	this.innerX = 15;
	this.innerY = 15;

	this.centerInner = true;

	this.duration = 8000;
	this.animationStart = null;

	this.ease = function (t) { return t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1 };
};

SquareProgress.prototype.init = function(){
	if(this.centerInner){
		this.centerInnerRect();
	}

	this.setCornerCoords();
	this.reset();
	this.animationStart = this.getTime();
};

SquareProgress.prototype.draw = function(){
	this.init();
	this.drawToPct(this.pct);
};

SquareProgress.prototype.getTime = function(){
	return window.performance != undefined ? window.performance.now() : Date.now();
};

SquareProgress.prototype.animate = function(){
	var self = this;

	var currentTime = window.performance != undefined ? window.performance.now() : Date.now();
	var timePassed = currentTime - this.animationStart;
	var pctOfDuration = this.ease(timePassed / this.duration);

	if(pctOfDuration >= 1){
		return;
	}

	var currentFramePct = pctOfDuration * this.pct;

	this.drawToPct(currentFramePct);

	requestAnimationFrame(function(){
		self.animate();
	});
};

SquareProgress.prototype.centerInnerRect = function(){
	this.innerX = ((this.width - this.innerWidth) / 2) + this.x;
	this.innerY = ((this.height - this.innerHeight) / 2) + this.y;
};

SquareProgress.prototype.getOuterPointFromPct = function(pct){
	var width = this.width,
		height = this.height,
		x = this.x,
		y = this.y;

	var rectC = (width + height) * 2;
	var ptAlongC = rectC * pct;
	
	var sideLimits = [
		width, // side 1
		width + height, // side 2,
		width * 2 + height, // side 3,
		rectC // side 4
	];

	var lastLimit = -1;
	var sideContainingPt = 0;
	
	while(ptAlongC > lastLimit && sideContainingPt < 4){
		lastLimit =...