Графический редактор на JavaScript. Часть 1. Введение

👁 158 просмотров

Данный цикл статей будет относится к проектированию простого графического редактора на основе клиентского языка JavaScript и серверного языка PHP. Графический редактор будет иметь возможность создавать простейшие примитивы: линия, эллипс, прямоугольник, многоугольник. Опишем возможность добавления, редактирования и удаления примитивов из текстового файла. Прорисовка примитивов будет производиться средствами HTML5 Canvas. HTML5 интегрирован с языком JavaScript и позволяет нам напрямую использовать API Canvas.

1. Клиентская часть на JavaScript

Клиентская часть, как известно, выполняется в браузера удаленного пользователя и для того, чтобы пользователь имел возможность редактировать файл на сервере необходимо будет иметь постоянную связь с PHP скриптом, для передачи параметров интерактивного редактирования примитива. Для этого будем использовать технологию ассинхроной связи с сервером AJAX. Для кроссбраузерной совместимости будем сразу использовать какую-нибудь библиотеку JavaScript, чтобы не отвлекаться на ненужные приемы совместимости и лучщим решением будет jQuery.

2. Серверная часть на PHP

Серверная часть будет написана на PHP. Необходимость в использовании PHP обусловлено тем, что JavaScript не имеет возможности работать с файлами: записывать, удалять, редактировать… Поэтому использование серверного языка — это одна из необходимостей для создания и редактирования графического файла, в котором будут храниться наши данные.

3. Расширение файла

Для того, чтобы сохранить наши примитивы для передачи между пользователями будем использовать обычный текстовый файл с расширением *.sgf(Simple Graphic Format). Название расширения не играет роли, можно любое, которое угодно вам и от этого файл не перестает быть текстовым. Другое дело — это , если бы мы использовали бинарный файл с 16-ричными значениями, но нас сейчас интересует первый вариант в виду легкости разработки и быстроты реализации.

4. Стрктура файла

Файл является собственным, структурированным, а это значит, что он не стнадартизирован как xml, хотя, можно было бы и его использовать, но не будем плодить копию SVG, а создадим свою структуру с нуля, чтобы лучше понять процесс разработки

Диалоговое окно открытия и сохранения файла в JavaFX

👁 367 просмотров

Иногда в программе требуется реализовать диалоговое окно, которое будет открывать или сохранять файл и для таких целей в JavaFX есть отдельный класс FileChooser. Данный класс реализует данные диалоговые окна посредством вызова методов showOpenDialog() или showSaveDialog().

1. Открытие файла определенного расширения

Ниже покажем пример кода реализации диалогового окна открытия файла определенного расширения или списка расширений

@FXML
private void hndlOpenFile(ActionEvent event) {
        FileChooser fileChooser = new FileChooser();//Класс работы с диалогом выборки и сохранения
        fileChooser.setTitle("Open Document");//Заголовок диалога
        FileChooser.ExtensionFilter extFilter = 
        new FileChooser.ExtensionFilter("HTML files (*.html)", "*.html");//Расширение
        fileChooser.getExtensionFilters().add(extFilter);
        File file = fileChooser.showOpenDialog(CodeNote.mainStage);//Указываем текущую сцену CodeNote.mainStage
        if (file != null) {
            //Open
            System.out.println("Процесс открытия файла");
        }
}

2. Диалоговое окно сохранения файла определенного расширения

Ниже покажем пример кода реализации диалогового окна сохранения файла определенного расширения или списка расширений

@FXML
private void hndlOpenFile(ActionEvent event) {
    FileChooser fileChooser = new FileChooser();//Класс работы с диалогом выборки и сохранения
    fileChooser.setTitle("Save Document");//Заголовок диалога
    FileChooser.ExtensionFilter extFilter = 
    new FileChooser.ExtensionFilter("HTML files (*.html)", "*.html");//Расширение
    fileChooser.getExtensionFilters().add(extFilter);
    File file = fileChooser.showSaveDialog(CodeNote.mainStage);//Указываем текущую сцену CodeNote.mainStage
    if (file != null) {
        //Save
        System.out.println("Процесс открытия файла");
    }
}

3. Дополнительно

Для того, чтобы открывать или сохранять несколько видов расширений необходимо использовать мульти-фильтр

