Fabricjs 平移和缩放

     2023-03-25     88

关键词:

【中文标题】Fabricjs 平移和缩放【英文标题】:Fabricjs pan and zoom 【发布时间】:2015-08-08 14:04:10 【问题描述】:

如何使用 fabricjs 进行平移和缩放?我试过使用 zoomToPoint 和 setZoom 方法,但它们不适用于平移。一旦我开始使用不同的缩放点,我就会遇到麻烦。

$('#zoomIn').click(function()
    canvas.setZoom(canvas.getZoom() * 1.1 ) ;
) ;

$('#zoomOut').click(function()
    canvas.setZoom(canvas.getZoom() / 1.1 ) ;
) ;

$('#goRight').click(function()
    //Need to implement
) ;

$('#goLeft').click(function()
    //Need to implement
) ;

http://jsfiddle.net/hdramos/ux16013L/

【问题讨论】:

你能详细说明一下吗?我在什么方面进行调整? 【参考方案1】:

使用以下方法解决:

相对平移() 绝对平移()

[更新]

$('#goRight').click(function()
    var units = 10 ;
    var delta = new fabric.Point(units,0) ;
    canvas.relativePan(delta) ;
) ;

$('#goLeft').click(function()
    var units = 10 ;
    var delta = new fabric.Point(-units,0) ;
    canvas.relativePan(delta) ;
) ;
$('#goUp').click(function()
    var units = 10 ;
    var delta = new fabric.Point(0,-units) ;
    canvas.relativePan(delta) ;
) ;

$('#goDown').click(function()
    var units = 10 ;
    var delta = new fabric.Point(0,units) ;
    canvas.relativePan(delta) ;
);

http://jsfiddle.net/ux16013L/2/

【讨论】:

您能提供一些示例代码并更新您的 JSFiddle 吗?谢谢! 请我尝试做同样的事情! 请参阅更新。这就是我所拥有的。 假设如果您放大并向左或向右移动等然后缩小,那么您将以某个不是初始位置的位置结束!可以重置到初始位置吗?? 如何重置为实际画布?【参考方案2】:

我知道它已经被回答了,但我不得不做一个鼠标平移,所以我调整了接受答案的小提琴来这样做。我把它贴在这里给任何必须做这样的事情的人。这只是主要思想:

var panning = false;
canvas.on('mouse:up', function (e) 
    panning = false;
);

canvas.on('mouse:down', function (e) 
    panning = true;
);
canvas.on('mouse:move', function (e) 
    if (panning && e && e.e) 
        var units = 10;
        var delta = new fabric.Point(e.e.movementX, e.e.movementY);
        canvas.relativePan(delta);
    
);

这里是小提琴:http://jsfiddle.net/gncabrera/hkee5L6d/5/

【讨论】:

这似乎在 IE 中不起作用。从外观上看,e.e.movementX 和 e.e.movementY 在fabric.js 的IE 版本中不存在。快速环顾四周,发现***.com/questions/40355425/…【参考方案3】:

这是我的画布缩放(使用鼠标滚轮)和平移(使用左/上/右/下键或 shift 键 + 鼠标左下 + 鼠标移动)的解决方案。

https://jsfiddle.net/milanhlinak/7s4w0uLy/8/

<!DOCTYPE html>
<html>

<head>
    <script type="text/javascript" src="lib/jquery-3.1.1.min.js"></script>
    <script type="text/javascript" src="lib/fabric.min.js"></script>
</head>

