Миграция кода из 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.