Wrapping an image around a cylindrical object in HTML5 / JavaScript

I want to wrap an image around a cylindrical object, like circles in a web application, like

Personalized Mug

This will most likely be a base image (for example, a jpeg image of a circle) containing a converted image of a user uploaded image.

Looks like there are a lot of resources in PhotoShop . However, this, of course, is not suitable for web applications, mobile or server environments.

I also know that this is possible, as a number of sites already do this very well. For example, Vista Print (see image), Asda Photos (and downloads more on the Internet just by browsing personalized circles on Google), using what seems like just HTML5.

, , -. StackOverflow , : , , html 5 canvas javascript, html5 !

- , , .

+4
2

enter image description here

function canvas1() {
  var canvas = document.getElementById("canvas1");
  var ctx = canvas.getContext("2d");

  var productImg = new Image();
  productImg.onload = function() {
    var iw = productImg.width;
    var ih = productImg.height;
    console.log("height");

    canvas.width = iw;
    canvas.height = ih;

    ctx.drawImage(productImg, 0, 0, productImg.width, productImg.height,
      0, 0, iw, ih);
    loadUpperIMage()
  };

  productImg.src = "http://res.cloudinary.com/pussyhunter/image/upload/c_scale,f_auto,h_350/left_handle_cup_i7ztfs.jpg"


  function loadUpperIMage() {
    var img = new Image();


    img.src = "http://res.cloudinary.com/pussyhunter/image/upload/v1488184107/500_F_97150423_M13q2FeAUZxxIx6CaPixHupprmyiVVli_skh6fe.jpg"
    img.onload = function() {

      var iw = img.width;
      var ih = img.height;

      var xOffset = 102, //left padding
        yOffset = 110; //top padding

      //alert(ih)
      var a = 75.0; //image width
      var b = 10; //round ness

      var scaleFactor = iw / (4 * a);

      // draw vertical slices
      for (var X = 0; X < iw; X += 1) {
        var y = b / a * Math.sqrt(a * a - (X - a) * (X - a)); // ellipsis equation
        ctx.drawImage(img, X * scaleFactor, 0, iw / 9, ih, X + xOffset, y + yOffset, 1, 174);
      }
    };
  }

};

function canvas2() {

  var canvas = document.getElementById("canvas2");
  var ctx = canvas.getContext("2d");

  var productImg = new Image();
  productImg.onload = function() {
    var iw = productImg.width;
    var ih = productImg.height;
    console.log("height");

    canvas.width = iw;
    canvas.height = ih;

    ctx.drawImage(productImg, 0, 0, productImg.width, productImg.height,
      0, 0, iw, ih);
    loadUpperIMage()
  };


  productImg.src = "http://res.cloudinary.com/pussyhunter/image/upload/h_350/canter_handle_cup_xyxhdd.jpg"

  function loadUpperIMage() {
    var img = new Image();

    img.src = "http://res.cloudinary.com/pussyhunter/image/upload/v1488184107/500_F_97150423_M13q2FeAUZxxIx6CaPixHupprmyiVVli_skh6fe.jpg"

    img.onload = function() {

      var iw = img.width;
      var ih = img.height;

      // alert(iw)

      var xOffset = 101, //left padding
        yOffset = 110; //top padding

      var a = 75.0; //image width
      var b = 10; //round ness

      var scaleFactor = iw / (4 * a);

      // draw vertical slices
      for (var X = 0; X < iw; X += 1) {
        var y = b / a * Math.sqrt(a * a - (X - a) * (X - a)); // ellipsis equation
        ctx.drawImage(img, X * scaleFactor, 0, iw / 3, ih, X + xOffset, y + yOffset, 1, 174);

      }
    };
  }

};