fileChooser.getExtensionFilters().addAll(
    new FileChooser.ExtensionFilter("All Images", "*.*"),
    new FileChooser.ExtensionFilter("HTML Documents", "*.html"),
    new FileChooser.ExtensionFilter("JPG", "*.jpg"),
    new FileChooser.ExtensionFilter("PNG", "*.png")
);

Для того, чтобы открывать несколько файлов необходимо использовать диалоговое окно мульти-выборки, который вызывается посредством метода showOpenMultipleDialog

List<File> list =
    fileChooser.showOpenMultipleDialog(CodeNote.mainStage);
    if (list != null) {
    for (File file : list) {
    openFile(file);
    }
}

Для того, чтобы узнать какое расширение выбрано в процессе сохранения или открытия используем getSelectedExtensionFilter(), а для того, чтобы сравнить существующие расширения используем метод getExtensionFilters().get(index), где index — порядковый номер регистрированного расширения

if(fileChooser.getSelectedExtensionFilter().equals(fileChooser.getExtensionFilters().get(0))){
    if (!file.getPath().endsWith(".html")) {
        file = new File(file.getPath() + ".html");
    }
        System.out.println("Процесс сохранения html файла");
    }else if(fileChooser.getSelectedExtensionFilter().equals(fileChooser.getExtensionFilters().get(1)))
    {
    if (!file.getPath().endsWith(".png")) {
        file = new File(file.getPath() + ".png");
    }
    System.out.println("Процесс сохранения png файла");
}

Создание архитектуры масштабируемого приложения Node.js

👁 395 просмотров

Понятие «Архитектура приложения»

Любая программа, будь то десктопная или WEB, должна иметь определенные правила оформления кода: классов, файлов, методов, частей и т.д. Это делается, скорее всего, для того, чтобы увеличить производительность труда разработчиков и уменьшить риск возникновения непредвиденной работы программы, которую можно быстро идентифицировать и отладить. Существуют несколько подходов того, как должна строиться архитектура WEB — приложения, в частности, эти же правила можно перенести и на приложения Node.js — это MVC, HMVC, MOVE и другие. В данной же статье рассмотрим простейший пример реализации архитектуры приложения на основе модели MVC (Model-View-Controller). Не будем придумывать что такое MVC,  а приведем цитату первого абзаца из Википедии:

Model-view-controller (MVC, «модель-представление-поведение», «модель-представление-контроллер», «модель-вид-контроллер») — схема использования нескольких шаблонов проектирования, с помощью которых модель данных приложения, пользовательский интерфейс и взаимодействие с пользователем разделены на три отдельных компонента таким образом, чтобы модификация одного из компонентов оказывала минимальное воздействие на остальные. Данная схема проектирования часто используется для построения архитектурного каркаса, когда переходят от теории к реализации в конкретной предметной области

Модель MVC, как и любая другая, — это такая вещь, которая призвана упростить разделение труда разработчиков. Так, если одна группа разрабатывает интерфейс, другая — пишет код, третья — разрабатывает модель взаимодействия и хранения, то MVC с легкостью может все это соединить воедино, чтобы получить рабочее приложение и наоборот — может разделить так, что одна модель может иметь несколько представлений, к примеру, одни и те же данные из БД выводятся на одной странице сайта в виде круговой диаграммы, а в другой -в виде таблицы, но данные неизменны или другой пример, где один и тот же запрос пользователя может воздействовать на модель по разному в различных представления, в зависимости от настроек контроллера и вида. По способу взаимодействия MVC можно подразделить на MVC с пассивной моделью, где данные отправляет на вид контроллер и с активной моделью, где данные отправляет на вид сама модель

mvc-active-passive-model

Это не единственное отличие, которое может быть в MVC, их ровно столько, сколько может позволить себе любой разработчик, но концепция MVC едина для всех.

Модульность в Node.js

Прежде чем рассмотрим реализацию архитектуры приложения в Node.js, давайте обсудим про модульность в Node.js. Как известно Node.js — это модульная платформа, в котором все работает по принципу лего. Даже простой пример

var http = require('http');//Подключаем модуль приема и отправки по протоколу Http 
//Создаем объект нового сервера 
http.createServer(function (req, res) { //Передаем заголовок res.writeHead(200, {'Content-Type': 'text/plain'}); //Выводим запись 
res.end('Hello World\n'); }).listen(1337, '127.0.0.1');//Указываем адрес хоста 
//Уведомляем в консоли о том, что запущен наш сервер console.log('Server running at http://127.0.0.1:1337/');

