1. https://appdevelopermagazine.com/programming
  2. https://appdevelopermagazine.com/awesome-demo-of-cloth-(fabric)-using-html5/
3/25/2013 9:26:07 AM
Awesome Demo of Cloth (fabric) using HTML5
\news_old\files\Cloth-HTML5-20130325-092604.png
App Developer Magazine

Programming

Awesome Demo of Cloth (fabric) using HTML5


Monday, March 25, 2013

Richard Harris Richard Harris


The flexibly of HTML5 and the power of browser physics meet in this neat little demo on fabric which demonstrats how far along real-time simulations have come.


CSS Code:
* {
margin: 0;
  background:#333;
}

p {
  position:absolute;
  top:16px;
  width:auto;
  left:620px;
  color: #777;
  font-family:sans-serif;
  font-size:20px;
}


JS Code:

// settings

var physics_accuracy = 3,
mouse_influence   = 20, 
mouse_cut     = 6,
gravity         = 900, 
  cloth_height     = 30,
cloth_width       = 50,
start_y       = 20,
spacing       = 7,
tear_distance   = 60;


window.requestAnimFrame =
window.requestAnimationFrame       ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame    ||
window.oRequestAnimationFrame      ||
window.msRequestAnimationFrame     ||
function(callback) {
    window.setTimeout(callback, 1000 / 60);
};

var canvas,
ctx,
points,
physics,
mouse = {
down: false,
button: 1,
x: 0,
y: 0,
px: 0,
py: 0
};

window.onload = function() {

canvas = document.getElementById('c');
ctx    = canvas.getContext('2d');

canvas.width  = 600;//window.innerWidth;
canvas.height = 320;//window.innerHeight;

canvas.onmousedown = function(e) {
mouse.button = e.which;
mouse.px = mouse.x;
mouse.py = mouse.y;
mouse.x = e.clientX || e.layerX;
mouse.y = e.clientY || e.layerY;
mouse.down = true;
e.preventDefault();
};

canvas.onmouseup = function(e) {
mouse.down = false;
e.preventDefault();
};

canvas.onmousemove = function(e) {
mouse.px = mouse.x;
mouse.py = mouse.y;
mouse.x = e.clientX || e.layerX;
mouse.y = e.clientY || e.layerY;
e.preventDefault();
};

canvas.oncontextmenu = function(e) {
e.preventDefault(); 
};

init();
};

var Constraint = function(p1, p2, spacing, tear_distance) {

this.p1 = p1;
this.p2 = p2;
this.length = spacing;
this.tear_distance = tear_distance;
};

Constraint.prototype.solve = function() {

var diff_x = this.p1.x - this.p2.x,
diff_y = this.p1.y - this.p2.y,
dist = Math.sqrt(diff_x * diff_x + diff_y * diff_y),
diff = (this.length - dist) / dist;

if (dist > this.tear_distance) this.p1.remove_constraint(this);

var scalar_1 = ((1 / this.p1.mass) / ((1 / this.p1.mass) + (1 / this.p2.mass))),
scalar_2 = 1 - scalar_1;

this.p1.x += diff_x * scalar_1 * diff;
this.p1.y += diff_y * scalar_1 * diff;

this.p2.x -= diff_x * scalar_2 * diff;
this.p2.y -= diff_y * scalar_2 * diff;
};

Constraint.prototype.draw = function() {
ctx.moveTo(this.p1.x, this.p1.y);
ctx.lineTo(this.p2.x, this.p2.y);
};

var Point = function(x, y) {

this.x = x;
this.y = y;
this.px = x;
this.py = y;
this.ax = 0;
this.ay = 0;
this.mass = 1;
this.constraints = [];
this.pinned = false;
this.pin_x;
this.pin_y;
};

Point.prototype.update = function(delta) {

this.add_force(0, this.mass * gravity);

var vx = this.x - this.px,
  vy = this.y - this.py;

delta *= delta;
nx = this.x + 0.99 * vx + 0.5 * this.ax * delta;
ny = this.y + 0.99 * vy + 0.5 * this.ay * delta;

this.px = this.x;
this.py = this.y;

this.x = nx;
this.y = ny;

this.ay = this.ax = 0
};

Point.prototype.update_mouse = function() {

if (!mouse.down) return;

var diff_x = this.x - mouse.x,
diff_y = this.y - mouse.y,
dist   = Math.sqrt(diff_x * diff_x + diff_y * diff_y);

if (mouse.button == 1) {

if(dist < mouse_influence) {
this.px = this.x - (mouse.x - mouse.px) * 1.8;
this.py = this.y - (mouse.y - mouse.py) * 1.8;
}

} else if (dist < mouse_cut) this.constraints = [];
};

Point.prototype.draw = function() {

if (this.constraints.length <= 0) return;
var i = this.constraints.length;
while(i--) this.constraints[i].draw();
};