function canvas3() {

  var canvas = document.getElementById("canvas3");
  var ctx = canvas.getContext("2d");

  var productImg = new Image();
  productImg.onload = function() {
    var iw = productImg.width;
    var ih = productImg.height;

    canvas.width = iw;
    canvas.height = ih;

    ctx.drawImage(productImg, 0, 0, productImg.width, productImg.height,
      0, 0, iw, ih);
    loadUpperIMage()
  };

  productImg.src = "http://res.cloudinary.com/pussyhunter/image/upload/h_350/right_handle_cup_dsdhr7.jpg"


  function loadUpperIMage() {
    var img = new Image();

    img.src = "http://res.cloudinary.com/pussyhunter/image/upload/v1488184107/500_F_97150423_M13q2FeAUZxxIx6CaPixHupprmyiVVli_skh6fe.jpg"

    img.onload = function() {

      var iw = img.width;
      var ih = img.height;

      //alert(iw)

      var xOffset = 102, //left padding
        yOffset = 110; //top padding

      var a = 75.0; //image width
      var b = 10; //round ness

      var scaleFactor = iw / (3 * a);

      // draw vertical slices
      for (var X = 0; X < iw; X += 1) {
        var y = b / a * Math.sqrt(a * a - (X - a) * (X - a)); // ellipsis equation
        ctx.drawImage(img, X * scaleFactor, 0, iw / 1.5, ih, X + xOffset, y + yOffset, 1, 174);
      }
    };
  }

};

setTimeout(function() {
  canvas1()
}, 1000);
setTimeout(function() {
  canvas2()
}, 2000);
setTimeout(function() {
  canvas3()
}, 3000);
<!DOCTYPE html>
<html>

<head>
  <script data-require="jquery@*" data-semver="2.1.4" src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
  <link rel="stylesheet" href="style.css" />

  <script src="script.js"></script>
</head>

<body>

  <div>
    <canvas id="canvas1"></canvas>
  </div>

  <div>
    <canvas id="canvas2"></canvas>
  </div>

  <div>
    <canvas id="canvas3"></canvas>
  </div>


</body>

</html>
Hide result

:

var scaleFactor = iw / (4*a); //EDIT 4*a TO 6*a

ctx.drawImage(img, X * scaleFactor, 0, iw/3, ih, X + xOffset, y + yOffset, 1, 174); //EDIT  iw/3 TO iw/4
+6

2D

sin cos . 1 , . - , , , y sin () ( = 0 Math.PI/2 ).

, , , webGL . , . Realtime 3D webGL

var createImage=function(w,h){var i=document.createElement("canvas");i.width=w;i.height=h;i.ctx=i.getContext("2d");return i;}

var canvas = createImage(400,400);
var ctx = canvas.ctx;
document.body.appendChild(canvas)
ctx.clearRect(0,0,500,500)
var image = createImage(400,200);
image.ctx.font = "60px arial";
image.ctx.textAlign = "center";
image.ctx.fillStyle = "#7F5";
image.ctx.fillRect(0,0,image.width,image.height)
image.ctx.fillStyle = "white";
image.ctx.fillText("Wrap around",200,60)
image.ctx.fillText("Some images",200,140)


function draw(ang,tilt, perspective){
    var step = 1/(Math.max(image.width,400));
    for(var i = 0; i < 1; i += step){
        var a = i * Math.PI;
        var a1 = (i+ step*2) * Math.PI ;
        var ix = i * image.width*1.2;
        var iw = step * image.width*1.2;
        a += ang * Math.PI * 2;
        a1 += ang * Math.PI * 2;
        a = Math.PI -a;
        a1 = Math.PI -a1;
        var x = canvas.width * 0.5;
        var y = canvas.height * 0.1;
        
        var x1 = x + Math.cos(a1) * 110;
        var y1 = y + Math.sin(a) * tilt;
        x += Math.cos(a) * 110;
        y += Math.sin(a) * tilt;
        var s = Math.sin(a);
        var s1 = Math.sin(a1);
        if(s > 0 || s1 > 0){
            ctx.drawImage(image,ix,0,iw,image.height,x1,y- s * perspective*0.5,x-x1,200 + s * perspective)
        }
        
        
    }
}
var w = canvas.width;
var h = canvas.height;




// main update function
function update(timer){
    ctx.setTransform(1,0,0,1,0,0); // reset transform
    ctx.globalAlpha = 1;           // reset alpha
    ctx.fillStyle = "black"
    ctx.fillRect(0,0,w,h);
    draw(timer / 2000, 40,30)
    requestAnimationFrame(update);
}
requestAnimationFrame(update);
Hide result

.

, . , , ( ) . , , , "", "lighten"

var createImage=function(w,h){var i=document.createElement("canvas");i.width=w;i.height=h;i.ctx=i.getContext("2d");return i;}

