09. Функции. Часть 3. Конструкторы
Контрольные задания
-
Создать класс Cylinder для работы с цилиндрами.
// Конструктор function Cylinder(radius, height) { // Свойства экземпляра класса ... } // Методы экземпляра класса // Метод volume -- возвращает объём цилиндра ... // Свойства класса // Число пи ... // Методы класса // Метод maxVolume принимает два объекта Cylinder и возвращает // ссылку на объект с большим объёмом. ... // Тестирование // ------------ alert(Cylinder.PI); // 3.14159 var cyl1 = new Cylinder(10,20); var cyl2 = new Cylinder(20,10); alert(cyl1.volume()); // 6283.18 -- объём первого цилиндра alert(cyl2.volume()); // 12566.36 -- объём второго цилиндра // Показать радиус цилиндра с наибольшим объёмом alert(Cylinder.maxVolume(cyl1,cyl2).radius); // 20
Решение// Конструктор function Cylinder(radius, height) { // Свойства экземпляра класса this.radius = radius; this.height = height; } // Методы экземпляра класса // Метод volume -- возвращает объём цилиндра Cylinder.prototype.volume = function () { return Cylinder.PI*this.radius*this.radius*this.height; } // Свойства класса // Число пи Cylinder.PI = 3.14159; // Методы класса // Метод maxVolume принимает два объекта Cylinder и возвращает // ссылку на объект с большим объёмом. Cylinder.maxVolume = function (x,y) { return x.volume() > y.volume() ? x : y; }; // Тестирование // ------------ alert(Cylinder.PI); // 3.14159 var cyl1 = new Cylinder(10,20); var cyl2 = new Cylinder(20,10); alert(cyl1.volume()); // 6283.18 -- объём первого цилиндра alert(cyl2.volume()); // 12566.36 -- объём второго цилиндра // Показать радиус цилиндра с наибольшим объёмом alert(Cylinder.maxVolume(cyl1,cyl2).radius); // 20
-
- Point — для работы с точками
- Rectangle — для работы с прямоугольниками
- Button — для работы с «кнопками» — прямоугольными областями в окне браузера
Класс Point — базовый. Класс Rectangle опирается на класс Point, а класс Button — на класс Rectangle.
При создании классов руководствуйтесь комментариями, которыми снабжены заготовки конструкций. После заполнения пустых мест в следующем ниже коде, сохраните код в виде файла index.htm и загрузите его в браузер для проведения тестовых испытаний (уже написанных в коде).
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <HTML lang="ru"> <HEAD> <META http-equiv="content-type" content="text/html; charset=windows-1251"> <TITLE>Работа с кнопками</TITLE> <SCRIPT> //-------------------------------------------------------------------- // Здесь описаны классы Точка (Point), Прямоугольник (Rectangle) // и Кнопка (Button) // Последний класс служит для вывода прямоугольных областей в // произвольные места окна браузера. //-------------------------------------------------------------------- // Начало описания класса Point -------------------------------------- // Конструктор класса Точка // Объекты класса Точка представляют собой точку на экране // в декартовой системе координат (x,y). Точка с координатами (0,0) // расположена в верхнем левом углу. Координата x увеличивается // горизонтально вправо, координата y увеличивается вертикально вниз. // function Point(x, y) { ... } // Сложение точек (сложение соответствующих координат). // Результат сохраняется в текущей точке. // Текущая точка this складывается с точкой-аргументом. // Метод не возвращает никакого значения. Point.prototype.add = function (p) { ... } // Вычитание точек (вычитание соответствующих координат). // Результат сохраняется в текущей точке. // От текущей точки this вычитается точка-аргумент. // Метод не возвращает никакого значения. Point.prototype.sub = function (p) { ... } // Равенство точек. // Текущая точка this сравнивается с точкой-аргументом // Метод возвращает true, если точки совпадают. Point.prototype.isEq = function (p) { ... } // Конец описания класса Point --------------------------------------- // Начало описания класса Rectangle ---------------------------------- // Конструктор класса Прямоугольник // Объект класса Прямоугольник представляют собой прямоугольник, // заданный двумя точками p1 и p2. // Точка p1 задает верхний левый угол прямоугольника. // Точка p2 задает нижний правый угол прямоугольника. function Rectangle(p1,p2) { ... } // Вернуть ширину прямоугольника Rectangle.prototype.getWidth = function () { ... } // Вернуть высоту прямоугольника Rectangle.prototype.getHeight = function () { ... } // Вернуть новый прямоугольник -- копию данного Rectangle.prototype.copy = function () { ... } // Переместить прямоугольник на указанные смещения Rectangle.prototype.move = function (dx, dy) { ... } // Переместить прямоугольник в точку p так, чтобы его верхний // левый угол оказалcя в заданной точке. Rectangle.prototype.moveToPoint = function (p) { ... } // Расширить прямоугольник на указанные величины по всем осям // в обоих направлениях Rectangle.prototype.grow = function (dx, dy) { ... } // Пересечение прямоугольников. Получить прямоугольник, // который является пересечением текущего прямоугольника и // прямоугольника-аргумента. // Результат сохраняется в текущем прямоугольнике. Rectangle.prototype.intersect = function (r) { ... } // Пересечение прямоугольников. Получить прямоугольник, // который является пересечением текущего прямоугольника и // прямоугольника-аргумента. // Результат вернуть в качестве нового прямоугольника Rectangle.prototype.intersectNew = function (r) { ... } // Объединение прямоугольников. Получить прямоугольник, // который описан вокруг двух фигур: текущего прямоугольника, и // прямоугольника-аргумента. // Результат сохраняется в текущем прямоугольнике. Rectangle.prototype.union = function (r) { ... } // Объединение прямоугольников. Получить прямоугольник, // который описан вокруг двух фигур: текущего прямоугольника, и // прямоугольника-аргумента. // Результат вернуть в качестве нового прямоугольника Rectangle.prototype.unionNew = function (r) { ... } // Содержится ли точка p в текущем прямоугольнике? Rectangle.prototype.contains = function (p) { ... } // Вырожден ли прямоугольник? // Прямоугольник вырожден, если первая точка правее или ниже второй, // а также в случае, если точки совпадают. Rectangle.prototype.isEmpty = function () { ... } // Конец описания класса Rectangle ---------------------------------- // Начало описания класса Button ------------------------------------- // Кнопка на экране // Конструктор класса Button // Объект класса Button представляют собой закрашенный прямоугольник // с рамкой и надписью внутри // Аргументы конструктора: // r -- объект-прямоугольник (обязательный параметр) // title -- надпись на кнопке, пустая строка, если аргумента нет // fon_color -- цвет фона кнопки, белый, если аргумент отсутствует // border_color -- цвет рамки, чёрный, если аргумент отсутствует function Button(r, title, fon_color, border_color) { this.r = ... this.title = ... this.fon_color = ... this.border_color = ... // Создадим элемент DIV // Метод createElement объекта document создаёт элемент, // название которого задано аргументом метода this.elementHTML = document.createElement("div"); // Добавим к созданному элементу потомка -- текстовый элемент this.elementHTML.appendChild(document.createTextNode(this.title)); // Создадим нужные стили для блока DIV // Доступ к стилям через свойство style элемента this.elementHTML.style.position = "absolute"; this.elementHTML.style.left = this.r.p1.x+"px"; this.elementHTML.style.top = this.r.p1.y+"px"; this.elementHTML.style.width = this.r.getWidth()+"px"; this.elementHTML.style.height = this.r.getHeight()+"px"; this.elementHTML.style.backgroundColor = this.fon_color; this.elementHTML.style.border = "1px solid " + this.border_color; this.elementHTML.style.textAlign = "center"; this.elementHTML.style.font = "icon"; } // Отобразить Кнопку на экране Button.prototype.draw = function () { // Добавим элемент потомок к BODY -- и он сразу // отобразится на экране document.body.appendChild(this.elementHTML); } // Сместить кнопку на (dx, dy) Button.prototype.move = function (dx, dy) { this.r.move(dx,dy); this.elementHTML.style.left = this.r.p1.x+"px"; this.elementHTML.style.top = this.r.p1.y+"px"; } // Конец описания класса Button ------------------------------------- // ------------------------------------------------------------------- // Создадим обработчик события onload ("окончание загрузки документа") // В качестве обработчика этого события задается функциональный литерал, // который будет запущен на выполнение один раз после того как наступит // событие "текущий HTML-документ полностью загружен в браузер" // ------------------------------------------------------------------- window.onload = function() { // Создаём первую кнопку var button1 = new Button ( new Rectangle(new Point(100,100), new Point(200,140)), "Кнопка","#ffbf00" ); // Создаём вторую кнопку var button2 = new Button ( new Rectangle(new Point(250,100), new Point(500,150)), "Очень большая кнопка", "#40ff00", "blue" ); // Показываем созданные кнопки на экране button1.draw(); button2.draw(); alert("Покажем массив кнопок"); // Готовимся к созданию массива кнопок var n = 10; // Число кнопок в массиве var b = new Array(n); // Массив для n кнопок var x0 = 0, y0 = 200; // Начальное положение первой кнопки на экране var w = 80, h = 30; // Ширина и высота каждой кнопки // Создадим массив кнопок и покажем их на экране for (var i=0; i<b.length; i++) { // Создадим кнопку... b[i] = new Button ( new Rectangle(new Point(x0+i*w,y0), new Point(x0+i*w + w,y0+h)), "Кнопка "+ i, "rgb("+Number(250-i*25)+","+i*25+","+i*25+")"); // и тут же ее покажем b[i].draw(); } alert("Сместим кнопку 1 на 50 пикселов вверх"); b[1].move(0, -50); alert("Сместим кнопку 3 на 50 пикселов вниз"); b[3].move(0, 50); alert("Сместим кнопку 5 на 20 пикселов влево и вверх"); b[5].move(-20, 20); alert("Проверим, есть ли пересечение кнопки 5 с кнопкой 4"); alert(!(b[5].r.intersectNew(b[4].r).isEmpty())); alert("Проверим, есть ли пересечение кнопки 5 с кнопкой 3"); alert(!(b[5].r.intersectNew(b[3].r).isEmpty())); }; </SCRIPT> </HEAD> <BODY> <H1>Работа с кнопками</H1> </BODY> </HTML>
Решение<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <HTML lang="ru"> <HEAD> <META http-equiv="content-type" content="text/html; charset=windows-1251"> <TITLE>Работа с кнопками</TITLE> <SCRIPT> //-------------------------------------------------------------------- // Здесь описаны классы Точка (Point), Прямоугольник (Rectangle) // и Кнопка (Button) // Последний класс служит для вывода прямоугольных областей в // произвольные места окна браузера. //-------------------------------------------------------------------- // Начало описания класса Point -------------------------------------- // Конструктор класса Точка // Объекты класса Точка представляют собой точку на экране // в декартовой системе координат (x,y). Точка с координатами (0,0) // расположена в верхнем левом углу. Координата x увеличивается // горизонтально вправо, координата y увеличивается вертикально вниз. // function Point(x, y) { this.x = x; this.y = y; } // Сложение точек (сложение соответствующих координат). // Результат сохраняется в текущей точке. // Текущая точка this складывается с точкой-аргументом. // Метод не возвращает никакого значения. Point.prototype.add = function (p) { this.x += p.x; this.y += p.y; } // Вычитание точек (вычитание соответствующих координат). // Результат сохраняется в текущей точке. // От текущей точки this вычитается точка-аргумент. // Метод не возвращает никакого значения. Point.prototype.sub = function (p) { this.x -= p.x; this.y -= p.y; } // Равенство точек. // Текущая точка this сравнивается с точкой-аргументом // Метод возвращает true, если точки совпадают. Point.prototype.isEq = function (p) { return (this.x == p.x) && (this.y == p.y); } // Конец описания класса Point --------------------------------------- // Начало описания класса Rectangle ---------------------------------- // Конструктор класса Прямоугольник // Объект класса Прямоугольник представляют собой прямоугольник, // заданный двумя точками p1 и p2. // Точка p1 задает верхний левый угол прямоугольника. // Точка p2 задает нижний правый угол прямоугольника. function Rectangle(p1,p2) { this.p1 = new Point(p1.x,p1.y); this.p2 = new Point(p2.x,p2.y); } // Вернуть ширину прямоугольника Rectangle.prototype.getWidth = function () { return this.p2.x - this.p1.x; } // Вернуть высоту прямоугольника Rectangle.prototype.getHeight = function () { return this.p2.y - this.p1.y; } // Вернуть новый прямоугольник -- копию данного Rectangle.prototype.copy = function () { return new Rectangle(this.p1, this.p2); } // Переместить прямоугольник на указанные смещения Rectangle.prototype.move = function (dx, dy) { this.p1.x += dx; this.p1.y += dy; this.p2.x += dx; this.p2.y += dy; } // Переместить прямоугольник в точку p так, чтобы его верхний // левый угол оказалcя в заданной точке. Rectangle.prototype.moveToPoint = function (p) { var w = this.getWidth(); var h = this.getHeight(); this.p1.x = p.x; this.p1.y = p.y; this.p2.x = p.x + w; this.p2.y = p.y + h; } // Расширить прямоугольник на указанные величины по всем осям // в обоих направлениях Rectangle.prototype.grow = function (dx, dy) { this.p1.x -= dx; this.p1.y -= dy; this.p2.x += dx; this.p2.y += dy; } // Пересечение прямоугольников. Получить прямоугольник, // который является пересечением текущего прямоугольника и // прямоугольника-аргумента. // Результат сохраняется в текущем прямоугольнике. Rectangle.prototype.intersect = function (r) { this.p1.x = Math.max(this.p1.x,r.p1.x); this.p1.y = Math.max(this.p1.y,r.p1.y); this.p2.x = Math.min(this.p2.x,r.p2.x); this.p2.y = Math.min(this.p2.y,r.p2.y); } // Пересечение прямоугольников. Получить прямоугольник, // который является пересечением текущего прямоугольника и // прямоугольника-аргумента. // Результат вернуть в качестве нового прямоугольника Rectangle.prototype.intersectNew = function (r) { var rect = this.copy(); rect.p1.x = Math.max(rect.p1.x,r.p1.x); rect.p1.y = Math.max(rect.p1.y,r.p1.y); rect.p2.x = Math.min(rect.p2.x,r.p2.x); rect.p2.y = Math.min(rect.p2.y,r.p2.y); return rect; } // Объединение прямоугольников. Получить прямоугольник, // который описан вокруг двух фигур: текущего прямоугольника, и // прямоугольника-аргумента. // Результат сохраняется в текущем прямоугольнике. Rectangle.prototype.union = function (r) { this.p1.x = Math.min(this.p1.x,r.p1.x); this.p1.y = Math.min(this.p1.y,r.p1.y); this.p2.x = Math.max(this.p2.x,r.p2.x); this.p2.y = Math.max(this.p2.y,r.p2.y); } // Объединение прямоугольников. Получить прямоугольник, // который описан вокруг двух фигур: текущего прямоугольника, и // прямоугольника-аргумента. // Результат вернуть в качестве нового прямоугольника Rectangle.prototype.unionNew = function (r) { var rect = this.copy(); rect.p1.x = Math.min(rect.p1.x,r.p1.x); rect.p1.y = Math.min(rect.p1.y,r.p1.y); rect.p2.x = Math.max(rect.p2.x,r.p2.x); rect.p2.y = Math.max(rect.p2.y,r.p2.y); return rect; } // Содержится ли точка p в текущем прямоугольнике? Rectangle.prototype.contains = function (p) { return p.x >= this.p1.x && p.x <= this.p2.x && p.y >= this.p1.y && p.y <= this.p2.y; } // Вырожден ли прямоугольник? // Прямоугольник вырожден, если первая точка правее или ниже второй, // а также в случае, если точки совпадают. Rectangle.prototype.isEmpty = function () { return this.p1.x >= this.p2.x || this.p1.y >= this.p2.y; } // Конец описания класса Rectangle ---------------------------------- // Начало описания класса Button ------------------------------------- // Кнопка на экране // Конструктор класса Button // Объект класса Button представляют собой закрашенный прямоугольник // с рамкой и надписью внутри // Аргументы конструктора: // r -- объект-прямоугольник (обязательный параметр) // title -- надпись на кнопке, пустая строка, если аргумента нет // fon_color -- цвет фона кнопки, белый, если аргумент отсутствует // border_color -- цвет рамки, чёрный, если аргумент отсутствует function Button(r, title, fon_color, border_color) { this.r = r; this.title = title || ""; this.fon_color = fon_color || "white"; this.border_color = border_color || "black"; // Создадим элемент DIV // Метод createElement объекта document создаёт элемент, // название которого задано аргументом метода this.elementHTML = document.createElement("div"); // Добавим к созданному элементу потомка -- текстовый элемент this.elementHTML.appendChild(document.createTextNode(this.title)); // Создадим нужные стили для блока DIV // Доступ к стилям через свойство style элемента this.elementHTML.style.position = "absolute"; this.elementHTML.style.left = this.r.p1.x+"px"; this.elementHTML.style.top = this.r.p1.y+"px"; this.elementHTML.style.width = this.r.getWidth()+"px"; this.elementHTML.style.height = this.r.getHeight()+"px"; this.elementHTML.style.backgroundColor = this.fon_color; this.elementHTML.style.border = "1px solid " + this.border_color; this.elementHTML.style.textAlign = "center"; this.elementHTML.style.font = "icon"; } // Отобразить Кнопку на экране Button.prototype.draw = function () { // Добавим элемент потомок к BODY -- и он сразу // отобразится на экране document.body.appendChild(this.elementHTML); } // Сместить кнопку на (dx, dy) Button.prototype.move = function (dx, dy) { this.r.move(dx,dy); this.elementHTML.style.left = this.r.p1.x+"px"; this.elementHTML.style.top = this.r.p1.y+"px"; } // Конец описания класса Button ------------------------------------- // ------------------------------------------------------------------- // Создадим обработчик события onload ("окончание загрузки документа") // В качестве обработчика этого события задается функциональный литерал, // который будет запущен на выполнение один раз после того как наступит // событие "текущий HTML-документ полностью загружен в браузер" // ------------------------------------------------------------------- window.onload = function() { // Создаём первую кнопку var button1 = new Button ( new Rectangle(new Point(100,100), new Point(200,140)), "Кнопка","#ffbf00" ); // Создаём вторую кнопку var button2 = new Button ( new Rectangle(new Point(250,100), new Point(500,150)), "Очень большая кнопка", "#40ff00", "blue" ); // Показываем созданные кнопки на экране button1.draw(); button2.draw(); alert("Покажем массив кнопок"); // Готовимся к созданию массива кнопок var n = 10; // Число кнопок в массиве var b = new Array(n); // Массив для n кнопок var x0 = 0, y0 = 200; // Начальное положение первой кнопки на экране var w = 80, h = 30; // Ширина и высота каждой кнопки // Создадим массив кнопок и покажем их на экране for (var i=0; i<b.length; i++) { // Создадим кнопку... b[i] = new Button ( new Rectangle(new Point(x0+i*w,y0), new Point(x0+i*w + w,y0+h)), "Кнопка "+ i, "rgb("+Number(250-i*25)+","+i*25+","+i*25+")"); // и тут же ее покажем b[i].draw(); } alert("Сместим кнопку 1 на 50 пикселов вверх"); b[1].move(0, -50); alert("Сместим кнопку 3 на 50 пикселов вниз"); b[3].move(0, 50); alert("Сместим кнопку 5 на 20 пикселов влево и вниз"); b[5].move(-20, 20); alert("Проверим, есть ли пересечение кнопки 5 с кнопкой 4"); alert(!(b[5].r.intersectNew(b[4].r).isEmpty())); alert("Проверим, есть ли пересечение кнопки 5 с кнопкой 3"); alert(!(b[5].r.intersectNew(b[3].r).isEmpty())); }; </SCRIPT> </HEAD> <BODY> <H1>Работа с кнопками</H1> </BODY> </HTML>