<body>

    <canvas id="canvas" style="border: 1px solid #cccccc"></canvas>

    <script>
        var Direction = 
            LEFT: 0,
            UP: 1,
            RIGHT: 2,
            DOWN: 3
        ;

        var zoomLevel = 0;
        var zoomLevelMin = 0;
        var zoomLevelMax = 3;

        var shiftKeyDown = false;
        var mouseDownPoint = null;

        var canvas = new fabric.Canvas('canvas', 
            width: 500,
            height: 500,
            selectionKey: 'ctrlKey'
        );

        canvas.add(new fabric.Rect(
            left: 100,
            top: 100,
            width: 50,
            height: 50,
            fill: '#faa'

        ));
        canvas.add(new fabric.Rect(
            left: 300,
            top: 300,
            width: 50,
            height: 50,
            fill: '#afa'
        ));

        canvas.on('mouse:down', function (options) 
            var pointer = canvas.getPointer(options.e, true);
            mouseDownPoint = new fabric.Point(pointer.x, pointer.y);
        );
        canvas.on('mouse:up', function (options) 
            mouseDownPoint = null;
        );
        canvas.on('mouse:move', function (options) 
            if (shiftKeyDown && mouseDownPoint) 
                var pointer = canvas.getPointer(options.e, true);
                var mouseMovePoint = new fabric.Point(pointer.x, pointer.y);
                canvas.relativePan(mouseMovePoint.subtract(mouseDownPoint));
                mouseDownPoint = mouseMovePoint;
                keepPositionInBounds(canvas);
            
        );
        fabric.util.addListener(document.body, 'keydown', function (options) 
            if (options.repeat) 
                return;
            
            var key = options.which || options.keyCode; // key detection
            if (key == 16)  // handle Shift key
                canvas.defaultCursor = 'move';
                canvas.selection = false;
                shiftKeyDown = true;
             else if (key === 37)  // handle Left key
                move(Direction.LEFT);
             else if (key === 38)  // handle Up key
                move(Direction.UP);
             else if (key === 39)  // handle Right key
                move(Direction.RIGHT);
             else if (key === 40)  // handle Down key
                move(Direction.DOWN);
            
        );
        fabric.util.addListener(document.body, 'keyup', function (options) 
            var key = options.which || options.keyCode; // key detection
            if (key == 16)  // handle Shift key
                canvas.defaultCursor = 'default';
                canvas.selection = true;
                shiftKeyDown = false;
            
        );
        jQuery('.canvas-container').on('mousewheel', function (options) 
            var delta = options.originalEvent.wheelDelta;
            if (delta != 0) 
                var pointer = canvas.getPointer(options.e, true);
                var point = new fabric.Point(pointer.x, pointer.y);
                if (delta > 0) 
                    zoomIn(point);
                 else if (delta < 0) 
                    zoomOut(point);
                
            
        );

        function move(direction) 
            switch (direction) 
            case Direction.LEFT:
                canvas.relativePan(new fabric.Point(-10 * canvas.getZoom(), 0));
                break;
            case Direction.UP:
                canvas.relativePan(new fabric.Point(0, -10 * canvas.getZoom()));
                break;
            case Direction.RIGHT:
                canvas.relativePan(new fabric.Point(10 * canvas.getZoom(), 0));
                break;
            case Direction.DOWN:
                canvas.relativePan(new fabric.Point(0, 10 * canvas.getZoom()));
                break;
            
            keepPositionInBounds(canvas);
        


        function zoomIn(point) 
            if (zoomLevel < zoomLevelMax) 
                zoomLevel++;
                canvas.zoomToPoint(point, Math.pow(2, zoomLevel));
                keepPositionInBounds(canvas);
            
        

        function zoomOut(point) 
            if (zoomLevel > zoomLevelMin) 
                zoomLevel--;
                canvas.zoomToPoint(point, Math.pow(2, zoomLevel));
                keepPositionInBounds(canvas);
            
        

        function keepPositionInBounds() 
            var zoom = canvas.getZoom();
            var xMin = (2 - zoom) * canvas.getWidth() / 2;
            var xMax = zoom * canvas.getWidth() / 2;
            var yMin = (2 - zoom) * canvas.getHeight() / 2;
            var yMax = zoom * canvas.getHeight() / 2;

            var point = new fabric.Point(canvas.getWidth() / 2, canvas.getHeight() / 2);
            var center = fabric.util.transformPoint(point, canvas.viewportTransform);

            var clampedCenterX = clamp(center.x, xMin, xMax);
            var clampedCenterY = clamp(center.y, yMin, yMax);

            var diffX = clampedCenterX - center.x;
            var diffY = clampedCenterY - center.y;

            if (diffX != 0 || diffY != 0) 
                canvas.relativePan(new fabric.Point(diffX, diffY));
            
        

        function clamp(value, min, max) 
            return Math.max(min, Math.min(value, max));
        
    </script>

