Prashant Pal
Prashant Pal

Reputation: 61

Zoom at fabricjs object smoothly

I am working with fabricjs canvas library. I am unable to find animation methods or supporting library for fabricjs.

What I want to do is to zoom at object. I don't want to scale the object size. Each object canvas will in place where it is.

What I want to do is to add effect like camera is focusing on a particular object as zooming in. and when we zoom out. It will come in initial state like camera is moving in at object and then moving out from object to initial state.

Here is what I have tried so far:

 var jsonData = {"objects":[{"type":"textbox","originX":"left","originY":"top","left":279.36,"top":102.23,"width":153,"height":29.83,"fill":"#333","stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":1.01,"scaleY":1.01,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"id":1474621288211,"hasControls":false,"objType":"text","attr":"{}","borderColor":"rgba(102,153,255,0.75)","cornerColor":"rgba(102,153,255,0.5)","borderScaleFactor":1,"editable":false,"selectable":true,"text":"First","fontSize":24,"fontWeight":"normal","fontFamily":"Lato","fontStyle":"","lineHeight":1.1,"textDecoration":"","textAlign":"left","textBackgroundColor":"","styles":{},"minWidth":20},
 {"type":"textbox","originX":"left","originY":"top","left":100.36,"top":160.23,"width":153,"height":29.83,"fill":"#333","stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":1.01,"scaleY":1.01,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"id":1474621288211,"hasControls":false,"objType":"text","attr":"{}","borderColor":"rgba(102,153,255,0.75)","cornerColor":"rgba(102,153,255,0.5)","borderScaleFactor":1,"editable":false,"selectable":true,"text":"Second","fontSize":24,"fontWeight":"normal","fontFamily":"Lato","fontStyle":"","lineHeight":1.1,"textDecoration":"","textAlign":"left","textBackgroundColor":"","styles":{},"minWidth":20},
 {"type":"textbox","originX":"left","originY":"top","left":10.36,"top":10.23,"width":153,"height":29.83,"fill":"#333","stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":1.01,"scaleY":1.01,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"id":1474621288211,"hasControls":false,"objType":"text","attr":"{}","borderColor":"rgba(102,153,255,0.75)","cornerColor":"rgba(102,153,255,0.5)","borderScaleFactor":1,"editable":false,"selectable":true,"text":"Third","fontSize":24,"fontWeight":"normal","fontFamily":"Lato","fontStyle":"","lineHeight":1.1,"textDecoration":"","textAlign":"left","textBackgroundColor":"","styles":{},"minWidth":20}
 ],"background":""};

        var canvas = new fabric.Canvas('c');
        canvas.loadFromJSON(jsonData, canvas.renderAll.bind(canvas), function(o, object) {
            fabric.log(o, object);
        });

        canvas.on('mouse:down', function(e) {
          console.log(e);
        })
        var canvasScale = 1;
        var SCALE_FACTOR = 1.5;
        var opt = {
          zoomIn : function(zObj){ 
            setTimeout(function(){
              canvas.forEachObject(function(obj){
               
                obj.animate('scaleX', obj.scaleX*SCALE_FACTOR, {duration:3000, onChange: canvas.renderAll.bind(canvas) });
                obj.animate('scaleY', obj.scaleY*SCALE_FACTOR, {duration:3000, onChange: canvas.renderAll.bind(canvas) });
                obj.animate('left', obj.left*SCALE_FACTOR, {duration:3000, onChange: canvas.renderAll.bind(canvas) });
                obj.animate('top', obj.top*SCALE_FACTOR, {duration:3000, onChange: canvas.renderAll.bind(canvas) });
              });
            },1000);
          },
          zoomOut : function(){ 
            setTimeout(function(){
              canvas.forEachObject(function(obj){
                obj.animate('scaleX', '1', {duration:3000, onChange: canvas.renderAll.bind(canvas) });
                obj.animate('scaleY', '1', {duration:3000, onChange: canvas.renderAll.bind(canvas) });
                obj.animate('left', '-=120', {duration:3000, onChange: canvas.renderAll.bind(canvas) });
                obj.animate('left', '-=120', {duration:3000, onChange: canvas.renderAll.bind(canvas) });
              });
            },1000);
          }
        } 

        opt.zoomIn(jsonData.objects[0]);
        setTimeout(function(){
          // opt.zoomOut();

        },10000);
        
        
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.4.0/fabric.js" integrity="sha256-JYw55W/ryDNiuvQUTPU0zXflTPF/HDlrIXv8+kfP5fM=" crossorigin="anonymous"></script>

