Миграция кода из Open Laszlo 3.3 до 5.0: TypeError: Ошибка #1009: Невозможно получить доступ к свойству или методу пустой ссылки на объект

Я сталкиваюсь с проблемой, когда я запускаю этот код в 5.0, но он отлично работает в 3.3. Я установил все, но все же это создает проблему. Я делаю это неправильно?

<canvas width="1000" height="584">

      <drawview width="200" height="300" 
              x="12" 
              y="12">
        <handler name="onwidth">
            this.redraw();
        </handler>
        <handler name="onheight">
            this.redraw();
        </handler>
        <method name="redraw">
            this.clear();
            var roundness = 5;
            this.beginPath();
            this.moveTo(roundness, 0);
            this.lineTo(this.width - roundness, 0);
            this.quadraticCurveTo(this.width, 0, this.width, roundness);
            this.lineTo(this.width, this.height - roundness);
            this.quadraticCurveTo(this.width, this.height, this.width - roundness, this.height);
            this.lineTo(roundness, this.height);
            this.quadraticCurveTo(0, this.height, 0, this.height - roundness);
            this.lineTo(0, roundness);
            this.quadraticCurveTo(0, 0, roundness, 0);
            this.closePath();

            var g = this.createRadialGradient(-this.width * .5, -this.height *.5, .7, 1.5 * this.width, 1.5 * this.height, 0)
            this.globalAlpha = 0;
            g.addColorStop(0, 0x000000);
            this.globalAlpha = 0.8;
            g.addColorStop(1, 0xffffff);

            this.setAttribute("fillStyle", g);
            this.fill();
        </method>
    </drawview>
</canvas>

1 ответ

Решение

Обработчик onwidth и onheight вызывается во время инициализации drawview, в момент, когда инициализация компонента еще не завершена. Если вы проверите атрибут isinited компонента, вы можете убедиться, что метод перерисовки вызывается только тогда, когда компонент готов. Я добавил некоторые отладочные данные в этот пример, чтобы показать вам, что происходит:

<drawview id="dv" width="100%" height="100%" 
      x="12" 
      y="12">
  <attribute name="isready" value="false" type="boolean" />
  <handler name="oncontext">
    this.setAttribute("isready", true);
    this.redraw();
  </handler>
  <handler name="onwidth">
    Debug.write('onwidth: calling redraw()');
    this.redraw();
  </handler>
  <handler name="onheight">
    Debug.write('onheight: calling redraw()');
    this.redraw();
  </handler>
  <method name="redraw">
    Debug.info('redraw: this.ininited=' + this.isinited + ' / isready=' + this.isready);
    if (this.isready) {
      this.clear();
      var roundness = 5;
      this.beginPath();
      this.moveTo(roundness, 0);
      this.lineTo(this.width - roundness, 0);
      this.quadraticCurveTo(this.width, 0, this.width, roundness);
      this.lineTo(this.width, this.height - roundness);
      this.quadraticCurveTo(this.width, this.height, this.width - roundness, this.height);
      this.lineTo(roundness, this.height);
      this.quadraticCurveTo(0, this.height, 0, this.height - roundness);
      this.lineTo(0, roundness);
      this.quadraticCurveTo(0, 0, roundness, 0);
      this.closePath();

      var g = this.createRadialGradient(-this.width * .5, -this.height *.5, .7, 1.5 * this.width, 1.5 * this.height, 0);
      this.globalAlpha = 0;
      g.addColorStop(0, 0x000000);
      this.globalAlpha = 0.8;
      g.addColorStop(1, 0xffffff);

      this.setAttribute("fillStyle", g);
      this.fill();
    }
  </method>
</drawview>

Изменить: Обновлена ​​поддержка кода для использования события oncontext вместо значения isinited

Я проверил документацию по drawview, и у drawview есть специальное событие, называемое событием oncontext. Из документов:

Событие oncontext отправляется, когда контекст готов к использованию, что может занять некоторое время в IE DHTML.

Если вы посмотрите на документацию по drawview в ссылке на OpenLaszlo, то увидите, что в примерах для рисования на холсте используется обработчик события oncontext.
Я обновил свое решение для использования дополнительного атрибута isready, который устанавливается в значение true после получения события oncontext. Как вы можете видеть в выводе отладки ниже, для isinited установлено значение true, а для isready установлено значение true:

onwidth: calling redraw() 
INFO: redraw: this.ininited=true / isready=false 
onheight: calling redraw() 
INFO: redraw: this.ininited=true / isready=false 
INFO: redraw: this.ininited=true / isready=true 

Если вы компилируете свой код с ошибками для среды выполнения DHTML, вы должны были увидеть следующее предупреждение:

ВНИМАНИЕ: this.context еще не определен. Пожалуйста, проверьте наличие свойства context перед использованием методов рисования и / или зарегистрируйтесь для события oncontext, чтобы узнать, когда свойство доступно.

К сожалению, такое предупреждение не отображается для среды выполнения SWF.

Другие вопросы по тегам