подключает модуль http для приема и отправки запросов, который находиться в составе Node.js,  а другой модуль, к примеру, fs нужен Node.js для работы с файловой системой компьютера и он тоже входит в стандартный набор Node.js, но это не значит, что платформа Node.js содержит модули для решения всех задач, которые встречаются у разработчиков, к примеру, в стандартный состав Node.js не входит модуль для работы с сокетами и для этого нам надо его установить через консоль командой

npm install socket.io

Отсюда мы понимаем, что для того чтобы создать масштабируемое приложение нам будет необходимо разделить его на отдельные модули и подключать их к программе по мере необходимости и Node.js позволяет нам создавать собственные модули. Для примера разделим выше приведенный простой код на модули и получим идентичный результат. Чтобы разбить код на модули нам необходимо создавать файлы модулей, к примеру, мы создадим новый модуль под названием server в файле serevr.js и поместим в нее весь код работы с запросами к серверу, а в файле index.js мы запустим наш пользовательский модуль server.  Название модуля соответствует названию файла без расширения .js, код в файле server.js будет следующим

 

var http = require('http');//Подключаем модуль протокола http

function start()//Создаем метод запуска модуля
{
	function onRequest(req, res){
	  //Передаем заголовок
	  res.writeHead(200, {'Content-Type': 'text/plain'});
	  //Выводим запись
	  res.end('Hello World from Server!\n');
	}
	//Указываем адрес хоста
	http.createServer(onRequest).listen(1337, '127.0.0.1');
}
//Указываем, что данный метод доступен из вне
exports.start = start;

А в файле index.js запишем код подключения модуля server и ее запуска

var server = require('./server');//Подключаем наш модуль server
server.start();//Запускаем наш модуль сервер
//Уведомляем в консоли о том, что запущен наш сервер
console.log('Server running at http://127.0.0.1:1337/');

Запускаем наш пример командой

node [ваш путь]/server.js

если все запустилось удачно, то будет следующее сообщение в консоли

start-node-js-hello-world-result

 

После этого идем в браузер и набираем адрес нашего запущенного хоста

http://127.0.0.1:1337/

node-js-h-w-module-from-server

На этом пример создания простого модуля закончено.

Роутер и обработка запросов

В предыдущем пункте мы использовали такую функцию, как onRequest(req, res), где req(request) — объект запроса пользователя, а res(response) — это ответ пользователю. Не имеет значения как называется данная функция, она передается как параметр, для нас важны параметры, которые передаются в данную функцию. Данная функция еще называется функцией обратного вызова(callback), которая работает ассинхронно. Чтобы соответствовать уровню MVC нам необходимо определять получаемые запросы из параметра req  и передавать в параметр  res ответ в виде вида страницы. А вид страницы — это сверстанный HTML файл, и таких файлов столько, сколько необходимо для нашего приложения и пользователь видит только их. Обычно, данные файлы расположены в отдельной папке. Чтобы узнать какой запрос с POST и GET данными отправил пользователь, нам необходим роутер, который будет проверять и выдавать ту информацию, которую мы позволили нашему приложению. Продолжение следует…

Введение в Node.js и запуск «Hello World!»

👁 133 просмотров

Node.js — это интерпретатор для языка JavaScript, который используется в виде серверного языка программирования ровно также, как и PHP, Ruby, Python и т.д. Так, зачем же надо было создавать еще один интерпретатор, если подобных уже немало? А затем, что это совсем необычная технология взаимодействия клиент-сервер. Основное отличие данного интерпретатора в том, что она позволяется быстро исполнять код JavaScript на стороне сервера и мгновенно ассинхронно передавать ответ на запросы удаленных пользователей. По сути дела, Node.js  — движок V8, на котором работает браузер Chrome от Google, который переделали в сервер, добавив к нему необходимые модули работы с файловой системой, с HTTP — запросами, c сокетами и т.д.

Установка Node.js

Скачать и установить Node.js — это проще простого. Для этого заходим на официальный сайт проекта и жмем на зеленную кнопку INSTALL. После скачивания установка происходит в стандартном режиме, если у вас Windows x64, то установщик по умолчанию установит в Node.js  в папке C:\Program Files\nodejs\, соглашаемся с установщиком

node-js-default-path

После установки мы сможем передавать команды управления для Node.js из командной строку, через ключевое слово node.

Запуск рабочего примера «Hello World!»

