平滑缩放fabricjs对象

3
我正在使用fabricjs画布库。我无法找到用于fabricjs的动画方法或支持库。
我想要做的是对对象进行缩放,而不是改变对象大小。每个对象画布都将保持在其原位。
我想要添加效果,就像相机聚焦于特定对象一样进行缩放。当我们缩小时,它将回到初始状态,就像相机从对象处移动到初始状态。
到目前为止,我尝试了以下方法:

 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>  


在画布上进行缩放就像是进行比例缩放,你改变了用户的感知,使其看起来像是放大。 - Maciej Sikora
我正在做同样的事情,但进展并不像预期的那样顺利。 - Prashant Pal
你能贴一些已经尝试过的代码片段作为示例吗? - StefanHayden
@StefanHayden 感谢您的回复。我已经找到了解决方案。我将问题(http://fiddle.jshell.net/5KKQ2/811/)以及解决方案一并发布出来。 - Prashant Pal
1个回答

1

我试图在相机聚焦于特定对象时对其进行缩放,并且应该平稳过渡。但是,在使用缩放对象时,很难管理特定对象的位置,因为我们永远不知道对象在运行时会放置在哪里。

解决方案: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> 

我在使用zoomToPoint方法,它的效果很好。不需要每次缩放每个对象。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接