In this article

I’ve listed three ways to change an image in fabric.js.

It also includes the operation of changing pictures in the group.





Environment and Version

Chrome version: 96.0.4664.45

Fabric.js version: 4.6.0

I developed in a native environment and also provided a copy of the code developed in the Vue3 environment (link at the end of this article).





hands-on

PNG and bhikkhu.png, which were found on the iconfont website.

If you want to use the image of this case, you can obtain it in the warehouse provided at the end of this article.

Scenario 1: Change the SRC of the image element

If you add an Image object to the Canvas, you can use image.setsrc to set the new Image, and then refresh the Canvas with Canvas.renderall.

<style>
  canvas {
    border: 1px solid #ccc;
  }
</style>


<button onclick="change()">The images</button>
<canvas width="300" height="300" id="canvas"></canvas>


<script src="https://cdn.bootcdn.net/ajax/libs/fabric.js/460/fabric.min.js"></script>
<script>
  // instantiate canvas
  canvas = new fabric.Canvas('canvas')
  // Create a picture object
  fabric.Image.fromURL('.. /.. /images/Agumon.png'.oImg= > {
    // Add the image object to the canvas
    canvas.add(oImg)
  })

  // Replace the image event
  function change() {
    // Get the image object. Because in this case there is only one element in the canvas, the first element of the array retrieved with getObjects() is the image
    const img = canvas.getObjects()[0]
    // Use the setSrc method to change the image. The second parameter is the callback function. Refresh the canvas in the callback function
    img.setSrc('.. /.. /images/Bhikkhu.png'.() = > {
      canvas.renderAll()
    })
  }
</script>
Copy the code

The above scenario is the simplest.

If you have multiple shapes and images on the canvas, you may need to add some custom attributes to the canvas when creating the image.

Use fabric.getobjects ().find() to search.

Find () is the original method of the array.





Scenario 2: Modifying images within the group (no caching)

Create groups are cached by default, and rerendering using canvas.renderall () does not update images if cached.

Therefore, you need to specify Group. ObjectCaching when creating a Group.

<style>
  canvas {
    border: 1px solid #ccc;
  }
</style>


<button onclick="change()">The images</button>
<canvas width="300" height="300" id="canvas"></canvas>


<script src="https://cdn.bootcdn.net/ajax/libs/fabric.js/460/fabric.min.js"></script>
<script>
  // instantiate canvas
  canvas = new fabric.Canvas('canvas')
  // Create a picture object
  fabric.Image.fromURL('.. /.. /images/Agumon.png'.oImg= > {
    / / text
    const text = new fabric.Text('Group without cache', {
      fontSize: 14.top: 50
    })

    / / create a group
    const group = new fabric.Group([oImg, text], {
      objectCaching: false // No cache!!
    })
    // Add the group to the canvas
    canvas.add(group)
  })

  // Replace the image event
  function change() {
    / / access group
    const group = canvas.getObjects()[0]
    // Get the image
    const img = group.getObjects().find(item= > {
      // Determine image elements by isType because there are two elements in the group (one image, one text)
      return item.isType('image')})// Find the image and replace it
    img.setSrc('.. /.. /images/Bhikkhu.png'.() = > {
      // Refresh the canvas after replacing the image
      canvas.renderAll()
    })
  }
</script>
Copy the code

In this case, objectCaching: false should be declared, especially when creating a group.





Scenario 3: Modifying images within the group (cached)

If the Group (Group) is set to cache, you need to change the image in the Group (Group).

Here’s how I did it:

  1. Find the image object and save it to a variable;
  2. Remove picture objects from a Group (using group.removeWithUpdate);
  3. To update the image objectsrcPoint to (useImage.setSrc );
  4. Put images into groups (using group.addWithUpdate);
  5. Rerender the Canvas (using canvas.renderAll);


<style>
  canvas {
    border: 1px solid #ccc;
  }
</style>


<button onclick="change()">The images</button>
<canvas width="300" height="300" id="canvas"></canvas>


<script src="https://cdn.bootcdn.net/ajax/libs/fabric.js/460/fabric.min.js"></script>
<script>
  // instantiate canvas
  canvas = new fabric.Canvas('canvas')
  // Create a picture object
  fabric.Image.fromURL('.. /.. /images/Agumon.png'.oImg= > {
    / / text
    const text = new fabric.Text('Group without cache', {
      fontSize: 14.top: 50
    })

    / / create a group
    const group = new fabric.Group([oImg, text])
    // Add the group to the canvas
    canvas.add(group)
  })

  // Replace the image event
  function change() {
    / / access group
    const group = canvas.getObjects()[0]
    // [1] Find the image object and save it to a variable
    const img = group.getObjects().find(item= > {
      // Determine image elements by isType because there are two elements in the group (one image, one text)
      return item.isType('image')})// [2] Delete the image object in the group
    group.removeWithUpdate(img)
    
    // [3] Update the 'SRC' direction of the image object
    img.setSrc('.. /.. /images/Bhikkhu.png'.() = > {
      // [4] Put the pictures into groups
      group.addWithUpdate(img)
      [5] re-render the canvas
      canvas.renderAll()
    })
  }
</script>
Copy the code

Following this example can achieve the goal, but always feel uncomfortable.

If you have a better idea to share, discuss learning together.


If you also need to change images in your project, but not in the above 3 scenarios, please leave a comment and I will try to solve it.





Code warehouse

The native implementation changes the image

Images are changed using the Fabric implementation in Vue3





More recommended

Fabric.js from Getting Started to Mastering

Fabric.js implement Gradient effects, including radial Gradient radial

Fabric.js Custom Right-click menu