Search code examples
javascripthtmlcssfabricjs

Render select object only while scaling or zoom?


I have a canvas, I add a rectangle to the canvas. Each rectangle has a unique ID and I am processing accordingly. When I want to change the color of the rectangle I choose, it does not render directly. It has an effect when I increase or decrease the size or zoom.

How do I get it to act directly? I guess there is a problem in rendering.

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

canvas.setBackgroundImage('https://i.hizliresim.com/iBHC0t.jpg', canvas.renderAll.bind(canvas));
canvas.selection = false;
//var uniqid = "0";
var uniqids = 0;
$("#door").on("click", function(e) {
  var uniqid = uniqids.toString();
  rect = new fabric.Rect({
    id: uniqid,
    left: 40,
    top: 40,
    width: 35,
    height: 50,
    fill: 'blue',
    stroke: 'blue',
    strokeWidth: 5,
    strokeUniform: false,
    hasControls: true,
  });

  canvas.add(rect);
  uniqids++;


});
//*****************************
canvas.on('mouse:wheel', function(opt) {
  var delta = opt.e.deltaY;
  var zoom = canvas.getZoom();
  zoom *= 0.999 ** delta;
  if (zoom > 20) zoom = 20;
  if (zoom < 0.01) zoom = 0.01;
  canvas.setZoom(zoom);
  opt.e.preventDefault();
  opt.e.stopPropagation();

})




//***************************************

$("#save").on("click", function(e) {
  $(".save").html(canvas.toSVG());
});

$('#delete').click(function() {
  var activeObject = canvas.getActiveObjects();
  canvas.discardActiveObject();
  canvas.remove(...activeObject);
});

$("#btnResetZoom").on("click", function(e) {
  canvas.setViewportTransform([1, 0, 0, 1, 0, 0]);
});


canvas.on('mouse:wheel', function(opt) {
  var delta = opt.e.deltaY;
  var zoom = canvas.getZoom();
  zoom *= 0.999 ** delta;
  if (zoom > 20) zoom = 20;
  if (zoom < 0.01) zoom = 0.01;
  canvas.zoomToPoint({
    x: opt.e.offsetX,
    y: opt.e.offsetY
  }, zoom);
  opt.e.preventDefault();
  opt.e.stopPropagation();
});
var shiftKeyDown = true;
var 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);
  }
});


$('#getid').click(function() {
  var activeObject = canvas.getActiveObjects();
  alert(canvas.getActiveObject().id);
});

$("#changeColor").on("click", function(e) {
  document.getElementById("c").fabric = canvas;
  var tmpId = canvas.getActiveObject().id;
  var activeObject = canvas.getActiveObject();

  canvas.getObjects().forEach(function(o) {
    if (o.id == tmpId) {
      canvas.setActiveObject(o);
      activeObject.fill = '#fcba03';
      canvas.requestRenderAll();
    }

  })
});
#c {
  background-color: grey;
  margin-top: 10px;
}

button {
  padding: 10px 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.1.0/fabric.min.js"></script>


<button id="door">Add Rect</button>
<button id="delete">Delete Rect</button>
<button id="save">Save</button>
<button id="changeColor">ChangeColor</button>
<button id="getid">GET ID</button>

<p>Save bastıktan sonra altta SVG dosyası oluşur</p>
<br>
<canvas id="c" width="800" height="800"></canvas>
<br>
<p class="save">
</p>


Solution

  • This change felt to the objectCaching mechanizm (more info).

    If you want fabricJS to know that something changed and that a particular object needs to be redrawn, use the set method

    rect.set('fill', 'red');
    canvas.requestRenderAll();
    

    So, for you case

    var canvas = new fabric.Canvas('c');
    
    canvas.setBackgroundImage('https://i.hizliresim.com/iBHC0t.jpg', canvas.renderAll.bind(canvas));
    canvas.selection = false;
    //var uniqid = "0";
    var uniqids = 0;
    $("#door").on("click", function(e) {
      var uniqid = uniqids.toString();
      rect = new fabric.Rect({
        id: uniqid,
        left: 40,
        top: 40,
        width: 35,
        height: 50,
        fill: 'blue',
        stroke: 'blue',
        strokeWidth: 5,
        strokeUniform: false,
        hasControls: true,
      });
    
      canvas.add(rect);
      uniqids++;
    });
    //*****************************
    canvas.on('mouse:wheel', function(opt) {
      var delta = opt.e.deltaY;
      var zoom = canvas.getZoom();
      zoom *= 0.999 ** delta;
      if (zoom > 20) zoom = 20;
      if (zoom < 0.01) zoom = 0.01;
      canvas.setZoom(zoom);
      opt.e.preventDefault();
      opt.e.stopPropagation();
    })
    
    //***************************************
    
    $("#save").on("click", function(e) {
      $(".save").html(canvas.toSVG());
    });
    
    $('#delete').click(function() {
      var activeObject = canvas.getActiveObjects();
      canvas.discardActiveObject();
      canvas.remove(...activeObject);
    });
    
    $("#btnResetZoom").on("click", function(e) {
      canvas.setViewportTransform([1, 0, 0, 1, 0, 0]);
    });
    
    canvas.on('mouse:wheel', function(opt) {
      var delta = opt.e.deltaY;
      var zoom = canvas.getZoom();
      zoom *= 0.999 ** delta;
      if (zoom > 20) zoom = 20;
      if (zoom < 0.01) zoom = 0.01;
      canvas.zoomToPoint({
        x: opt.e.offsetX,
        y: opt.e.offsetY
      }, zoom);
      opt.e.preventDefault();
      opt.e.stopPropagation();
    });
    var shiftKeyDown = true;
    var 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);
      }
    });
    
    $('#getid').click(function() {
      var activeObject = canvas.getActiveObjects();
      alert(canvas.getActiveObject().id);
    });
    
    $("#changeColor").on("click", function(e) {
      canvas.getActiveObject().set('fill', '#fcba03');
      canvas.requestRenderAll();
    });
    #c {
      background-color: grey;
      margin-top: 10px;
    }
    
    button {
      padding: 10px 20px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.1.0/fabric.min.js"></script>
    
    <button id="door">Add Rect</button>
    <button id="delete">Delete Rect</button>
    <button id="save">Save</button>
    <button id="changeColor">ChangeColor</button>
    <button id="getid">GET ID</button>
    
    <p>Save bastıktan sonra altta SVG dosyası oluşur</p>
    <br>
    <canvas id="c" width="800" height="800"></canvas>
    <br>
    <p class="save">
    </p>