Home > Net >  Mapping image onto JS cloth and creating a slider
Mapping image onto JS cloth and creating a slider

Time:03-16

Here is all the code for the website, it has many bugs, like the footer which is stuck in the middle. So the idea is to create 11 different tissues in the format of this image mapped to the JS I have, bit i dont know how to do that.[![sample tissue][1]][1]

I would like to create a slider that functions when you click on the collection number it switchees to the next collection.

Also all the links only take the size and not the column width when hovered.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>$</title>
 <link rel="stylesheet" href="normalize.css">
  <style type="text/css">
    * {
    margin: 0;
    overflow: hidden;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    -o-user-select: none;
    user-select: none;
    font-family: sans-serif;
}
body {
}
#c {
    display: block;
    margin: 20px auto 0;
}
#info {
    position: absolute;
    left: -1px;
    top: -1px;
    width: auto;
    max-width: 420px;
    height: auto;
    background: #f8f8f8;
    border-bottom-right-radius: 10px;
    border:1px solid #ccc;
}
#top {
    background: #fff;
    width: 100%;
    height: auto;
    position: relative;
    border-bottom: 1px solid #eee;
}
p {
    font-family: Arial, sans-serif;
    color: #666;
    text-align: justify;
    font-size: 16px;
    margin: 0px 16px;
}
#github, #twitter {
  color:#3377ee;
  font-family: Helvetica, Arial, sans-serif;
  font-size: 14px;
  margin: 0 auto;
  text-align: center;
  text-decoration:none;
}
.center {
  text-align: center;
}
#net {
  text-align:center;
  white-space:nowrap;
  font-size:19px;
  background:rgba(0,0,0,0.1);
  padding:8px 12px;
  border-radius:8px;
  display:block;
  color:#888;
}
#net > span {
  color:#3377ee;
  font-family: Helvetica, Arial, sans-serif;
  font-size: 14px;
  display: block;
  margin: 0 auto;
  text-align: center;
  text-decoration:none;
}


.bull {
  opacity: 0.3;
  margin: 0 6px;
  font-size: 14px;
}

.row {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  border-bottom: 1px solid black;
}

.column {
  flex-basis: 100%;
  border-right: 1px solid black;
}

@media screen and (min-width: 800px) {
  .column {
    flex: 1;
  }
}

@media screen and (min-width: 800px) {
  ._25 {
    flex: 2.5;
  }
  ._55 {
    flex: 5.5;
  }
  ._20 {
    flex: 2;
  }
}
 a:link {
  text-decoration: none;
}

 a:visited {
  text-decoration: none;
  color: black;
}

a:hover {
  text-decoration: none;
  color: white;
background: black;}

 a:active {
  text-decoration: none;
    color: white;
background: black;
}
  </style>
</head>
<body>
<div >
  <div >
    <a href="">Rakṣas Sari collection</a>
  </div>
  <div >
   <a href=""> Concept</a>
  </div>
  <div >
   <a href=""> Process</a>
  </div>
</div>
<div >
  <div >
   <a href=""> Red Collection N°1</a>
  </div>
  <div >
   <a href=""> Collection N°2</a>
  </div>
  <div >
   <a href=""> Collection N°3</a>
  </div>
  <div >
   <a href=""> Collection N°4</a>
  </div>
  <div >
  <a href="">  Collection N°5</a>
  </div>
  <div >
  <a href="">  Collection N°6</a>
  </div>
  <div >
   <a href=""> Collection N°7</a>
  </div>
  <div >
   <a href=""> Collection N°8</a>
  </div>
  <div >
  <a href="">  Collection N°9</a>
  </div>
  <div >
   <a href=""> Collection N°10</a>
  </div>
  <div >
   <a href=""> Collection N°11</a>
  </div>
</div>
<div >
  <div >
    Project photoshoot
  </div>
  <div >
    <canvas id="c"></canvas>


  <div id="top">
    <a id="close" href="">Reset tissue</a>
  </div>
  </div>
  <div >
    Red is a celebratory color. It commemorates a couple’s union. It symbolizes love, sensuality, and passion. That’s why it features prominently in auspicious occasions, such as weddings, festivals, and births. As red also signifies chastity, it is the color of choice for brides. 
  </div>
