Wrap images on papercup(background image)

2019-01-19 07:33发布

问题:

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 all times. I am using Fabric JS for the html5 canvas tool. Here is my code but there it only shows 1pixel of image, also when I click the image to drag and drop ,it VANISHES.

HTML:

<div id="container">
    <input type="file" id="imageLoader" name="imageLoader" />
    Remove:<input type="button" value="remove" id="imageRemove" name="imageRemove" onClick="handleRemove()"/>
    <canvas id="canvas" width="500" height="400" style="width:1000px;height:500px;margin-left:5%;" ></canvas>


</div>

JS:

var offsetY=[0,1,2,3,4,5,6,5,4,3,2,1,0];

var canvas = new fabric.Canvas('canvas', {
    backgroundColor: 'rgb(240,240,240)'
});



var imageLoader = document.getElementById('imageLoader');
imageLoader.addEventListener('change', handleImage, false);

function handleImage(e) {
  var reader = new FileReader();
  reader.onload = function (event) {
    var image = new Image();
    image.onload = function () {
        var width = image.width,
            height = image.height;
        var context = $("canvas")[0].getContext("2d");
        for(var x=0;x<offsetY.length;x++){
            context.drawImage(image,
                x,0,1,image.height,
                x,offsetY[x],1,image.height);           
        }

    };
    image.src = event.target.result;
}
reader.readAsDataURL(e.target.files[0]);
}

function handleRemove() {
canvas.clear().renderAll();
}

I am new at html5 canvas,please help.

http://jsfiddle.net/kNEaX/217/

回答1:

You can draw a user image like this:

On to this paper cup:

With results like this:

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);