Давайте запустим пример работы в среде Node.js. Для этого нам нужно место, где будут храниться наши файлы сервера. Представьте это как папку хранения хостов Denvera или OpenServer, хотя для Node.js нет принципиальной разницы где будут храниться ваши исполняемые файлы, но мы условимся хранить наши файлы на диске C:/NodeServer/hostname.loc, а в папку hostname.loc добавим файл index.js со следующим сожержимым

var http = require('http');//Подключаем подуль приема и отправки по протоколу Http
//Создаем объект нового сервера
http.createServer(function (req, res) {
  //Передаем заголовок
  res.writeHead(200, {'Content-Type': 'text/plain'});
  //Выводим запись
  res.end('Hello World\n');
}).listen(1337, '127.0.0.1');//Указываем адрес хоста
//Уведомляем в консоли о том, что запущен наш сервер
console.log('Server running at http://127.0.0.1:1337/');

После записи данного кода сохраняем данный файл и закрываем, переходим в консоль и набираем команду исполнения данного файла с указанием пути

node C:/NodeServer/hostname.loc/index.js

start-node-js-hello-worldЕсли все удачно установилось и запустилось, то увидите следующее собщение

start-node-js-hello-world-result

Теперь отрываем браузер и вводим адрес http://127.0.0.1:1337/ и убеждаемся, что у нас вышла долгожданная строка

node-js-result-in-browser-hw

 

На этом все, Node.js установлен и готов для дальнейшей работы.

 

Часть 1. Написание игры «Крестики и нолики» под Android. Подготовка инструментов

👁 187 просмотров

Итак, с сегодняшнего дня начнем цикл статей, которые пошагово разъяснять как написать свою собственную игру на примере классической игры «Крестики и нолики», другое забавное название для данной игры «Tic-Tac-Toe» 🙂  . Плюс ко всему этому попытаемся загрузить, после написания, на Google Play, чтобы игроманы смогли оценить наше детище 🙂 .

В данной части разъясним что нам необходимо для полноценной разработки игры:

  • Android Studio — полнофункциональный официальный инструмент разработки для кроссплатформенной разработки приложений для Android, который еще содержит и эмулятор для виртуального тестирования программ;
  • JDK — набор инструментов для разработки программ, работающих на Java. Наш инструмент Android Studio работает на основе Java машины, поэтому нам необходимо ее установить на компьютер, прежде чем устанавливать Android Studio;
  • Inkscape — векторный редактор для рисования наших ресурсов, таких как кнопки, иконки, фоны и т.д. Это необязательное условие, можете использовать другой, на котором набита рука.

1. Установка JDK

Установка JDK ничем не отличается от установки любой другой программы. Скачиваем отсюда и я не буду вдаваться в дебри установки, потому что нет никаких сложностей. Единственное, если у вас Windows, после установки откройте командную строку и введите команду

java -version

Если установка удачная, то должна вернуть версию программы

 

java-console-version-result

если это не так, то следует открыть «переменные среды» вашего компьютера

java-variable-java-home

 

и создать новую пременную JAVA_HOME с параметром пути, где установлена ваша JDK и все — JDK у вас установлена, перейдем к следующему пункту.

2. Установка Android Studio

Скачать Android Studio можно на официальном сайте. Установка Android Studio не должно иметь затруднений, вам лишь необходимо указать место для установки и совершать действия следуя подсказкам установщика. После установки Android Studio нам необходимо настроить программу для дальнейшей разработки — будет во второй части.

3. Установка Inkscape

Считаю, что данная бесплатная программа ничем не хуже платных и нашпигованных и платных Adobe Illustrator, CorelDraw… Не все при деньгах и не все без совести, чтобы пользоваться кряками 🙂 .

Заключение

В данной статье рассмотрели инструменты, которые нам пригодятся для разработки простой игры «Крестики и нолики» под Android. Следуйте в ногу обновлениям и скачивайте последние версии против привычности работы на старых 🙂 . В следующей части рассмотрим Android Studio по подробнее и займемся настройкой и запуском тестовой программы.

3. WEB — графика с Three.js. Создание плоскости

👁 0 просмотров

