首页 > 解决方案 > 出血区域适用于通过鼠标拖动移动的对象,但不适用于键盘的箭头键

问题描述

我有 2 个 FabricJS 画布和一些键盘移动功能。我可以在 2 个画布周围添加和拖动文本并且受到限制(根据需要)。但是,如果我选择一个对象并用我的箭头键移动它,它就不会绑定到“出血区域”。如何将限制应用于键盘移动?

var activeCanvas, front, back, canvas1, canvas2;
$(document).ready(function() {

  canvas1 = new fabric.Canvas('front');
  canvas2 = new fabric.Canvas('back');
  canvas1.setHeight(360);
  canvas1.setWidth(208);
  canvas2.setHeight(360);
  canvas2.setWidth(208);
  changeView(1);

  var padding = 20;
  canvas1.on('object:moving', onObjectMoving);
  canvas2.on('object:moving', onObjectMoving);

  function onObjectMoving(e) {
    var obj = e.target;

    // if object is too big ignore
    if (obj.currentHeight > obj.canvas.height - padding * 2 ||
      obj.currentWidth > obj.canvas.width - padding * 2) {
      return;
    }
    obj.setCoords();

    // top-left corner
    if (obj.getBoundingRect().top < padding ||
      obj.getBoundingRect().left < padding) {
      obj.top = Math.max(obj.top, obj.top - obj.getBoundingRect().top + padding);
      obj.left = Math.max(obj.left, obj.left - obj.getBoundingRect().left + padding);
    }

    // bot-right corner
    if (obj.getBoundingRect().top + obj.getBoundingRect().height > obj.canvas.height - padding ||
      obj.getBoundingRect().left + obj.getBoundingRect().width > obj.canvas.width - padding) {
      obj.top = Math.min(
        obj.top,
        obj.canvas.height - obj.getBoundingRect().height + obj.top - obj.getBoundingRect().top - padding);
      obj.left = Math.min(
        obj.left,
        obj.canvas.width - obj.getBoundingRect().width + obj.left - obj.getBoundingRect().left - padding);
    }
  };
});

function changeView(value) {
  if (value == 1) {
    activeCanvas = canvas1;
    $('#front').parent().css('display', 'block');
    $('#back').parent().css('display', 'none');
  }

  if (value == 2) {
    activeCanvas = canvas2;
    $('#front').parent().css('display', 'none');
    $('#back').parent().css('display', 'block');
  }
}

function dropText() {
  var text = new fabric.Text('test');
  activeCanvas.add(text);
}

// Keyboard Movement
const STEP = 1;

var Direction = {
  LEFT: 0,
  UP: 1,
  RIGHT: 2,
  DOWN: 3
};

fabric.util.addListener(document.body, 'keydown', function(options) {
  if (options.repeat) {
    return;
  }
  var key = options.which || options.keyCode; // key detection
  if (key === 37) { // handle Left key
    moveSelected(Direction.LEFT);
  } else if (key === 38) { // handle Up key
    moveSelected(Direction.UP);
  } else if (key === 39) { // handle Right key
    moveSelected(Direction.RIGHT);
  } else if (key === 40) { // handle Down key
    moveSelected(Direction.DOWN);
  }
});