</div>



  
<footer>
  <div >
  <div >
    ©Copyright Angelo Barbattini
  </div>
  <div >
   ECAL 2022
  </div>
</div>
</footer style="position: fixed;bottom: 0;">
<!--div id="new">
  Wobble some <a target="_blank" href="https://codepen.io/dissimulate/details/dJgMaO">jelly</a> <span >&bull;</span>
  Check out my <a target="_blank" href="https://www.instagram.com/abro_oks/">instagram!</a>
</div-->
<script type="text/javascript">
  document.getElementById("close").onmousedown = function (e) {
  e.preventDefault();
  document.getElementById("info").style.display = "none";
  return false;
};

// settings

var physics_accuracy = 3,
  mouse_influence = 20,
  mouse_cut = 5,
  gravity = 1200,
  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,
  cloth,
  boundsx,
  boundsy,
  mouse = {
    down: false,
    button: 1,
    x: 0,
    y: 0,
    px: 0,
    py: 0
  };

var Point = function (x, y) {
  this.x = x;
  this.y = y;
  this.px = x;
  this.py = y;
  this.vx = 0;
  this.vy = 0;
  this.pin_x = null;
  this.pin_y = null;

  this.constraints = [];
};

Point.prototype.update = function (delta) {
  if (mouse.down) {
    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 = [];
  }

  this.add_force(0, gravity);

  delta *= delta;
  nx = this.x   (this.x - this.px) * 0.99   (this.vx / 2) * delta;
  ny = this.y   (this.y - this.py) * 0.99   (this.vy / 2) * delta;

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

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

  this.vy = this.vx = 0;
};

Point.prototype.draw = function () {
  if (!this.constraints.length) return;

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

Point.prototype.resolve_constraints = function () {
  if (this.pin_x != null && this.pin_y != null) {
    this.x = this.pin_x;
    this.y = this.pin_y;
    return;
  }

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

  this.x > boundsx
    ? (this.x = 2 * boundsx - this.x)
    : 1 > this.x && (this.x = 2 - this.x);
  this.y < 1
    ? (this.y = 2 - this.y)
    : this.y > boundsy && (this.y = 2 * boundsy - this.y);
};

Point.prototype.attach = function (point) {
  this.constraints.push(new Constraint(this, point));
};

Point.prototype.remove_constraint = function (constraint) {
  this.constraints.splice(this.constraints.indexOf(constraint), 1);
};

Point.prototype.add_force = function (x, y) {
  this.vx  = x;
  this.vy  = y;

  var round = 400;
  this.vx = ~~(this.vx * round) / round;
  this.vy = ~~(this.vy * round) / round;
};

Point.prototype.pin = function (pinx, piny) {
  this.pin_x = pinx;
  this.pin_y = piny;
};

var Constraint = function (p1, p2) {
  this.p1 = p1;
  this.p2 = p2;
  this.length = spacing;
};

Constraint.prototype.resolve = 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 > tear_distance) this.p1.remove_constraint(this);

  var px = diff_x * diff * 0.5;
  var py = diff_y * diff * 0.5;

  this.p1.x  = px;
  this.p1.y  = py;
  this.p2.x -= px;
  this.p2.y -= py;
};

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

var Cloth = function () {
  this.points = [];

  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, start_y   y * spacing);

      x != 0 && p.attach(this.points[this.points.length - 1]);
      y == 0 && p.pin(p.x, p.y);
      y != 0 && p.attach(this.points[x   (y - 1) * (cloth_width   1)]);

      this.points.push(p);
    }
  }
};

Cloth.prototype.update = function () {
  var i = physics_accuracy;

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

  i = this.points.length;
  while (i--) this.points[i].update(0.016);
};

Cloth.prototype.draw = function () {
  ctx.beginPath();

  var i = cloth.points.length;
  while (i--) cloth.points[i].draw();

  ctx.stroke();
};

function update() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  cloth.update();
  cloth.draw();

  requestAnimFrame(update);
}