Плоскость в компьютерной графике можно представить как сетку бесконечно малой толщины. На сетку можно наложить текстуру, материал и раскрасить цветом. Для того, чтобы нарисовать и вывести сетку в Three.js нам необходимо сделать не так много действий — передать объект THREE.MeshBasicMaterial с параметрами в рендер, присвоив объекту свойства текстуры, материала или цвета. В данной статье просто разукрасим нашу плоскость, передав материал. Тему текстурирования затронем в последующих статьях. И так, код в script.js ничем не отличается от кода в предыдущих статьях, кроме как кода в разделе создания объекта

window.onload = init;
function init(){
	//--------------Создаем в дереве DOM элемен для вывода на экран-------
	container = document.createElement("div");
	document.body.appendChild(container);
	
	//--------------Общие переменные--------------
	var scene, camera, render;
	
	//--------------Инициализация общих переменных---------
	scene = new THREE.Scene();//Сцена
	camera = new THREE.PerspectiveCamera(65, window.innerWidth/window.innerHeight, 0.1, 2000);//Перспективаная проекция камеры. Принимает 3 параметра(масштаб, пропорция, точка 0 в близи, точка 0 в дали
    camera.position.x = 150;//Позиция камеры по x
	camera.position.z = 600;//Позиция камеры по y
	render = new THREE.WebGLRenderer();//Рендеринг
	render.setSize(window.innerWidth, window.innerHeight);//Инициализация рендерера
	
	//--------------Создаем объект-------------------
	var planeGeometry = new THREE.PlaneGeometry(window.innerWidth, window.innerHeight);//Производная фигура
	planeGeometry.applyMatrix(new THREE.Matrix4().makeRotationX(-Math.PI/3));//Поворачиваем вокуруг оси X
	var planeMaterial = new THREE.MeshBasicMaterial({color:0xe0e0e0});//Устанавливаем материал
	var plane = new THREE.Mesh(planeGeometry, planeMaterial);//Создаем линию из созданной геометрии
	//--------------Добавление вывод-----------------
	scene.add(plane);//Добавляем объект на сцену
	render.render(scene, camera);//Добавляем сцену и камеру в рендер
	container.appendChild(render.domElement);//Добавляем рендер в DOM для вывода на экран
}

Ка видим все очень просто. Скрин работы данного примера

Threejs-3-pane
Весь код примера в архиве доступен здесь.

2. WEB — графика с Three.js. Рисование линий

👁 0 просмотров

Линия — это один из примитивов в Three.js, наверное как и в любой графической библиотеке, на основе которой можно построить составные объекты. После предыдущей статьи нам будет легче ориентироваться в методологии рисовании на Three.js. Рисовать линию действительно просто, надо только знать базовые основы математики такие как декартовы координаты и векторы. Давайте возьмем код из первой статьи, а именно файл script.js, остальное будет прежним,  и перепишем так, чтобы Three.js нам вывел обычную линию

window.onload = init;
function init(){
	//--------------Создаем в дереве DOM элемент для вывода на экран-------
	container = document.createElement("div");
	document.body.appendChild(container);
	
	//--------------Общие переменные--------------
	var scene, camera, render;
	
	//--------------Инициализация общих переменных---------
	scene = new THREE.Scene();//Сцена
	camera = new THREE.PerspectiveCamera(65, window.innerWidth/window.innerHeight, 0.1, 2000);//Перспективная проекция камеры. Принимает 3 параметра(масштаб, пропорция, точка 0 вблизи, точка 0 в дали
    camera.position.x = 150;//Позиция камеры по x
	camera.position.z = 600;//Позиция камеры по y
	render = new THREE.WebGLRenderer();//Рендеринг
	render.setSize(window.innerWidth, window.innerHeight);//Инициализация рендерера
	
	//--------------Создаем объект-------------------
	var lineGeometry = new THREE.Geometry();//Производная фигура
	lineGeometry.vertices.push(new THREE.Vector3(0, 0, 0));//Указываем вектор первой точки
	lineGeometry.vertices.push(new THREE.Vector3(0, 200, 0));//Указываем вектор второй точки
	var lineMaterial = new THREE.LineBasicMaterial({color:0xFFFFFF, linewidth:500});
	var line = new THREE.Line(lineGeometry, lineMaterial);//Создаем линию из созданной геометрии
	
	//--------------Добавление вывод-----------------
	scene.add(line);//Добавляем объект на сцену
	render.render(scene, camera);//Добавляем сцену и камеру в рендер
	container.appendChild(render.domElement);//Добавляем рендер в DOM для вывода на экран
}

