Wrap images on papercup(background image)

前端 未结 1 1437
隐瞒了意图╮
隐瞒了意图╮ 2020-12-18 10:59

I want to wrap images and text on sample papercup. When a image is uploaded on canvas, I want to wrap it around the background image of papercup whose position is fixed at a

相关标签:
1条回答
  • 2020-12-18 11:27

    You can draw a user image like this:

    enter image description here

    On to this paper cup:

    enter image description here

    With results like this:

    enter image description here

    Using this example code:

    Modify this example to fit your needs. Good luck with your project!

    var faceCanvas = document.getElementById('face');
    var faceCtx = faceCanvas.getContext('2d');
    
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    var cw, ch;
    
    
    $myslider = $('#myslider');
    $myslider.val(50);
    
    var PI = Math.PI;
    var cupTop = 78;
    var cupBottom = 295;
    var dxx = 19;
    var dyy = 34;
    var l = {
      x0: 41,
      y0: cupTop,
      x1: 74,
      y1: cupBottom
    };
    var r = {
      x0: 249,
      y0: cupTop,
      x1: 218,
      y1: cupBottom
    };
    var t = {
      x0: l.x0,
      y0: l.y0,
      x1: l.x0 + dxx,
      y1: r.y0 + dyy,
      x2: r.x0 - dxx,
      y2: r.y0 + dyy,
      x3: r.x0,
      y3: r.y0
    };
    var b = {
      x0: l.x1,
      y0: l.y1,
      x1: l.x1 + dxx,
      y1: r.y1 + dyy,
      x2: r.x1 - dxx,
      y2: r.y1 + dyy,
      x3: r.x1,
      y3: r.y1
    };
    var topOffset = 40;
    
    var imgCount = 2;
    var cup = new Image();
    cup.crossOrigin = 'anonymous';
    cup.onload = start;
    var pic = new Image();
    pic.crossOrigin = 'anonymous';
    pic.onload = start;
    cup.src = 'https://image.ibb.co/iKJvyc/VENFv.png';
    pic.src = 'https://image.ibb.co/dJHG4H/Pu7aY.jpg';
    
    function start() {
      if (--imgCount > 0) {
        return;
      }
    
      cw = canvas.width = faceCanvas.width = cup.width;
      ch = canvas.height = faceCanvas.height = cup.height;
    
      draw();
    
      face();
    
      $myslider.change(function() {
        var value = parseInt($(this).val()) / 100;
        topOffset = (l.y1 - l.y0 - pic.height) * value;
        draw();
        face();
      });
    
    }
    
    
    function face() {
    
      //
      var lm = (l.y1 - l.y0) / (l.x1 - l.x0);
      var lb = l.y1 - (lm * l.x1);
      //
      var rm = (r.y1 - r.y0) / (r.x1 - r.x0);
      var rb = r.y1 - (rm * r.x1);
    
      faceCtx.clearRect(0, 0, faceCanvas.width, faceCanvas.height);
    
      for (var y = 0; y < pic.height; y++) {
    
        var yy = cupTop + topOffset + y;
        var leftX = (yy - lb) / lm;
        var rightX = (yy - rb) / rm;
        var width = rightX - leftX;
    
        faceCtx.drawImage(
          pic,
          0, y, pic.width, 1,
          leftX, yy, width, 1
        );
    
      }
    
      var yy = cupTop + topOffset;
      var p0 = {
        x: (yy - lb) / lm,
        y: cupTop + topOffset
      };
      var p3 = {
        x: (yy - rb) / rm,
        y: cupTop + topOffset
      };
      var p1 = {
        x: p0.x + dxx,
        y: p0.y + dyy
      };
      var p2 = {
        x: p3.x - dxx,
        y: p3.y + dyy
      };
      var points = calcPointsOnBezier(p0, p1, p2, p3);
    
      for (var x in points) {
        var y = points[x];
        ctx.drawImage(faceCanvas, x, 0, 1, ch, x, y - yy, 1, ch);
      }
    
    }
    
    function calcPointsOnBezier(p0, p1, p2, p3) {
    
      var points = {};
      for (var x = parseInt(p0.x); x < parseInt(p3.x + 1); x++) {
        points[x] = p0.y;
      }
    
      for (var i = 0; i < 1000; i++) {
        var t = i / 1000;
        var pt = getCubicBezierXYatT(p0, p1, p2, p3, t);
        points[parseInt(pt.x)] = parseInt(pt.y);
      }
    
      return (points);
    }
    
    function draw() {
      ctx.strokeStyle = 'gold';
      ctx.clearRect(0, 0, cw, ch);
      ctx.drawImage(cup, 0, 0);
      // diagnostic();
    }
    
    function diagnostic() {
      ctx.beginPath();
      ctx.moveTo(l.x0, l.y0);
      ctx.lineTo(l.x1, l.y1);
      ctx.moveTo(r.x0, r.y0);
      ctx.lineTo(r.x1, r.y1);
      ctx.lineWidth = 3;
      ctx.stroke();
    
      ctx.beginPath();
      ctx.moveTo(t.x0, t.y0);
      ctx.bezierCurveTo(t.x1, t.y1, t.x2, t.y2, t.x3, t.y3);
      ctx.stroke();
    
      ctx.beginPath();
      ctx.moveTo(b.x0, b.y0);
      ctx.bezierCurveTo(b.x1, b.y1, b.x2, b.y2, b.x3, b.y3);
      ctx.stroke();
    }
    
    function getCubicBezierXYatT(startPt, controlPt1, controlPt2, endPt, T) {
      var x = CubicN(T, startPt.x, controlPt1.x, controlPt2.x, endPt.x);
      var y = CubicN(T, startPt.y, controlPt1.y, controlPt2.y, endPt.y);
      return ({
        x: x,
        y: y
      });
    }
    
    // cubic helper formula at T distance
    function CubicN(T, a, b, c, d) {
      var t2 = T * T;
      var t3 = t2 * T;
      return a + (-a * 3 + T * (3 * a - a * T)) * T +
        (3 * b + T * (-6 * b + b * 3 * T)) * T +
        (c * 3 - c * 3 * T) * t2 +
        d * t3;
    }
    body {
      background-color: ivory;
    }
    
    canvas {
      border: 1px solid red;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    Vertical Position:<input id=myslider type=range min=0 max=100 value=50><br>
    <canvas id="canvas" width=300 height=300></canvas>
    <canvas id="face" width=300 height=300 hidden></canvas>

    ADDITIONAL NOTE: The example above creates the effect on an Html Canvas element

    That's done because the effect requires the context.drawImage method which is available in the native Canvas element.

    Once you create your effect using native canvas, you can easily use that native canvas as an image source to create a FabricJS Image object (fabric.Image accepts an html canvas as an image source):

    // get a reference to the html canvas with the
    // "image around mug" effect
    var canvas=document.getElementById("canvas");
    
    // create a fabric.Image using that html canvas
    // as an image source
    var c=new fabric.Canvas('c');
    var myFabricImage=new fabric.Image(canvas, {
      left: 50,
      top: 50,
    });
    c.add(myFabricImage);
    
    0 讨论(0)
提交回复
热议问题