function start() {
  canvas.onmousedown = function (e) {
    mouse.button = e.which;
    mouse.px = mouse.x;
    mouse.py = mouse.y;
    var rect = canvas.getBoundingClientRect();
    (mouse.x = e.clientX - rect.left),
      (mouse.y = e.clientY - rect.top),
      (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;
    var rect = canvas.getBoundingClientRect();
    (mouse.x = e.clientX - rect.left),
      (mouse.y = e.clientY - rect.top),
      e.preventDefault();
  };

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

  boundsx = canvas.width - 1;
  boundsy = canvas.height - 1;

  ctx.strokeStyle = "#888";

  cloth = new Cloth();

  update();
}

window.onload = function () {
  canvas = document.getElementById("c");
  ctx = canvas.getContext("2d");

  canvas.width = 560;
  canvas.height = 350;

  start();
};

</script>
</body>
</html>```


  [1]: https://i.stack.imgur.com/Celmj.jpg

CodePudding user response:

The questioner is focusing on the problem of getting an actual image to look like material being moved with the wind.

The code presented to do this divides a canvas into small rectangular elements and moves each of those as required by the 'physics' given (value of gravity/wind for example).

The original just draws grid lines for each of these areas. What we need is for the equivalent rectangle in the original image to be copied to that point.

This snippet achieves this by adding a origx/y to the info kept about each point so that we know where to find the original rectangle.

It brings the image into an img element (it is important to wait until this is loaded before doing more with it) then copies it to an off-screen canvas that has the same dimensions as the one which will hold the material. This canvas is inspected when we need the 'mini image' to put at a given point.

WARNING: this code (even without the introduction of an image) is pretty processor intensive. On a farily powerful laptop with good GPU it was taking around 19% of CPU and not much less of GPU and the fan was whirring. This is even when there is no movement of the mouse. The code could do with a thorough look through, for example to stop the timer when user activity is completed, and perhaps putting the frame rate down (it's 60fps in the given code). I would not recommend it be put in a webpage and left there running - it will be a battery drainer.

<html xmlns="http://www.w3.org/1999/xhtml">

<head>
  <title></title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <!-- 
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    -->

  <script type="text/javascript" src=""></script>
  <link rel="stylesheet" type="text/css" href="">

  <style type="text/css">
    body {}
    
    .wrapper {}
    
    * {
      margin: 0;
      overflow: hidden;
      -webkit-user-select: none;
      -moz-user-select: none;
      -ms-user-select: none;
      -o-user-select: none;
      user-select: none;
    }
    
    body {
      background: #333;
    }
    
    canvas {
      background: #333;
      width: 100%;
      height: 376px;
      margin: 0 auto;
      display: block;
      border: solid red 2px;
    }
    
    #info {
      position: absolute;
      left: -1px;
      top: -1px;
      width: auto;
      max-width: 380px;
      height: auto;
      background: #f2f2f2;
      border-bottom-right-radius: 10px;
    }
    
    #top {
      background: #fff;
      width: 100%;
      height: auto;
      position: relative;
      border-bottom: 1px solid #eee;
    }
    
    p {
      font-family: Arial, sans-serif;
      color: #666;
      text-align: justify;
      font-size: 16px;
      margin: 10px;
    }
    
    a {
      font-family: sans-serif;
      color: #444;
      text-decoration: none;
      font-size: 20px;
    }
    
    #site {
      float: left;
      margin: 10px;
      color: #38a;
      border-bottom: 1px dashed #888;
    }
    
    #site:hover {
      color: #7af;
    }
    
    #close {
      float: right;
      margin: 10px;
    }
    
    #p {
      font-family: Verdana, sans-serif;
      position: absolute;
      right: 10px;
      bottom: 10px;
      color: #adf;
      border: 1px dashed #555;
      padding: 4px 8px;
    }
  </style>
  <img src="https://i.stack.imgur.com/Celmj.jpg" style="margin-top: -2000px; position: absolute;">
  <canvas width="1360" height="376" style="margin-top: -2000px; position: absolute;"></canvas>
  <script type="text/javascript">
    /*
    Copyright (c) 2013 lonely-pixel.com, Stuffit at codepen.io (http://codepen.io/stuffit)

    View this and others at http://lonely-pixel.com

    Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
    */


    const mycanvas = document.querySelector('canvas');
    const mycontext = mycanvas.getContext('2d');

    // settings


    var physics_accuracy = 5,
      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,
      cloth,
      boundsx,
      boundsy,
      mouse = {
        down: false,
        button: 1,
        x: 0,
        y: 0,
        px: 0,
        py: 0
      };

    window.onload = function() {
      // ADDED TO BRING IN THE IMAGE
      mycontext.clearRect(0, 0, mycanvas.width, mycanvas.height);
      mycontext.drawImage(document.querySelector('img'), 0, 0, 1180, 376);


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

      canvas.width = canvas.clientWidth;
      canvas.height = 376;

      canvas.onmousedown = function(e) {
        mouse.button = e.which;
        mouse.px = mouse.x;
        mouse.py = mouse.y;
        var rect = canvas.getBoundingClientRect();
        mouse.x = e.clientX - rect.left,
          mouse.y = e.clientY - rect.top,
          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;
        var rect = canvas.getBoundingClientRect();
        mouse.x = e.clientX - rect.left,
          mouse.y = e.clientY - rect.top,
          e.preventDefault();
      };

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

      boundsx = canvas.width - 1;
      boundsy = canvas.height - 1;

      ctx.strokeStyle = 'rgba(222,222,222,0.6)';
      ctx.strokeStyle = 'magenta';
      cloth = new Cloth();
      update();
    };

    var Point = function(x, y) {

      this.x = x;
      this.y = y;
      this.px = x;
      this.py = y;
      this.vx = 0;
      this.vy = 0;
      this.pin_x = null;
      this.pin_y = null;
      this.constraints = [];
      //added - remember where this point was originally so we can get the right bit of the img
      this.origx = x;
      this.origy = y;
    };

    Point.prototype.update = function(delta) {

      if (mouse.down) {

        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 = [];
      }

      this.add_force(0, gravity);

      delta *= delta;
      nx = this.x   ((this.x - this.px) * .99)   ((this.vx / 2) * delta);
      ny = this.y   ((this.y - this.py) * .99)   ((this.vy / 2) * delta);

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

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

      this.vy = this.vx = 0
    };

    Point.prototype.draw = function() {

      if (this.constraints.length <= 0) return;

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

    Point.prototype.resolve_constraints = function() {

      if (this.pin_x != null && this.pin_y != null) {

        this.x = this.pin_x;
        this.y = this.pin_y;
        return;
      }

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

      this.x > boundsx ? this.x = 2 * boundsx - this.x : 1 > this.x && (this.x = 2 - this.x);
      this.y < 1 ? this.y = 2 - this.y : this.y > boundsy && (this.y = 2 * boundsy - this.y);
    };

    Point.prototype.attach = function(point) {

      this.constraints.push(
        new Constraint(this, point)
      );
    };

    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(x, y) {

      this.vx  = x;
      this.vy  = y;
    };

    Point.prototype.pin = function(pinx, piny) {
      this.pin_x = pinx;
      this.pin_y = piny;
    };

    var Constraint = function(p1, p2) {

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

    Constraint.prototype.resolve = 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 > tear_distance) this.p1.remove_constraint(this);

      var px = diff_x * diff * 0.5;
      var py = diff_y * diff * 0.5;

      this.p1.x  = px;
      this.p1.y  = py;
      this.p2.x -= px;
      this.p2.y -= py;
    };
    let num = 0;
    Constraint.prototype.draw = function() {

      ctx.drawImage(mycanvas, this.p1.origx, this.p1.origy, spacing, spacing, this.p1.x, this.p1.y, spacing   1, spacing   1);
    };

    var Cloth = function() {

      this.points = [];

      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, start_y   y * spacing);

          x != 0 && p.attach(this.points[this.points.length - 1]);
          y == 0 && p.pin(p.x, p.y);
          y != 0 && p.attach(this.points[x   (y - 1) * (cloth_width   1)])

          this.points.push(p);
        }
      }
    };

    Cloth.prototype.update = function() {

      var i = physics_accuracy;

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

      i = this.points.length;
      while (i--) this.points[i].update(.016);
    };

    Cloth.prototype.draw = function() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.beginPath();

      var i = cloth.points.length;
      while (i--) cloth.points[i].draw();

      ctx.stroke();
    };

    function update() {

      cloth.update();
      cloth.draw();

      requestAnimFrame(update);
    }
  </script>

</head>

<body>

  <canvas id="c" width="800" height="376"> </canvas>




</body>

</html>

Note: it is possible to 'tear' the material with a right click and this facility probably needs removing - unless you want users to ruin the look of the cloth :)

  • Related