Как видим все просто. Как видим из примера в Three.js существует понятие вектор и специальный объект для этого и при создании объекта будущей фигуры мы должны, передав вектору значения по координатным осям, передать нашему объекту в виде параметра метода вершин vertices() и он послужит для нас точкой, для определения второй точки поступаем тем же образом, а для того, чтобы указать Three.js, что мы хотим вывести именно линии, а не чисто 2 точки, то существует для этого специальный объект

THREE.Line(lineGeometry, lineMaterial)

который помимо объекта линии принимает еще и значение материала. Материал, в данном случае, принимает значения цвета и ширины линии. Пример работы показан на картинке ниже, а исходный код примера можете скачать здесь.
ThreejsLine-post-2

1. WEB — графика с Three.js. Общий принцип создания графики на Three.js

👁 471 просмотров

Three.js — это легкая библиотека для создания кроссбраузерных графических WEB приложений. Данная библиотека для отображения графики может использовать как Canvas из HTML5, как SVG для отображения 2D графики, так и WebGL для отображения 3D графики.

Примечание. Что плохо, так это то, что раз WebGL работает не во всех браузерах и типичным примером этого является отсутствие поддержки WebGL в JDK, посредством которых можно было бы создавать 3D программы на HTML5, из-за чего моя любимая платформа JavaFX не удовлетворяет меня в некоторых моих проектах 🙂 , но есть Canvas и SVG.

Последнюю версию Three.js можно скачать с репозитории GitHub или на официальном сайте Three.js. После распаковки архива у вас есть целый набор примеров и вспомогательных инструментов для работы с графикой. Следует отметить, что для работы некоторых примеров потребуется сервер, без которого они, наверняка не заработают в браузере, а так для начала достаточно обычного текстового редактора и навыков работы на HTML/JavaScript. Библиотека Three.js сама по себе кроссбраузерна, но если мы будем писать на голом JavaScript необходимо помнить, что пользовательский код на JavaScript должен быть оптимизирован под каждый браузер, а можно сделать еще легче — использовать кроссбраузерную библиотеку, такую как jQuery, но для простых примеров сойдет и обычный JavaScript 🙂 .

Прежде чем идти дальше, давайте разберем общую архитектуру построения Three.js — приложений и обозначим основные моменты, на которых следует акцентировать внимание. Ниже приведен рисунок, который отражает основной принцип. Все, что отображает Threejs — это либо объекты Canvas, либо SVG или WebGL, а JavaScript выступает связующим звеном между DOM HTML — интерфейса страницы — 6 и элементами сцены — 1 Three.js. В простейшем случае сцена может состоять из самой области вывода — 1, она так и называется — сцена(Scene), из камеры — 2, из объектов, которых мы хотим отобразить — 3 и освещения — пока этого всего нам достаточно, чтобы рассмотреть простейшие примеры. После окончания построения сцены начинается этап рендеринга(прорисовки) — 4 и приема пользовательских команд для изменения состояния элементов сцены — 1.

threejs-1

Итак, что нам нужно сделать для того, чтобы отобразить простой объект в окне браузера:

  • создать сцену;
  • создать рендер;
  • создать освещение;
  • создать камеру;
  • создать объекты;
  • добавить освещение, камеру и объекты на сцену;
  • добавить сцену на рендер;

Давайте теперь приступим к процессу кодирования и для этого нам, в первую очередь, будет необходимо создать скелет пустого HTML с названием index.html

<html lang="ru">
        <head>
            <meta charset="utf-8" />
            <title>Графика на Three.js</title>
            <script src="js/three.min.js"></script>
            <script src="js/script.js"></script>
        </head>
    <body>
    </body>
</html>

В разделе head мы подключаем библиотеку Three.js и наш рабочий скрипт, который мы назвали script.js, обеих закинули в папку js, из которого мы их читаем. Библиотека Three.js находиться в скачанном архиве в папке build, причем есть компрессивная и полная версия, разницы нет, кроме как в размере файла. В компрессивном отсутствуют лишние пробелы и символы. Итак, мы подключили файлы библиотеки и нашего рабочего скрипта, теперьпосмотрим на наш файл script.js

 