</body>

</html>

【讨论】:

【参考方案4】:

我在 Github 上有一个使用 fabric.js 画布平移和缩放的示例:https://sabatinomasala.github.io/fabric-clipping-demo/

负责平移行为的代码如下:https://github.com/SabatinoMasala/fabric-clipping-demo/blob/master/src/classes/Panning.js

这是fabric.Canvas.prototype 上的一个简单扩展,可让您在画布上切换“拖动模式”,如下所示:

canvas.toggleDragMode(true); // Start panning
canvas.toggleDragMode(false); // Stop panning

看看下面的 sn-p,整个代码都有文档。

const STATE_IDLE = 'idle';
const STATE_PANNING = 'panning';
fabric.Canvas.prototype.toggleDragMode = function(dragMode) 
  // Remember the previous X and Y coordinates for delta calculations
  let lastClientX;
  let lastClientY;
  // Keep track of the state
  let state = STATE_IDLE;
  // We're entering dragmode
  if (dragMode) 
    // Discard any active object
    this.discardActiveObject();
    // Set the cursor to 'move'
    this.defaultCursor = 'move';
    // Loop over all objects and disable events / selectable. We remember its value in a temp variable stored on each object
    this.forEachObject(function(object) 
      object.prevEvented = object.evented;
      object.prevSelectable = object.selectable;
      object.evented = false;
      object.selectable = false;
    );
    // Remove selection ability on the canvas
    this.selection = false;
    // When MouseUp fires, we set the state to idle
    this.on('mouse:up', function(e) 
      state = STATE_IDLE;
    );
    // When MouseDown fires, we set the state to panning
    this.on('mouse:down', (e) => 
      state = STATE_PANNING;
      lastClientX = e.e.clientX;
      lastClientY = e.e.clientY;
    );
    // When the mouse moves, and we're panning (mouse down), we continue
    this.on('mouse:move', (e) => 
      if (state === STATE_PANNING && e && e.e) 
        // let delta = new fabric.Point(e.e.movementX, e.e.movementY); // No Safari support for movementX and movementY
        // For cross-browser compatibility, I had to manually keep track of the delta

        // Calculate deltas
        let deltaX = 0;
        let deltaY = 0;
        if (lastClientX) 
          deltaX = e.e.clientX - lastClientX;
        
        if (lastClientY) 
          deltaY = e.e.clientY - lastClientY;
        
        // Update the last X and Y values
        lastClientX = e.e.clientX;
        lastClientY = e.e.clientY;

        let delta = new fabric.Point(deltaX, deltaY);
        this.relativePan(delta);
        this.trigger('moved');
      
    );
   else 
    // When we exit dragmode, we restore the previous values on all objects
    this.forEachObject(function(object) 
      object.evented = (object.prevEvented !== undefined) ? object.prevEvented : object.evented;
      object.selectable = (object.prevSelectable !== undefined) ? object.prevSelectable : object.selectable;
    );
    // Reset the cursor
    this.defaultCursor = 'default';
    // Remove the event listeners
    this.off('mouse:up');
    this.off('mouse:down');
    this.off('mouse:move');
    // Restore selection ability on the canvas
    this.selection = true;
  
;

// Create the canvas

let canvas = new fabric.Canvas('fabric')
canvas.backgroundColor = '#f1f1f1';

