Целевой JavaScript
В этом графическом примере с Canvas мы увидим, как простая функция делает JavaScript языком целевого программирования.
Пример показывает автомобиль, двигающийся по дороге, к месту назначения, его предназначение. Самый простой принцип программирования - определить цель в виде выражения и поместить действие, стремящееся к этой цели, в итерацию.
Показ
Цель - подпустить машину к правому краю рамы.
Код JavaScript
var car = new Image();
car.src="images/car-green.png";
var roadCanvas = document.getElementById("road");
var roadCtx = roadCanvas.getContext("2d");
function scenery() {
roadCtx.fillStyle="white";
roadCtx.rect(0,0,640,160);
roadCtx.fill();
}
var xcar= 0;
car.onload=function() {
roadCtx.drawImage(car, xcar, 60);
}
var carInterval;
var stopFlag=false;
function startCar() {
carInterval = setInterval(function() {
scenery();
roadCtx.drawImage(car, xcar, 60);
xcar++;
if(xcar >= 400 || stopFlag) {
clearInterval(carInterval);
return true;
}
}, 20);
}
HTML-код
<input type="button" value="Avancer" onClick="stopFlag=false;startCar()">
<input type="button" value="Stopper" onClick="stopFlag=true">
Возможно, можно добавить ограничение по времени, в этом случае ты просто пытаешься приблизиться к цели. Но с этим становится сложнее справиться, особенно если есть несколько объектов, которые нужно анимировать одновременно.
Однако ориентированное на цели программирование сделает все очень простым. Определяется функция «цель», которая имеет следующие аргументы:
- Условие, которое нужно выполнить, цель.
- Параметр максимальной продолжительности. И
- действия, которые должны быть совершены итеративно, чтобы приблизиться к цели.
Демонстрация, ориентированная на цель
Исходный код функции «цель»
var stopDuo=false;
var goal = function(condi, dur, actio) {
var iter = setInterval(function() {
if(condi() || stopDuo) {
clearInterval(iter);
clearTimeout(limiter);
return;
}
actio();
}, 0);
if(dur == "&") dur = 2147483647;
var limiter=setTimeout(function() { clearInterval(iter); }, dur);
}
Код JavaScript анимации
var orange = new Image();
orange.src="images/car-orange.png";
var green = new Image();
green.src="images/car-green.png";
var raceCanvas = document.getElementById("race");
var raceCtx = raceCanvas.getContext("2d");
var xgreen = 0;
var xorange = 0 ;
green.onload=function() {
raceCtx.drawImage(green, xgreen, 220);
}
orange.onload=function() {
raceCtx.drawImage(orange, xorange, 60);
}
function redraw()
{
raceCtx.fillStyle="white";
raceCtx.rect(0,0,640,320);
raceCtx.fill();
raceCtx.drawImage(orange, xorange, 60);
raceCtx.drawImage(green, xgreen, 220);
}
function startDuo() {
goal( function() { return (xorange >= 400); }, "&", function() {
redraw();
xorange++;
});
goal( function() { return(xgreen >= 400); }, "&", function() {
redraw();
xgreen+=2;
});
}
HTML-код
<input type="button" value="Avancer" onClick="stopDuo=false;startDuo()">
<input type="button" value="Stopper" onClick="stopDuo=true;">
Как видно, все это работает асинхронно. Обе машины двигаются одновременно, независимо друг от друга. Можно определить функцию назначения, действующую синхронно:
var goalSync=function(condi, dur, actio) {
stopFlag = false;
if(dur == "&") dur = 2147483647;
var limiter=setTimeout(function() { stopFlag=true; }, dur);
while(stopFlag == false) {
if(condi()) {
clearTimeout(limiter);
stopFlag=true;
return;
}
actio();
}
}
В этом случае машины двигались бы одна за другой.
Оба объекта являются частью фреймворка скриптол.js, используемого компилятором Script-JavaScript. Язык имеет более простой синтаксис для реализации целевой ориентации.