window.onload = init;
function init(){
	//--------------Создаем в дереве DOM элемен для вывода на экран-------
	container = document.createElement("div");//Создаем тег контейнера для вывода
	document.body.appendChild(container);//Добавляем в DOM HTML - документа
	
	//--------------Общие переменные объектов--------------
	var scene, camera, render;
	
	//--------------Инициализация общих переменных---------
	scene = new THREE.Scene();//Сцена
	camera = new THREE.PerspectiveCamera(65, window.innerWidth/window.innerHeight, 0.1, 2000);//Перспективаная проекция камеры. Принимает 3 параметра(масштаб, пропорция, точка 0 в близи, точка 0 в дали
    camera.position.x = 150;//Позиция камеры по x
	camera.position.z = 600;//Позиция камеры по y
	render = new THREE.WebGLRenderer();//Рендеринг
	render.setSize(window.innerWidth, window.innerHeight);//Инициализация рендерера
	
	//--------------Создаем объекты-------------------
	var cubeGeometry = new THREE.BoxGeometry(100, 100, 100);//Производная фигура. Первые 3 параметра - размеры, вторые - количество сегментов по 3-м граням. Последние параметры нужны для исключения деформации вывода текстуры при перспективе
	var cubeMaterial = new THREE.MeshNormalMaterial();//Устанавливаем материал
	var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);//Создаем линию из созданной геометрии
	scene.add(cube);//Добавляем объект на сцену
	
	var cylinderGeometry = new THREE.CylinderGeometry(50, 50, 200);//Производная фигура
	var cylinderMaterial = new THREE.MeshNormalMaterial();//Устанавливаем материал
	var cylinder = new THREE.Mesh(cylinderGeometry, cylinderMaterial);//Создаем линию из созданной геометрии
	cylinder.position.x = 200;//Перемещаем от начала координат по оси X
	scene.add(cylinder);//Добавляем объект на сцену
	
	//--------------Добавление вывод-----------------
	render.render(scene, camera);//Добавляем сцену и камеру в рендер после каждого цикла вызова
	
	container.appendChild(render.domElement);//Добавляем рендер в DOM для вывода на экран
}

В итоге должен получиться вот такой вот результат

Threejs-1-screen-1Пример вы можете скачать вот здесь.

Способы передачи параметров в Java

👁 124 просмотров

Как известно, в Java нет отдельных функций, как в С++/C/PHP/…, все реализуется в пределах класса и бывает случаи, когда необходимо передавать параметры методу или конструкции по умолчанию, или переменное количество параметров. В данной статье рассмотрим несколько способов реализации передачи необязательных параметров.

1.Способ перегрузки

void foo(String a,Integer b){//...}
void foo(String a){
foo(a,0);// где, 0 является необязательным параметром для b
}
foo("a",2); foo("a");

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

2. Использование Varargs

a) Все необязательные параметры имеют одинаковые типы:

void foo(String a, Integer... b){
  Integer b1 = b.length >0? b[0]:0;
  Integer b2 = b.length >1? b[1]:0;
  //...
  }
  foo("a");
  foo("a", 1, 2);

b) Типы необязательных параметров различные:

void foo(String a,Object... b){
     Integer b1 =0;
     String b2 ="";
     if(b.length >0){
        if(!(b[0] instanceof Integer)){
          throw new IllegalArgumentException("...");
        }
        b1 =(Integer)b[0];
     }
     if(b.length > 1){
       if(!(b[1] instanceof String)){
         throw new IllegalArgumentException("...");
       }
       b2 =(String)b[1];
       //...
     }
     //...
}  

foo("a");
foo("a",1);
foo("a",1,"b2");

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

3. Проверка на NULL

Для устранения ограничения передачи по типу можно использовать другой подход — проверка на передача значения на null и внутри тела функции организовать проверку : если передано null, то установить значения по умолчанию

void foo(String a,Integer b,Integer c){ 
         b = b !=null? b :0; 
         c = c !=null? c :0;
         //...
      }  
      foo("a",null,2);

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

4. Передача необязательного класса

Этот подход аналогичен предыдущему подходу, но использует guava необязательный класс в виде параметра, который имеет значения по умолчанию

void foo(String a,Optional bOpt){
         Integer b = bOpt.isPresent()? bOpt.get():0;
         //...
   }

   foo("a",Optional.of(2));
   foo("a",Optional.absent());

5.Использование шаблона Builder

Шаблон Builder используется для конструкторов и реализуется путем введения отдельного класса Builder

