3

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/

  • There are several initial errors here: you are using CSS to set canvas size (use width and height directly, and only), you drawImage the image using destination width of 1 pixel (which explains why the image is 1 pixel in width), and using canvas directly won't update fabric's internals (you should use a fabric method instead) which is why the canvas gets blank when you interact with fabric. –  Dec 03 '14 at 17:23
  • Could you please help me with the code of drawImage.I want to achieve something like this - http://stackoverflow.com/questions/26403646/fabric-js-html-5-image-curving-options – user3752437 Dec 04 '14 at 00:48

1 Answers1

9

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);
Val
  • 65
  • 2
  • 12
markE
  • 102,905
  • 11
  • 164
  • 176
  • Thanks markE. This will help a lot.However Is it possible using fabric method instead?Drag drop,resize and rotate is not allowed in this method. – user3752437 Dec 05 '14 at 11:11
  • After you've created the effect using an html canvas, you can create a fabric.Image using that html canvas as an image source. I've added example code to do that in my answer. Cheers! – markE Dec 05 '14 at 16:23
  • Awesome.I guess this will do :) – user3752437 Dec 05 '14 at 18:00
  • @markE can I ask why you use the drawImage function that clips the image instead of just setting the width and height? I'm trying to implement this for a very similar project but it's making my image that goes over the object (in this case cup) look really skewered. Thanks in advance for responding. – MCsuchNsuch Sep 30 '18 at 23:22
  • This is good as static image but how to make it 3d rotating animation. – rohit jaiswal Jan 12 '20 at 16:13