Я использую AngularJS и TypeScript. Я использую библиотеку cytoscape с расширением cytoscape-edgehandles и оболочкой ngCytoscape для AngularJS. Я пытаюсь добавить изображение в дескриптор наведения узлов, однако реализация метода drawImage в cytoscape-edgehandles 2.7.1 не ожидает загрузки изображения перед рисованием, поэтому возникает ошибка диапазона.

Я попытался дать графику Cytoscape параметры после загрузки изображения, однако график Cytoscape ожидает, что параметры будут немедленно доступны для использования. Так или иначе, мне нужно загрузить изображение, прежде чем передать его на график.

В конструкторе контроллера:

this.$scope.ehOptions = this.GetEhOptions();

Метод get EhOptions:

protected GetEhOptions(): GraphModels.EhOptions {
    var options = new GraphModels.EhOptions;

    var img = new Image();
    img.width = 25;
    img.height = 25
    img.src = "../../Content/icons/ic_circle_add_24px.svg";
    options.handleImage = img;
    img.addEventListener('load', e => {
          return options;
    });
}

Это приводит к тому, что параметры никогда не загружаются графиком. Если я сделаю это вместо меня, я получу все варианты, кроме изображения:

var options = new GraphModels.EhOptions;

var img = new Image();
img.width = 25;
img.height = 25
img.src = "../../Content/icons/ic_circle_add_24px.svg";

img.addEventListener('load', e => {
   options.handleImage = img;
});
return options;

Код cytoscape-edgehandles относительно handleIcon:

if(options().handleIcon){
    var icon = options().handleIcon;
    var width = icon.width*cy.zoom(), height = icon.height*cy.zoom();
    ctx.drawImage(icon, hx-(width/2), hy-(height/2), width, height);
}

Если это изменено на это, то это работает:

if (true) {
    var img = new Image();
    var width = 25 * cy.zoom();
    var height = 25 * cy.zoom();
    img.width = width;
    img.height = height
    img.src = "../../Content/icons/ic_circle_add_24px.svg";
    img.addEventListener('load', e => {
        ctx.drawImage(img, hx - (width/2), hy - (height/2), width, height)
    })
}

Однако я не могу изменить код библиотеки.

Надеюсь, у вас есть идеи. Спасибо!

2
Sander B 7 Ноя 2019 в 10:28
Предоставьте пример Stackblitz, если можете
 – 
Shashan Sooriyahetti
15 Ноя 2019 в 11:51

3 ответа

Создайте обещание AngularJS:

protected GetEhOptions(): GraphModels.EhOptions {

    var deferred = $q.defer();
    var options = new GraphModels.EhOptions;           
    var img = new Image();

    img.width = 25;
    img.height = 25
    img.src = "../../Content/icons/ic_circle_add_24px.svg";
    options.handleImage = img;
    img.addEventListener('load', e => {
         ̶r̶e̶t̶u̶r̶n̶ ̶o̶p̶t̶i̶o̶n̶s̶;̶
         deferred.resolve(options);
    });
    img.addEventListener('error', e => {
         deferred.reject(e);
    });

    return deferred.promise;
}

Затем извлеките параметры из возвращенного обещания:

this.GetEhOptions().then(options => {
  this.$scope.ehOptions = options;
});

Для получения дополнительной информации см.

2
georgeawg 15 Ноя 2019 в 20:03

Я понятия не имею о cytoscape, но попробуйте это,

options:any = new GraphModels.EhOptions;
let globleThis = this;

var img = new Image();
img.width = 25;
img.height = 25
img.src = "../../Content/icons/ic_circle_add_24px.svg";
this.options.handleImage = img;

img.addEventListener('load', e => {
   this.GetEhOptions(globleThis.options);
});

protected GetEhOptions(options): GraphModels.EhOptions {
   return options;
}

Или

var options = new GraphModels.EhOptions;

var img = new Image();
img.width = 25;
img.height = 25
img.src = "../../Content/icons/ic_circle_add_24px.svg";

img.addEventListener('load', e => {
   return options.handleImage = img;
});
0
Shashan Sooriyahetti 15 Ноя 2019 в 11:50

Нет опыта работы с конкретной библиотекой, но я работал с похожими. В этих случаях я заключил его в свою собственную директиву, а затем напрямую контролировал создание оттуда. В этом случае у вас есть доступ к элементу $, и вы можете создавать его на лету.

0
user1540857 15 Ноя 2019 в 11:57