class Foo{
     privatefinalString a;
     privatefinalInteger b;
     Foo(String a,Integer b){
       this.a = a;
       this.b = b;
     }
     //...
}
class FooBuilder{
    privateString a ="";
    privateInteger b =0;
    FooBuilder setA(String a){
     this.a = a;
     return this;
    }
    FooBuilder setB(Integer b){
      this.b = b;
      return this;
    }
    Foo build(){returnnewFoo(a, b);
  }
}
Foo foo =new FooBuilder().setA("a").build();

6. Использование карт Maps

Когда количество параметров слишком большое и для большинство из них используют значения по умолчанию, то вы можете получить аргументы метода в виде карты, как имя/значение

void foo(Map<String,Object> parameters){
        String a ="";
        Integer b =0;
        if(parameters.containsKey("a")){
        if(!(parameters.get("a") instanceof Integer)){
           throw new IllegalArgumentException("...");
        }
        a =(String)parameters.get("a");
    }
    if(parameters.containsKey("b")){
     //... 
    }
     //...
}
foo(ImmutableMap.<String, Object>of("a", "a", "b", 2, "d", "value"));

 

Класс Stage в JavaFX

👁 143 просмотров

В данной статье попытаемся разобраться с классом Stage в JavaFX. Понимание принципа работы данного класса очень важно, так как это один из главных классов, который вплотную работает с графами(контролами JavaFX). Публичный класс Stage расширяет класс Window. 

Замечание. Так как, данное слово имеет множество омонимов, то мне так и не удалось ясно представить суть значения этого слова с английского на русский, но кандидатами могут быть следующие значения: этап, стадия, ступень, платформа. Но больше всего подходит платформа, на котором, в дальнейшем, строятся различные сцены с помощью класса Scene.

public class Stage extends Window

Класс Stage в JavaFX является верхнеуровневым контейнером.  Основной Stage конструирует платформу. В приложении могут быть сконструированы дополнительные платформы на основе Stage. Объект Stage должен быть сконструирован и модифицирован на основе потока JavaFX приложения. Большинство свойств данного класса предназначены только для чтения, потому что они могут быть изменены извне базовой платформы и, следовательно, не могут быть связанными.

Стили Stage

Stage платформа может иметь один из следующих стилей, которые являются статическими свойствами класса  StageStyle:

  • StageStyle.DECORATEDStage со сплошным белым задним фоном и стилизацией платформы;
  • StageStyle.UNDECORATED — Stage со сплошным белым задним фоном и без стилизацией платформы;
  • StageStyle.TRANSPARENT — Stage с прозрачным задним фоном и без стилизации платформы;
  • StageStyle.UTILITY — Stage со сплошным белым задним фоном и с минимальной стилизацией платформы;

Стили должны быть инициализированы перед тем, как платформа может быть выведена на экран с помощью метода show().  На некоторых платформах стилизации могут быть недоступны. К примеру, на некоторых мобильных или встраиваемых устройствах. В таких случаях запросы DECORATED или UTILITY окна могут быть установлены, но стили не будут показаны.

Родитель Stage

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

Модальность

Платформа имеет один из следующих модальностей:

  • Modality.NONE — платформа, которая не блокируется никаким другим окном;
  • Modality.WINDOW_MODAL — платформа, которую блокируют входные события, распространяемые от источника ко всем окнам из его родителя к его корню. Этот корень является ближайшим предком окна без родителя;
  • Modality.APPLICATION_MODAL — платформа, которую блокируют входные события, распространяемые от того же приложения, исключая для тех которые исходят из его иерархии потомков;

Когда окно блокировано модальной платформой Stage его Z-порядок по отношению к потомкам сохраняется и он не получает никаких событий и никаких событий активации окна, но продолжает анимировать и нормально визуализировать. Необходимо заметить, что показываемая модальная платформа не обязательно блокирует его вызвавший родитель.  Метод show() возвращает вывод непосредственно и независимо от модальности платформы.  Если необходимо блокировать родитель, вызвавший платформу Stage до скрытия или закрытия платформы, то необходимо использовать showAndWait().  Модальное окно может быть инициализировано перед тем, как платформа может быть выведена(показана).

Пример использования Stage

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class HelloWorld extends Application {

    @Override public void start(Stage stage) {
        Text text = new Text(10, 40, "Hello World!");
        text.setFont(new Font(40));
        Scene scene = new Scene(new Group(text));

        stage.setTitle("Welcome to JavaFX!"); 
        stage.setScene(scene); 
        stage.sizeToScene(); 
        stage.show(); 
    }

    public static void main(String[] args) {
        Application.launch(args);
    }
}