Basi c Fabri c. js Выбор изображения с маской - PullRequest
1 голос
/ 16 апреля 2020

У меня есть уникальная (но, надеюсь, простая) проблема, которую нужно исправить с помощью Fabri c. js, чтобы исправить.

У меня есть очень простой пример ниже: enter image description here

У меня есть

  • 2 изображения
  • Оба имеют маску absolutePositioned через свойство clipPath в экземпляре fabric.Image экземпляр

Моя проблема: Я хочу, чтобы изображение можно было выбирать (и отображать) только всякий раз, когда выбор происходит в пределах маски, а не где-либо на изображении (даже за пределами его маски).

На этом изображении показана мышь, нависающая над изображением красной двери (даже если мышь находится за пределами маски, но не за пределами изображения: enter image description here

Вот фрагмент кода фрагмента изображения двери:

fabric.Image.fromURL(url1, function(img){
  canvas.add(img.set({
    left: 0,
    top: 0,
    clipPath: rect1,
    hasControls: false,
  }));
  img.on('mouseover', () => {
    const filter = new fabric.Image.filters.BlendColor({
      color: 'white',
      alpha: 0.7,
      mode: 'tint'
    })
    img.filters.push(filter)
    img.applyFilters()
    canvas.renderAll()
  })
  img.on('mouseout', () => {
    img.filters.pop()
    img.applyFilters()
    canvas.renderAll()
  })
}, {crossOrigin: "Anonymous"});

JS Пример скрипты , показывающий текущее поведение, которое я пытаюсь выполнить изменить.

1 Ответ

0 голосов
/ 17 апреля 2020

Возможным решением является прослушивание события мыши на холсте и переключение activeObject в зависимости от положения мыши:

canvas.observe('mouse:move', function(options) {
  const pos = canvas.getPointer(options.e);
  if (!imageRight || !imageLeft) return
  if (pos.x > 200) {
    activeImage = imageRight
  } else {
    activeImage = imageLeft
  }
  const activeObj = canvas.getActiveObject();
  if (activeImage !== activeObj) {
    canvas.setActiveObject(activeImage);
    canvas.renderAll()
  }
});

Это очень упрощенный способ обнаружения, если мышь находится над изображение. Он проверяет, является ли x > 200, поскольку именно там расположена линия между обоими изображениями. Это может быть улучшено, чтобы быть более точным, но это работает только для иллюстрации идеи.

var canvas = window._canvas = new fabric.Canvas('c');

const url1 = 'https://picsum.photos/300/200'
const url2 = 'https://picsum.photos/320'

let imageRight
let imageLeft
let activeImage

canvas.observe('mouse:move', function(options) {
  const pos = canvas.getPointer(options.e);
  if (!imageRight || !imageLeft) return
  if (pos.x > 200) {
    activeImage = imageRight
  } else {
    activeImage = imageLeft
  }
  const activeObj = canvas.getActiveObject();
  if (activeImage !== activeObj) {
    canvas.setActiveObject(activeImage);
    canvas.renderAll()
  }
});

const baseProps = {
  width: 200,
  height: 200,
  top: 0,
  fill: '#000',
  absolutePositioned: true,
  hasControls: false,
  evented: false,
  selectable: false
}

const rect1 = new fabric.Rect({
  ...baseProps,
  left: 0,
})

const rect2 = new fabric.Rect({
  ...baseProps,
  left: 200,
})

canvas.add(rect1)
canvas.add(rect2)

fabric.Image.fromURL(url2, function(img) {
  imageRight = img
  canvas.add(img.set({
    left: 200,
    top: 0,
    clipPath: rect2,
    hasControls: false
  }))
}, {
  crossOrigin: "Anonymouse"
})

fabric.Image.fromURL(url1, function(img) {
  imageLeft = img
  canvas.add(img.set({
    left: 0,
    top: 0,
    clipPath: rect1,
    hasControls: false,
  }));
}, {
  crossOrigin: "Anonymous"
});
canvas {
  border: 2px red solid;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.6.0/fabric.min.js"></script>
<canvas id="c" width="420" height="220"></canvas>
...