// Add a couple of rects

let rect = new fabric.Rect(
  width: 100,
  height: 100,
  fill: '#f00'
);
canvas.add(rect)

rect = new fabric.Rect(
  width: 200,
  height: 200,
  top: 200,
  left: 200,
  fill: '#f00'
);
canvas.add(rect)

// Handle dragmode change

let dragMode = false;
$('#dragmode').change(_ => 
  dragMode = !dragMode;
  canvas.toggleDragMode(dragMode);
);
<div>
  <label for="dragmode">
    Enable panning
    <input type="checkbox" id="dragmode" name="dragmode" />
  </label>
</div>
<canvas   id="fabric"></canvas>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.15/fabric.min.js"></script>

【讨论】:

【参考方案5】:

如果你只想在显示中平移画布,而不是改变元素的位置, 你可以使用this solution。

这个想法是有一个固定大小的容器,其 css 为overflow: hidden,里面有一个扩展的画布。平底锅将在容器内移动画布,因此用户每次都会看到已用过的画布的不同区域。

【讨论】:

canvas - 使用fabricjs和angularjs进行捏缩放

】canvas-使用fabricjs和angularjs进行捏缩放【英文标题】:canvas-pinchzoomingusingbyfabricjsandangularjs【发布时间】:2014-11-0215:05:13【问题描述】:我正在尝试使用FabricJs在画布上进行捏合缩放。但我对此一无所知。我还从谷歌搜索了一些代... 查看详情

如何修复 FabricJS 中 Inkscape SVG 的缩放和旋转?

】如何修复FabricJS中InkscapeSVG的缩放和旋转?【英文标题】:HowcanIfixtheScalingandRotatingofanInkscapeSVGinFabricJS?【发布时间】:2014-03-2307:58:03【问题描述】:我在使用FabricJS缩放和旋转SVG图像时遇到了一些问题。我一直在为我的网站开发... 查看详情

fabricjs:缩放后如何显示对象大小

】fabricjs:缩放后如何显示对象大小【英文标题】:fabricjs:howtoshowobjectsizeafterscaling【发布时间】:2015-08-2312:28:55【问题描述】:我正在使用名为“WoocommerceProductDesigner”的wordpress插件,其中包含一个1.4.9版中名为fabicjs的JavaScript库... 查看详情

如何在 QGraphicsView 中启用平移和缩放

】如何在QGraphicsView中启用平移和缩放【英文标题】:HowtoenablePanandZoominaQGraphicsView【发布时间】:2016-06-0105:27:14【问题描述】:我正在使用python和QtDesigner来实现加载tiff图像并在某些鼠标事件(滚轮-缩放,按下滚轮-平移)上启用... 查看详情

平移和缩放图像

】平移和缩放图像【英文标题】:Pan&ZoomImage【发布时间】:2010-10-1900:33:03【问题描述】:我想在WPF中创建一个简单的图像查看器,使用户能够:平移(通过鼠标拖动图像)。缩放(使用滑块)。显示叠加层(例如矩形选择)... 查看详情

矩阵的平移旋转与缩放

世界坐标中的一个点乘以一个四维矩阵,可以实现平移,旋转和缩放等等。平移就是,旋转和缩放就是(M分别是对应的旋转缩放矩阵)当中为0时,是向量,为1时,是坐标。平移,旋转,缩放,     查看详情

缩放和平移画布后鼠标坐标不匹配

】缩放和平移画布后鼠标坐标不匹配【英文标题】:Mousecoordinatesdon\'tmatchafterScalingandPanningcanvas【发布时间】:2014-09-1301:11:31【问题描述】:我对javascript和canvas非常陌生,我有一个程序可以检测椭圆路径上的动画元素。它稍后会... 查看详情

CGAffineTransform 缩放和平移 - 动画前跳转