<canvas id="c" width="450" height="250" style="width:800px; height:400px; border:2px solid black;"></canvas>  

Upvotes: 3

Views: 2629

Answers (1)

Prashant Pal
Prashant Pal

Reputation: 61

Here I was trying to zoom on particular object as camera is focusing on a particular object and it should go smoothly. But while using scaling the object it tough to manage the position for particular object because we never know where object will place at run time.

Solution: https://jsfiddle.net/cw9k31vy/

 var jsonData = {"objects":[{"type":"textbox","originX":"left","originY":"top","left":279.36,"top":102.23,"width":153,"height":29.83,"fill":"#333","stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":1.01,"scaleY":1.01,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"id":1474621288211,"hasControls":false,"objType":"text","attr":"{}","borderColor":"rgba(102,153,255,0.75)","cornerColor":"rgba(102,153,255,0.5)","borderScaleFactor":1,"editable":false,"selectable":true,"text":"First","fontSize":24,"fontWeight":"normal","fontFamily":"Lato","fontStyle":"","lineHeight":1.1,"textDecoration":"","textAlign":"left","textBackgroundColor":"","styles":{},"minWidth":20},
 {"type":"textbox","originX":"left","originY":"top","left":100.36,"top":160.23,"width":153,"height":29.83,"fill":"#333","stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":1.01,"scaleY":1.01,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"id":1474621288211,"hasControls":false,"objType":"text","attr":"{}","borderColor":"rgba(102,153,255,0.75)","cornerColor":"rgba(102,153,255,0.5)","borderScaleFactor":1,"editable":false,"selectable":true,"text":"Second","fontSize":24,"fontWeight":"normal","fontFamily":"Lato","fontStyle":"","lineHeight":1.1,"textDecoration":"","textAlign":"left","textBackgroundColor":"","styles":{},"minWidth":20},
 {"type":"textbox","originX":"left","originY":"top","left":10.36,"top":10.23,"width":153,"height":29.83,"fill":"#333","stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":1.01,"scaleY":1.01,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"id":1474621288211,"hasControls":false,"objType":"text","attr":"{}","borderColor":"rgba(102,153,255,0.75)","cornerColor":"rgba(102,153,255,0.5)","borderScaleFactor":1,"editable":false,"selectable":true,"text":"Third","fontSize":24,"fontWeight":"normal","fontFamily":"Lato","fontStyle":"","lineHeight":1.1,"textDecoration":"","textAlign":"left","textBackgroundColor":"","styles":{},"minWidth":20}
 ],"background":""};

var canvas = new fabric.Canvas('c');
canvas.loadFromJSON(jsonData, canvas.renderAll.bind(canvas), function(o, object) {
	fabric.log(o, object);
});

canvas.on('mouse:down', function(e) {
  console.log(e);
})
var canvasScale = 1;
var SCALE_FACTOR = 1.5;
 var opt = {
  zoomIn : function(zObj){ 
	setTimeout(function(){
	  var posX = zObj.left+(zObj.width/2);
	  var posY = zObj.top+(zObj.height/2);
	  
	  var zoomCenter = new fabric.Point(posX,posY);
	  var zoomValue = canvas.getZoom() + 0.002;
	  if(zoomValue<1.5){
		canvas.zoomToPoint(zoomCenter, zoomValue);
		canvas.renderAll.bind(canvas)

		opt.zoomIn(zObj)
	  }
	},20);
  },
  zoomOut : function(zObj){ 
	setTimeout(function(){
	  canvas.forEachObject(function(obj){
		var posX = zObj.left+(zObj.width/2);
		var posY = zObj.top+(zObj.height/2);
		
		var zoomCenter = new fabric.Point(posX,posY);
		var zoomValue = canvas.getZoom() -0.002;
		if(zoomValue>1){
		  canvas.zoomToPoint(zoomCenter, zoomValue);
		  canvas.renderAll.bind(canvas)
		  opt.zoomOut(zObj)
		}
	  });
	},20);
  }
} 

opt.zoomIn(jsonData.objects[1]);
setTimeout(function(){
  opt.zoomOut(jsonData.objects[1]);

},10000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.4.0/fabric.min.js" integrity="sha256-42MK8ODIRAEkCECsfaZOXb2psvEjAD0vK3AL3eNe86w=" crossorigin="anonymous"></script>

<canvas id="c" width="450" height="250" style="width:800px; height:400px; border:2px solid black;"></canvas> 

Here I am using zoomToPoint method which is working fine. No need to scale each object every time.

Upvotes: 1

Related Questions