Search code examples
fabricjs

Problem subclassing fabricjs Image and restoring it


I am trying to subclass a fabricjs Image for a barcode field.

import {fabric} from 'fabric';
import bwipjs from 'bwip-js';

class Barcode extends fabric.Image {

    constructor(options) {
        console.log("constructor", options);
        var wrkOptions = {
            width: options.position.width,
            height: options.position.height,
            left: options.position.left,
            top: options.position.top,
            angle: options.direction || 0,
            form: options.form || {}
            };

        super(wrkOptions);
        this.type = 'barcode';

        let canvas1 = document.createElement('canvas');

        canvas1.width = options.position.width;
        canvas1.height = options.position.height;

        var bcOptions = {   bcid:        'code128',       // Barcode type
                                text:        '0123456789',    // Text to encode
                                scale:       3,               // 3x scaling factor
                                height:      10,              // Bar height, in millimeters
                                includetext: true,            // Show human-readable text
                                textxalign:  'center',        // Always good to set this
                        };

        bwipjs.toCanvas(canvas1, bcOptions);
        var dataUrl = canvas1.toDataURL("image/png");

       this.setSrc(dataUrl, () => {
           if (!options.restore) {
            curCanvas.add(this);
            this.setOptions(options);
            this.setCoords();
           }
            },
           wrkOptions);
        }


    toObject = () =>{
       var ret = {
             type: this.type,
             position: {top: this.top, left: this.left, width: this.width * this.scaleX, height: this.height * this.scaleY},
             color: this.fill,
             direction: this.angle,
             form: this.form
             };

       console.log(ret);
       return ret;


        }
    }


fabric.Barcode = Barcode;
fabric.Barcode.fromObject = function (options, callback)  {
    var wrkOptions = {restore: true, ...options};
    var bc =  new Barcode(wrkOptions);
    callback(bc);
    };

Creating the barcode field works:

 onAddBarcode = () => {
         var color = Math.floor(Math.random() * 256 * 256 *256).toString(16);

        var options = {
            color: "#" + color,
            position: {
                top: Math.floor(Math.random() * 500),
                left: Math.floor(Math.random() * 500),
                width: Math.floor(Math.random() * 100),
                height: Math.floor(Math.random() * 100)
                }
            };

        return ret;
            ...this.getRandom()
            };
        var barcode = new Barcode(options);
        }

But serializing and restoring the canvas does not work:

onReload = () => {
        var json = JSON.stringify(this.canvas, null, 2);
        this.canvas.clear();
        this.canvas.loadFromJSON(json, this.canvas.renderAll.bind(this.canvas));
        }

It does restore a barcode image, but it is positioned wrongly outside of the controls.

What's wrong?


Solution

  • I got it positioned correctly (after restoring) by resetting the position attributes in the setSrc callback:

    ....
        this.setSrv(dataUrl, 
                    () => {
                        this.left = options.position.left;
                        this.top = options.position.top;
                        this.angle = options.direction || 0;
                        this.width = options.position.width;
                        this.height = options.position.height;
                        this.setCoords();
                        callback(this);
                        });