】CGAffineTransform缩放和平移-动画前跳转【英文标题】:CGAffineTransformscaleandtranslation-jumpbeforeanimation【发布时间】:2015-01-1321:01:51【问题描述】:我正在努力解决有关CGAffineTransform缩放和平移的问题,当我在已经具有变换的视图上... 查看详情

动作脚本 2 上的平移和缩放舞台

】动作脚本2上的平移和缩放舞台【英文标题】:PanandZoomstageonActionScript2【发布时间】:2017-08-0705:16:45【问题描述】:我正在尝试在动作脚本2上创建缩放和平移选项。我想在舞台上而不是在影片剪辑上进行。我已经完成了基本的... 查看详情

放大鼠标滚轮点(使用缩放和平移)

】放大鼠标滚轮点(使用缩放和平移)【英文标题】:Zoominonamousewheelpoint(usingscaleandtranslate)【发布时间】:2018-03-2016:53:32【问题描述】:这个问题和这个问题类似:Zoominonapoint(usingscaleandtranslate)甚至这个:Imagezoomcenteredonmousepositio... 查看详情

平移和缩放的替代方案

】平移和缩放的替代方案【英文标题】:Alternativesforpanningandzooming【发布时间】:2014-09-1221:44:55【问题描述】:我有一个包含许多子视图的视图(代表数学对象——想想一个方程组,每个方程中的每个项都是一个单独的控件)。... 查看详情

图片的缩放旋转和平移

1、视图1<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"2xmlns:tools="http://schemas.android.com/tools"3android:layout_width="match_parent"4android:layout_height="match_parent"5 查看详情

带有缩放和平移功能的 Windows 窗体的 PictureBox

】带有缩放和平移功能的Windows窗体的PictureBox【英文标题】:WindowsForms\'PictureBoxwithzoomingandpanning【发布时间】:2011-02-0604:12:45【问题描述】:我的应用程序需要控制显示位图(jpg),还需要缩放和平移它们(因此,如果您按下鼠标... 查看详情

FabricJS 缩放图像以适应宽度/大小

】FabricJS缩放图像以适应宽度/大小【英文标题】:FabricJSscaleimagetofitwidth/size【发布时间】:2018-08-1802:58:31【问题描述】:如何正确缩放图像以适合容器大小?我想要一个由两个图像组成的网格,每个图像都适合提供的大小。https:... 查看详情

在 Android 中动画平移和缩放视图

】在Android中动画平移和缩放视图【英文标题】:AnimatingtranslationandscalingofviewinAndroid【发布时间】:2010-04-1114:16:19【问题描述】:我必须通过更改视图的比例、位置和滚动来将视图从状态A变为B。以下代码几乎可以解决问题:Animat... 查看详情

缩放和平移 HTML5 画布 - 库

】缩放和平移HTML5画布-库【英文标题】:ZoomandpanHTML5canvas-library【发布时间】:2014-09-1410:49:10【问题描述】:我正在尝试实现缩放和平移包含图片的画布。我找到了这个例子http://phrogz.net/tmp/canvas_zoom_to_cursor.html,但是转换是应用... 查看详情

UIImageView:如何在平移和缩放后仅捕获可见内容

】UIImageView:如何在平移和缩放后仅捕获可见内容【英文标题】:UIImageView:HowtocapturejustvisiblecontentafterPan&Zoom【发布时间】:2020-09-2115:49:43【问题描述】:我有一个UIImageView,它由ImagePicker加载,照片(3kx4k大小)使用AspectFit模... 查看详情

JavaFx 缩放和平移覆盖固定比例标签的图像

】JavaFx缩放和平移覆盖固定比例标签的图像【英文标题】:JavaFxzoomingandpanninganimagewithoverlaidfixedscalelabels【发布时间】:2021-11-1021:04:07【问题描述】:我是一所大学的医生,我正在开发X射线分析软件,在该软件中,用户通过将小... 查看详情