function moveSelected(direction) {

  var activeObject = activeCanvas.getActiveObject();
  var activeGroup = activeCanvas.getActiveGroup();

  if (activeObject) {
    switch (direction) {
      case Direction.LEFT:
        activeObject.setLeft(activeObject.getLeft() - STEP);
        break;
      case Direction.UP:
        activeObject.setTop(activeObject.getTop() - STEP);
        break;
      case Direction.RIGHT:
        activeObject.setLeft(activeObject.getLeft() + STEP);
        break;
      case Direction.DOWN:
        activeObject.setTop(activeObject.getTop() + STEP);
        break;
    }
    activeObject.setCoords();
    activeCanvas.renderAll();
    console.log('selected objects was moved');
  } else if (activeGroup) {
    switch (direction) {
      case Direction.LEFT:
        activeGroup.setLeft(activeGroup.getLeft() - STEP);
        break;
      case Direction.UP:
        activeGroup.setTop(activeGroup.getTop() - STEP);
        break;
      case Direction.RIGHT:
        activeGroup.setLeft(activeGroup.getLeft() + STEP);
        break;
      case Direction.DOWN:
        activeGroup.setTop(activeGroup.getTop() + STEP);
        break;
    }
    activeGroup.setCoords();
    activeCanvas.renderAll();
    console.log('selected group was moved');
  } else {
    console.log('no object selected');
  }
}
canvas {
  border: 1px solid #dddddd;
  margin-top: 10px;
  border-radius: 3px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.20/fabric.min.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
<button onclick="changeView(1);">Front</button>
<button onclick="changeView(2);">Back</button>
<button onclick="dropText();">Add Text</button>

<div style="text-align: center">
  <canvas id="front"></canvas>
  <canvas id="back"></canvas>
</div>

标签: javascripthtmlcssfabricjs

解决方案


您需要object:moving手动触发事件。

activeCanvas.trigger('object:moving', {
    target: activeObject
})

查看演示(也在jsFiddle上):

var activeCanvas, front, back, canvas1, canvas2;
$(document).ready(function() {

  canvas1 = new fabric.Canvas('front');
  canvas2 = new fabric.Canvas('back');
  canvas1.setHeight(360);
  canvas1.setWidth(208);
  canvas2.setHeight(360);
  canvas2.setWidth(208);
  changeView(1);

  var padding = 20;
  canvas1.on('object:moving', onObjectMoving);
  canvas2.on('object:moving', onObjectMoving);

  function onObjectMoving(e) {
    var obj = e.target;

    // if object is too big ignore
    if (obj.currentHeight > obj.canvas.height - padding * 2 ||
      obj.currentWidth > obj.canvas.width - padding * 2) {
      return;
    }
    obj.setCoords();

    // top-left corner
    if (obj.getBoundingRect().top < padding ||
      obj.getBoundingRect().left < padding) {
      obj.top = Math.max(obj.top, obj.top - obj.getBoundingRect().top + padding);
      obj.left = Math.max(obj.left, obj.left - obj.getBoundingRect().left + padding);
    }

    // bot-right corner
    if (obj.getBoundingRect().top + obj.getBoundingRect().height > obj.canvas.height - padding ||
      obj.getBoundingRect().left + obj.getBoundingRect().width > obj.canvas.width - padding) {
      obj.top = Math.min(
        obj.top,
        obj.canvas.height - obj.getBoundingRect().height + obj.top - obj.getBoundingRect().top - padding);
      obj.left = Math.min(
        obj.left,
        obj.canvas.width - obj.getBoundingRect().width + obj.left - obj.getBoundingRect().left - padding);
    }
  };
});

function changeView(value) {
  if (value == 1) {
    activeCanvas = canvas1;
    $('#front').parent().css('display', 'block');
    $('#back').parent().css('display', 'none');
  }

  if (value == 2) {
    activeCanvas = canvas2;
    $('#front').parent().css('display', 'none');
    $('#back').parent().css('display', 'block');
  }
}

function dropText() {
  var text = new fabric.Text('test');
  activeCanvas.add(text);
}

// Keyboard Movement
const STEP = 1;

var Direction = {
  LEFT: 0,
  UP: 1,
  RIGHT: 2,
  DOWN: 3
};

fabric.util.addListener(document.body, 'keydown', function(options) {
  if (options.repeat) {
    return;
  }
  var key = options.which || options.keyCode; // key detection
  if (key === 37) { // handle Left key
    moveSelected(Direction.LEFT);
  } else if (key === 38) { // handle Up key
    moveSelected(Direction.UP);
  } else if (key === 39) { // handle Right key
    moveSelected(Direction.RIGHT);
  } else if (key === 40) { // handle Down key
    moveSelected(Direction.DOWN);
  }
});

function moveSelected(direction) {

  var activeObject = activeCanvas.getActiveObject();
  var activeGroup = activeCanvas.getActiveGroup();

  if (activeObject) {
    switch (direction) {
      case Direction.LEFT:
        activeObject.setLeft(activeObject.getLeft() - STEP);
        break;
      case Direction.UP:
        activeObject.setTop(activeObject.getTop() - STEP);
        break;
      case Direction.RIGHT:
        activeObject.setLeft(activeObject.getLeft() + STEP);
        break;
      case Direction.DOWN:
        activeObject.setTop(activeObject.getTop() + STEP);
        break;
    }
    activeObject.setCoords();
    activeCanvas.trigger('object:moving', {
    	target: activeObject
    })
    activeCanvas.renderAll();
    console.log('selected objects was moved');
  } else if (activeGroup) {
    switch (direction) {
      case Direction.LEFT:
        activeGroup.setLeft(activeGroup.getLeft() - STEP);
        break;
      case Direction.UP:
        activeGroup.setTop(activeGroup.getTop() - STEP);
        break;
      case Direction.RIGHT:
        activeGroup.setLeft(activeGroup.getLeft() + STEP);
        break;
      case Direction.DOWN:
        activeGroup.setTop(activeGroup.getTop() + STEP);
        break;
    }
    activeGroup.setCoords();
    activeCanvas.trigger('object:moving', {
    	target: activeGroup
    })
    activeCanvas.renderAll();
    console.log('selected group was moved');
  } else {
    console.log('no object selected');
  }
}
canvas {
  border: 1px solid #dddddd;
  margin-top: 10px;
  border-radius: 3px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.20/fabric.min.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
<button onclick="changeView(1);">Front</button>
<button onclick="changeView(2);">Back</button>
<button onclick="dropText();">Add Text</button>

<div style="text-align: center">
  <canvas id="front"></canvas>
  <canvas id="back"></canvas>
</div>


推荐阅读