代码之家  ›  专栏  ›  技术社区  ›  BrunoLM

如何通过动画使对象水平居中?

  •  1
  • BrunoLM  · 技术社区  · 6 年前

    我找到了方法 centerH 它把元素正确地放在中间

    const activeElement = canvas.getActiveObject()
    activeElement.centerH()
    

    但是,它不会为对象设置动画。所以我试着自己去实现它

    const activeElement = canvas.getActiveObject()
    
    const { left, top } = canvas.getCenter();
    
    const dest = {
      left: left - activeElement.width / 2,
      // top: top - activeElement.height / 2,
    }
    
    activeElement.animate(dest, {
      onChange: canvas.renderAll.bind(canvas),
      easing: fabric.util.ease['easeOutCubic'],
      duration: 500,
    })
    

    这里的问题是,当元素被缩放和/或旋转时,它不起作用。

    有简单的方法吗 创建动画 中心 是吗?

    代码:

    const fabric = window.fabric;
    
    const canvas = new fabric.Canvas('canvas', {
      background: 'silver',
      centeredRotation: true,
    })
    
    canvas.setWidth(250)
    canvas.setHeight(250)
    
    const textbox = new fabric.Textbox('hello world this is', {
      left: 5,
      top: 200,
      fontSize: 30,
      hasRotatingPoint: false,
      centeredScaling: true,
      centeredRotation: true,
      originX: 'left',
      originY: 'top',
      fixedWidth: 200,
      width: 200,
      angle: -75,
    }).scale(0.65)
    canvas.add(textbox).setActiveObject(textbox)
    
    // grid
    const gridStyle = {
      stroke: 'red',
      strokeWidth: 1,
      selectable: false,
    }
    const center = {
      h: canvas.width / 2,
      v: canvas.height / 2,
    }
    const h = new fabric.Line([ center.h, 0, center.h, canvas.height], gridStyle)
    const v = new fabric.Line([ 0, center.v, canvas.width, center.v], gridStyle)
    canvas.add(h)
    canvas.add(v)
    
    // center function
    document.getElementById('center').addEventListener('click', () => {
      const activeElement = canvas.getActiveObject()
      
      const { left, top } = canvas.getCenter()
      
      const dest = {
        left: left - activeElement.width / 2,
        // top: top - activeElement.height / 2,
      }
      
      activeElement.animate(dest, {
        onChange: canvas.renderAll.bind(canvas),
        easing: fabric.util.ease['easeOutCubic'],
        duration: 500,
      })
    }, { passive: true })
    body {
      margin: 20px;
    }
    
    canvas {
      border: 1px dashed red;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.2/fabric.min.js"></script>
    <button id="center">center element</button>
    <br/>
    <canvas id="canvas"></canvas>
    1 回复  |  直到 6 年前
        1
  •  1
  •   shkaper    6 年前

    据我所见,你的任务转化为

    将元素移动到一个位置,使其中心位于 帆布中心

    这是一个计算函数。参数 x y 是画布上点的坐标; originX originY 描述要放置在元素的哪个点 x,y .返回值是需要将其坐标设置为对象坐标的点 left , top 要有这个位置,要考虑到物体的起源。

    function getPositionByOrigin (x, y, originX, originY) {
      const point = new fabric.Point(x, y)
      const center = this.translateToCenterPoint(point, originX, originY)
      return this.translateToOriginPoint(center, this.originX, this.originY)
    }
    

    这基本上是 fabric.Object.prototype.setPositionByOrigin() 但不会立即改变对象。

    下面是一个片段:

    const fabric = window.fabric;
    
    const canvas = new fabric.Canvas('canvas', {
      background: 'silver',
      centeredRotation: true,
    })
    
    canvas.setWidth(250)
    canvas.setHeight(250)
    
    const textbox = new fabric.Textbox('hello world this is', {
      left: 5,
      top: 200,
      fontSize: 30,
      hasRotatingPoint: false,
      centeredScaling: true,
      centeredRotation: true,
      originX: 'left',
      originY: 'top',
      fixedWidth: 200,
      width: 200,
      angle: -75,
    }).scale(0.65)
    canvas.add(textbox).setActiveObject(textbox)
    
    // grid
    const gridStyle = {
      stroke: 'red',
      strokeWidth: 1,
      selectable: false,
    }
    const center = {
      h: canvas.width / 2,
      v: canvas.height / 2,
    }
    const h = new fabric.Line([ center.h, 0, center.h, canvas.height], gridStyle)
    const v = new fabric.Line([ 0, center.v, canvas.width, center.v], gridStyle)
    canvas.add(h)
    canvas.add(v)
    
    function getPositionByOrigin (x, y, originX, originY) {
      const point = new fabric.Point(x, y)
      const center = this.translateToCenterPoint(point, originX, originY)
      return this.translateToOriginPoint(center, this.originX, this.originY)
    }
    
    // center function
    document.getElementById('center').addEventListener('click', () => {
      const activeElement = canvas.getActiveObject()
      
      const { left, top } = canvas.getCenter()
      const newPosition = getPositionByOrigin.call(activeElement, left, top, 'center', 'center')
      
      const dest = {
        left: newPosition.x,
        top: newPosition.y
      }
      
      activeElement.animate(dest, {
        onChange: canvas.renderAll.bind(canvas),
        easing: fabric.util.ease['easeOutCubic'],
        duration: 500,
      })
    }, { passive: true })
    body {
      margin: 20px;
    }
    
    canvas {
      border: 1px dashed red;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.2/fabric.min.js"></script>
    <button id="center">center element</button>
    <br/>
    <canvas id="canvas"></canvas>