Fabric.js custom object properties and work with video element

Posted on: 1/7/2025 4:41:00 PM

Here is some tips when i work with fabricjs to build Canva-like editor.

Custom object properties

For saving some custom properties when work with fabricjs, you need to add a custom attribute to fabric object, for doing this you need to override fabric Object toObject method.

import { Object as FabricObject } from 'fabric'

//whatever properties you want to save
const _properties = ['video_src', 'animationType', 'hyperlink'];

FabricObject.prototype.toObject = (function (toObject) {
    return function (propertiesToInclude) {
        propertiesToInclude = (propertiesToInclude || []).concat(_properties);
        return toObject.apply(this, [propertiesToInclude]);
    };
})(FabricObject.prototype.toObject);

Save and re-render video element

As original example: https://fabricjs.com/demos/video-element/ You can add video element to canvas. But how about if you want to export, then import data from JSON?

Work with video element

 First, this is some code to render video element to our canvas

import { Object as FabricObject, util, Image as FabricImage, Canvas } from "fabric";

function createVideoElement(url) {
    var videoE = document.createElement('video');
    videoE.width = 530;
    videoE.height = 298;
    videoE.muted = true;
    videoE.crossOrigin = "anonymous";
    var source = document.createElement('source');
    source.src = url;
    source.type = 'video/mp4';
    videoE.appendChild(source);
    return videoE;
}
var canvas = new FabricCanvas('c');
var url_mp4 = '/path/to/video.mp4';

var videoE = createVideoElement(url_mp4);
var fab_video = new FabricImage(videoE, {left: 0,   top: 0});
fab_video.set('video_src', url_mp4); // <========= set custom property to save video src
canvas.add(fab_video);
fab_video.getElement().play();
util.requestAnimFrame(function render() {
   canvas.renderAll();
   util.requestAnimFrame(render);
});

You can see a line:

fab_video.set('video_src', url_mp4); // <========= set custom property to save video src

==> Read Custom object properties trick above, and add video_src property.

Now, we can export to json by call method: 

canvas.toJSON();

Ok, now we can load saved json by call this method:

canvas.loadFromJSON(json_data)
//loadFromJSON method used to convert JSON object to actual fabric object and load them to canvas.

The question now is how it will recognize the custom attribute video_src. The answer is, it won’t. We need to create a video element and render it manually.


function canvasLoaded(){      
   canvas.renderAll.bind(canvas);
   var objs = data['objects'];      
   for(var i=0; i< objs.length; i++){
      const elm = objs[i];
      if(objs[i].hasOwnProperty('video_src')){
         var videoE = createVideoElement(elm['video_src']); 
         videoE.addEventListener("loadeddata", () => {
             videoE.width = videoE.videoWidth;
             videoE.height = videoE.videoHeight;
             elm.setElement(videoE);
             elm.getElement().play();
         });
         util.requestAnimFrame(function render() {
             canvas.renderAll();
             util.requestAnimFrame(render);
         });
      }
   }
}

//load saved json data to canvas, then process to display video element.
var canvas = canvas.loadFromJSON(json_data).then(canvasLoaded);

Tip: In method canvasLoaded above, we check if object has video_src, then create a html video element then using setElement method to mount it to existed image element we added before, so all saved properties is not changed.

References