Point.prototype.solve_constraints = function() {

var i = this.constraints.length;
while(i--) this.constraints[i].solve();

if (this.y < 1) this.y = 2 * (1) - this.y;
else if (this.y > canvas.height-1) this.y = 2 * (canvas.height - 1) - this.y;
 
if (this.x > canvas.width-1) this.x = 2 * (canvas.width - 1) - this.x;
else if (this.x < 1) this.x = 2 * (1) - this.x;

if (this.pinned) {
this.x = this.pin_x;
this.y = this.pin_y; 
}
};

Point.prototype.attach = function(P, spacing, tear_distance) {

this.constraints.push(
new Constraint(this, P, spacing, tear_distance)
);
};

Point.prototype.remove_constraint = function(lnk) {

var i = this.constraints.length;
while(i--) if(this.constraints[i] == lnk) this.constraints.splice(i, 1);
};

Point.prototype.add_force = function(fX, fY) {

this.ax += fX/this.mass;
this.ay += fY/this.mass;
};

Point.prototype.pin = function(pX, pY) {

this.pinned = true;
this.pin_x = pX;
this.pin_y = pY;
};

var Physics = function() {

this.delta_sec = 16 / 1000;
this.accuracy = physics_accuracy;
};

Physics.prototype.update = function() {

var i = this.accuracy;

while(i--) {
var p = points.length;
while(p--) points[p].solve_constraints();
}

i = points.length;
while(i--) {
points[i].update_mouse();
points[i].update(this.delta_sec);
}
};

function init() {
  
physics = new Physics();
points = [];
build_cloth();
update();
}

function update() {

ctx.clearRect(0, 0, canvas.width, canvas.height);

physics.update();
  
ctx.strokeStyle = 'rgba(222,222,222,0.6)';
ctx.beginPath();
var i = points.length;
while(i--) points[i].draw();
ctx.stroke();

requestAnimFrame(update);
}

function build_cloth() {

var start_x = canvas.width / 2 - cloth_width * spacing / 2;

for(var y = 0; y <= cloth_height; y++) {

for(var x = 0; x <= cloth_width; x++) {

var p = new Point(start_x + x * spacing, y * spacing + start_y);

0 != x &&
p.attach(points[points.length - 1], spacing, tear_distance);

0 != y &&
p.attach(points[(y - 1) * (cloth_width + 1) + x], spacing, tear_distance);

0 == y &&
p.pin(p.x, p.y);

points.push(p)
}
}
}

HTML Code:

  Tear the cloth with your mouse.

  Right click and drag to cut the cloth.

  Reduce physics_accuracy if it's laggy, increase it for a better effect.

Awesome Demo of Cloth (fabric) using HTML5




Read more: http://codepen.io/stuffit/pen/KrAwx




Subscribe to App Developer Magazine

Become a subscriber of App Developer Magazine for just $5.99 a month and take advantage of all these perks.

MEMBERS GET ACCESS TO

  • - Exclusive content from leaders in the industry
  • - Q&A articles from industry leaders
  • - Tips and tricks from the most successful developers weekly
  • - Monthly issues, including all 90+ back-issues since 2012
  • - Event discounts and early-bird signups
  • - Gain insight from top achievers in the app store
  • - Learn what tools to use, what SDK's to use, and more

    Subscribe here



Stay Updated

Sign up for our newsletter for the headlines delivered to you

SuccessFull SignUp

Featured Stories


API scoring tool shows if your API is ready for AI
API scoring tool shows if your API is ready for AI Monday, June 22, 2026


Agentic AI Reality Check: The Million-Dollar Mistake Hiding Inside ERP
Agentic AI Reality Check: The Million-Dollar Mistake Hiding Inside ERP Friday, June 19, 2026




Influencer Debate AI Anthropic IPO Reveals Industry Concerns
Influencer Debate AI Anthropic IPO Reveals Industry Concerns Wednesday, June 17, 2026


Subscription apps are losing users faster than ever
Subscription apps are losing users faster than ever Tuesday, June 16, 2026


DomainTools announces real time threat feeds
DomainTools announces real time threat feeds Monday, June 15, 2026


Take It Down Act results in warning letters from FTC
Take It Down Act results in warning letters from FTC Friday, June 12, 2026


Nvidia valuation fears grow
Nvidia valuation fears grow Friday, June 12, 2026


Anthropic launches Claude Design
Anthropic launches Claude Design Wednesday, June 10, 2026


Spotlite Expands Into AI Era With New IP Protection Tool
Spotlite Expands Into AI Era With New IP Protection Tool Wednesday, June 3, 2026


Spotify and UMG strike landmark AI music licensing deal
Spotify and UMG strike landmark AI music licensing deal Thursday, May 28, 2026


Get More App News