var canvas = createImage(400,400);
var ctx = canvas.ctx;
document.body.appendChild(canvas)
ctx.clearRect(0,0,500,500)
var image = createImage(400,200);
image.ctx.font = "60px arial";
image.ctx.textAlign = "center";
image.ctx.fillStyle = "#999";
image.ctx.fillRect(0,10,image.width,image.height-20)
image.ctx.fillStyle = "white";
image.ctx.fillText("Wrap around",200,60)
image.ctx.fillText("Some images",200,140)

//---------------------------------------------------------------------
// create shading map
var shading = createImage(400,200);
// left to right shading
var g1 = shading.ctx.createLinearGradient(0,0,400,0);
g1.addColorStop(0,"rgba(245,245,245,1)");
g1.addColorStop(0.05,"rgba(255,255,255,1)");
g1.addColorStop(0.5,"rgba(230,230,230,1)");
g1.addColorStop(0.95,"rgba(255,255,255,1)");
g1.addColorStop(1,"rgba(245,245,245,1)");
shading.ctx.fillStyle = g1;
shading.ctx.fillRect(0,0,400,200);

// bottom to top shading
var g = shading.ctx.createLinearGradient(0,0,0,200);
g.addColorStop(1,"rgba(200,200,200,1)");
g.addColorStop(0.95,"rgba(200,200,200,0.4)");
g.addColorStop(0,"rgba(255,255,255,0.0)");
shading.ctx.globalCompositeOperation = "multiply";
shading.ctx.fillStyle = g;
shading.ctx.fillRect(0,0,400,200);


var g = shading.ctx.createRadialGradient(0,-100,100,0,-100,200);
g.addColorStop(0,"rgba(200,200,200,1)");
g.addColorStop(0.95,"rgba(255,255,255,1)");
g.addColorStop(1,"rgba(255,255,255,0)");
shading.ctx.fillStyle = g;
shading.ctx.globalCompositeOperation = "screen";
shading.ctx.setTransform(1.4,0,0,1,200,0);
shading.ctx.beginPath();
shading.ctx.arc(0,-100,200,0,Math.PI * 2);
shading.ctx.globalAlpha = 0.5;
shading.ctx.fill();
shading.ctx.setTransform(1,0,0,1,0,0);
shading.ctx.fillStyle = g1;
shading.ctx.fillRect(0,0,400,200);

var overlay = createImage(400,400);
draw(shading,overlay.ctx,0, 40,30,110,200,1);

function draw(image,ctx,ang,tilt, perspective, width, height,stretch){
    var step = 1/(Math.max(image.width,400));
    for(var i = 0; i < 1; i += step){
        var a = i * Math.PI;
        var a1 = (i+ step*2) * Math.PI ;
        var ix = i * image.width*stretch;
        var iw = step * image.width*stretch;
        a += ang * Math.PI * 2;
        a1 += ang * Math.PI * 2;
        a = Math.PI -a;
        a1 = Math.PI -a1;
        var x = canvas.width * 0.5;
        var y = canvas.height * 0.1;
        
        var x1 = x + Math.cos(a1) * width;
        var y1 = y + Math.sin(a) * tilt;
        x += Math.cos(a) * width;
        y += Math.sin(a) * tilt;
        var s = Math.sin(a);
        var s1 = Math.sin(a1);
        if(s > 0 || s1 > 0){
            ctx.drawImage(image,ix,0,iw,image.height,x1,y- s * perspective*0.5,(x-x1-1),height + s * perspective)
        }
        
        
    }
}
var w = canvas.width;
var h = canvas.height;

// main update function
function update1(timer){
    ctx.setTransform(1,0,0,1,0,0); // reset transform
    ctx.globalAlpha = 1;           // reset alpha
    ctx.fillStyle = "black"
    ctx.fillRect(0,0,w,h);
    ctx.drawImage(overlay,0,0);
    draw(image,ctx,timer / 4000, 40,30,110,200,1)
    ctx.globalCompositeOperation = "multiply";
    ctx.drawImage(overlay,0,0);
    ctx.globalAlpha = 0.2
    ctx.globalCompositeOperation = "lighten";
    ctx.drawImage(overlay,0,0);
    ctx.globalCompositeOperation = "source-over";
    requestAnimationFrame(update1);
}

 requestAnimationFrame(update1);
Hide result
+3

Source: https://habr.com/ru/post/1662986/


All Articles