Fabric.js.Grayout Grayout图像的其他部分,而不是选定的部分。

问题描述 投票:1回答:1

在下面的图片中,我在画布上有三个盒子,在图片的底部有三个按钮。每当我点击一个按钮,画布中相应的对象就会被选中(即当我点击绿色按钮时,画布中的绿色矩形就会被选中)。

我的要求是只高亮选中的部分,而画布的其他部分应该是灰色的。(例如:如果我点击绿色按钮,绿色的矩形应该被选中,而其他部分应该叠加一个灰色的背景)。

Js Fiddle链接。https:/jsfiddle.netrnvs2hdk1

var canvas = new fabric.Canvas('c');
canvas.backgroundColor = 'yellow';
var li= []

canvas.renderAll();

fabric.Image.fromURL('http://fabricjs.com/assets/pug_small.jpg', function(myImg) {
 var img1 = myImg.set({ left: 0, top: 0 ,width:400,height:500});
 canvas.add(img1); 
 var green = new fabric.Rect({
       left: 50,
       top: 50,
       width: 50,
       height: 50,
       fill: 'rgba(255,255,255,1)',
       stroke: 'rgba(34,177,76,1)',
       strokeWidth: 5,
       name:"green"
  });
  var yellow = new fabric.Rect({
       left: 150,
       top: 50,
       width: 50,
       height: 50,
       fill: 'rgba(255,255,255,1)',
       stroke: 'rgba(255,255,0,1)',
       strokeWidth: 5,
       name:"yellow"
  });
  var red = new fabric.Rect({
       left: 250,
       top: 50,
       width: 50,
       height: 50,
       fill: 'rgba(255,255,255,1)',
       stroke: 'rgba(255,0,0,1)',
       strokeWidth: 5,
       name:"red"
  });
   canvas.add(green, yellow,red);
   li.push(green);
   li.push(yellow);
   li.push(red);
   li.some(v=>{
     var btn = document.createElement("BUTTON");   // Create a <button> elem
         btn.innerHTML = v.name;     
     btn.addEventListener('click',function(e){
        var name = e.target
      if(name.innerText == "green"){
        canvas.setActiveObject(li[0]);
      }
      if(name.innerText == "yellow"){
        canvas.setActiveObject(li[1]);
      }
      if(name.innerText == "red"){
        canvas.setActiveObject(li[2]);
      }
     });// Insert text
            document.body.appendChild(btn);  
   });
   console.log(li);
});


enter image description here

预期结果:(例)enter image description here

javascript fabricjs
1个回答
1
投票

这是我的解决方案。使用 after:render 事件,您可以在每一帧渲染后对其执行画布绘制操作。这种方法的好处是避免了根据需要创建和销毁织物对象,而这是一个昂贵的操作。

请确保调用 .setCoords() 方法,以便对象在执行这些操作时更新其位置信息。

var canvas = new fabric.Canvas('c');
canvas.backgroundColor = 'yellow';
var li = [];

canvas.renderAll();

fabric.Image.fromURL('http://fabricjs.com/assets/pug_small.jpg', function(myImg) {
  var img1 = myImg.set({
    left: 0,
    top: 0,
    width: 400,
    height: 500
  });
  canvas.add(img1);
  var green = new fabric.Rect({
    left: 50,
    top: 50,
    width: 50,
    height: 50,
    fill: 'rgba(255,255,255,1)',
    stroke: 'rgba(34,177,76,1)',
    strokeWidth: 5,
    name: "green",
    hasRotatingPoint: false
  });
  var yellow = new fabric.Rect({
    left: 150,
    top: 50,
    width: 50,
    height: 50,
    fill: 'rgba(255,255,255,1)',
    stroke: 'rgba(255,255,0,1)',
    strokeWidth: 5,
    name: "yellow",
    hasRotatingPoint: false
  });
  var red = new fabric.Rect({
    left: 250,
    top: 50,
    width: 50,
    height: 50,
    fill: 'rgba(255,255,255,1)',
    stroke: 'rgba(255,0,0,1)',
    strokeWidth: 5,
    name: "red",
    hasRotatingPoint: false
  });
  canvas.add(green, yellow, red);
  li.push(green);
  li.push(yellow);
  li.push(red);
  li.some(v => {
    var btn = document.createElement("BUTTON"); // Create a <button> elem
    btn.innerHTML = v.name;
    btn.addEventListener('click', function(e) {
      var name = e.target
      if (name.innerText == "green") {
        canvas.setActiveObject(li[0]);
      }
      if (name.innerText == "yellow") {
        canvas.setActiveObject(li[1]);
      }
      if (name.innerText == "red") {
        canvas.setActiveObject(li[2]);
      }
    }); // Insert text
    document.body.appendChild(btn);
  });
  console.log(li);
});

canvas.on({
  'object:moving': function(e) {
    //makes objects update their coordinates while being moved
    e.target.setCoords();
  },
  'object:scaling': function(e) {
    //makes objects update their coordinates while being scaled
    e.target.setCoords();
  }
});

//the after:render event allows you to perform a draw function on each frame after it is rendered
canvas.on('after:render', function() {

  var ctx = canvas.contextContainer,
    obj = canvas.getActiveObject();

  if (obj) {
    //set the fill color of the overlay
    ctx.fillStyle = "rgba(0, 0, 0, 0.3)";
    var bound = obj.getBoundingRect();
    ctx.beginPath();
    //draw rectangle to the left of the selection
    ctx.rect(0, 0, bound.left, canvas.height);
    //draw rectangle to the right of the selection
    ctx.rect(bound.left + bound.width, 0, canvas.width - bound.left - bound.width, canvas.height);
    //draw rectangle above the selection
    ctx.rect(bound.left, 0, bound.width, bound.top);
    //draw rectangle below the selection
    ctx.rect(bound.left, bound.top + bound.height, bound.width, canvas.height - bound.top - bound.height)
    ctx.fill();
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<canvas id="c" width="400" height="400"></canvas>
<div id="bt"></div>

1
投票

我在实际的矩形周围又创建了4个矩形。我已经把外部的矩形涂成灰色,这样就有了叠加的效果。另外,在创建新的矩形之前,我将删除所有的矩形。

let blankColor = "rgba(0,0,0,0)";
let grayOut = "rgba(0,0,0,0.4)";
let rect = createRect(x, y, width, height, 1, blankColor);
let rect1 = createRect(0, 0, getViewPortDimensions()[0], y, 0, grayOut);
let rect2 = createRect(0, y + height, getViewPortDimensions()[0], getViewPortDimensions()[1] - (y + height), 0, grayOut);
let rect3 = createRect(0, y, x, height, 0, grayOut);
let rect4 = createRect(x + width, y, getViewPortDimensions()[0] - (x + width), height, 0, grayOut);
state.canvas.add(rect, rect1, rect2, rect3, rect4);

删除已经画好的矩形。

state.canvas.forEachObject((o, index) => {
  if (index != 0) {
    state.canvas.remove(o);
  }
})
© www.soinside.com 2019 - 2024. All rights reserved.