Небольшое руководство, которое покажет вам, как создавать привлекательные рисунки Java2D без хлопот, благодаря одному из конструкторов Groovy: GraphicsBuilder.
Вступление
Java2D был доступен в течение многих лет, с тех пор, как вышел Swing, по-прежнему создавать привлекательные и хорошо отрисованные чертежи — непростая задача для всех (если только вы не являетесь французом по прозвищу Gfx). Именно эту проблему и решает GraphicsBuilder. Если в последние годы вы жили под скалой (или были отключены от сети), динамические языки заняли центральное место, одним из таких языков является Groovy. Groovy — это один из многих языков, которые работают на JVM, но его отличает то, что он легко интегрируется с языком Java и самой платформой Java.
Поскольку Groovy является динамическим языком, вы можете воспользоваться преимуществами необязательной типизации, иными словами, утиная типизация является реальностью, таким образом сокращая значительное количество строк кода, если вы знаете, что делаете, но если вы все еще слишком привязаны к типам Не волнуйтесь, Groovy тоже доволен типами. Еще один интересный момент в Groovy — это то, что у него есть возможности метапрограммирования, что означает, что вы можете расширить поведение класса во время выполнения, даже если это конечный класс, такой как java.lang.String (не беспокойтесь о его безопасности). Благодаря этим двум фактам и некоторым другим функциям Groovy позволяет реализовать шаблон компоновщика простым, но элегантным способом, и именно здесь в игру вступает GraphicsBuilder.
GraphicsBuilder в некотором смысле представляет собой набор узлов, где каждый узел представляет операцию рисования, такую как фигуры, краски, преобразования и изображения. Чертеж затем составляется из группы операций, составленных компоновщиком в порядке, в котором они определены, с учетом того, что некоторые операции допускают вложение других, что обеспечивает хорошую структурированную иерархию операций. Это может показаться немного знакомым из Swing, поскольку каждый компонент является звеном в цепочке иерархии. Java2D делает всю свою магию с экземпляром Graphics (или Graphics2D), который позволяет рисовать фигуры, устанавливать цвета и цвета, обрезать поверхность рисования до определенной формы или границ и т. Д .; То, что обеспечивает GraphicsBuilder — это тонкий слой абстракции над этими основными операциями.
Давайте начнем, наша цель нарисовать следующее изображение
Рисование фона
Первым шагом было бы нарисовать фон, заметив, что это прямоугольник со скругленными углами, который является одной из основных форм, которые предоставляет Java2D. Позвольте мне показать вам код для этого
// define some useful variables
def width = 300
def height = width*3/4
def gb = new GraphicsBuilder()
// group all operations in the same set
def graphicsOperation = gb.group {
// translate the whole group to an arbitrary position
transformations { translate( x: 10, y: 10 ) }
// turn on antialiasing
antialias( 'on' )
// base background shape, it will be reused for clipping
rect( x: 0, y: 0, width: width, height: height, arcWidth: 40, arcHeight: 40,
asShape: true, id: 'background' )
// clip everything outside of the background shape
clip( background )
// draw the actual background
draw( background, borderColor: false ){
// a nice downward diagonal gradient from 'blue' to 'cyan'
gradientPaint( x1: 0, y1: 0, x2: 50, y2: 50,
color1: color('blue'), color2: color('cyan') )
}
}
Несколько вещей должны быть объяснены здесь. Сначала мы определяем некоторые полезные переменные для ширины и высоты изображения, так как они будут использованы повторно позже, затем мы группируем все операции в одном наборе, что облегчает их обработку. Глобальное преобразование применяется ко всей группе, поэтому все вложенные операции будут иметь смещение 10 пикселей по оси x и 10 пикселей по оси y. Сглаживание включено, чтобы получить плавные края, затем создается базовая форма фона, но она не рисуется сразу (благодаря asShape = true), потому что мы будем использовать эту форму дважды: во-первых, чтобы обрезать область рисования, а во-вторых, нарисовать реальный фон. Вы можете заметить, что borderColor формы bakground имеет значение false (это также могло бы быть ‘none’), что предотвращает прорисовку границы,так как это может привести к появлению нежелательных артефактов рендеринга, как видно на следующих изображениях, первое имеет borderColor = false, а второе имеет borderColor по умолчанию (обычно черный).
[img_assist | nid = 286 | title = | desc = | link = none | align = middle | width = 330 | height = 275] [img_assist | nid = 287 | title = | desc = | link = none | align = middle | ширина = 330 | высота = 275]
Рисование радиальных линий
На следующем шаге рисуем радиальные линии. Совершенно очевидно, что нам нужно было бы выполнить некоторые математические расчеты с углами и радиусами, поскольку Java2D не предоставляет быстрой формы или средства для выполнения такого рода рисования из коробки, но не волнуйтесь, это делает GraphicsBuilder. Форма лучей требует, чтобы центр (cx, cy) и радиус были минимальными свойствами, но вы можете установить другие как количество лучей, которые будут нарисованы (лучи), экстент угла на луч (экстент) и начальный угол ( полезно для быстрых поворотов). Добавьте следующий код после операции рисования фона
rays( cx: width/2, cy: height/2, radius: width*2, rays: 30, extent: 0.4, borderColor: false ){
colorPaint( color('black').derive(alpha:0.5) )
}
Что дает следующее изображение
Обратите внимание, что в окончательном изображении есть подсказка об изменении цвета, исходящая из центра, мы будем использовать радиальный градиент для достижения этого эффекта, который служит введением в мультикраски. Как следует из названия, мультикраски — это набор красок, которые можно наносить одновременно на одну фигуру, в этом случае мы бы хотели, чтобы базовый цвет и радиальный градиент были применены к лучам. Радиальный градиент требует центра (cx, cy), радиуса и, по крайней мере, двух определений стопа; остановка заботится о настройке, где в градиенте будет использоваться цвет. Мы обновляем форму лучей с помощью следующего кода
rays( cx: width/2, cy: height/2, radius: width*2, rays: 30, extent: 0.4, borderColor: false ){
multiPaint {
colorPaint( color('black').derive(alpha:0.5) )
radialGradient( cx: width/2, cy: height/2, radius: width/3 ){
stop( offset: 0, color: color('white').derive(alpha:0.5) )
stop( offset: 1, color: color('white').derive(alpha:0.0) )
transformations { translate( x: 10, y: 10 ) }
}
}
}
Что дает нам следующий результат
Рисование звезды
Ах, звезды, к сожалению, Java2D не предоставляет им базовую форму, не было бы неплохо, если бы это сделал GraphicsBuilder? конечно, это так! Звезды имеют те же свойства, что и лучи, с той лишь разницей, сколько точек вы хотели бы получить, а также внутренний и внешний радиусы. Следующий код должен сделать свое дело
star( cx: width/2, cy: height/2, or: 30, ir: 15, borderColor: 'white' ){
basicStroke( width: 2 )
multiPaint {
colorPaint( color('white') )
radialGradient( cx: (width/2)+10, cy: (height/2)-10, radius: 50 ){
stop( offset: 0, color: color('cyan').derive(alpha:0.4) )
stop( offset: 1, color: color('gray').derive(alpha:0.0) )
transformations { translate( x: 10, y: 10 ) }
}
}
}
Мультикраски снова используются для рисования основного белого цвета и радиального градиента на основе голубого / серого, теперь для радиальных бликов звезды, мы снова будем использовать форму лучей с более длинным экстентом и радиальным градиентом в качестве краски. Основные моменты должны быть нарисованы перед звездой, эффективно отрисовывая их позади звезды.
// star highlights
rays( cx: width/2, cy: height/2, radius: height*4/5, rays: 5, extent: 0.75,
angle: 45-(360/10*0.5), borderColor: false ){
radialGradient( cx: (width/2)+10, cy: (height/2)-10, radius: height/2 ){
stop( offset: 0, color: color('white').derive(alpha:0.5) )
stop( offset: 1, color: color('gray').derive(alpha:0.0) )
transformations { translate( x: 10, y: 10 ) }
}
}
Обратите внимание, что для лучей установлено значение 0,75 (оно колеблется от 0 до 1), а также что угол был также изменен.
Рисование текста
Мы находимся на последнем шаге, рисуем слова «Groovy» и «Zone», у них снова хорошие градиенты и белая рамка. Но здесь есть хитрость, вместо того, чтобы устанавливать значение ширины границы, белая граница — фактически тот же самый текст, нарисованный позади, это потому, что шрифт рисует все контуры букв, и нас интересует только контур слова. Итак, давайте сначала нарисуем базовый текст
def fontFile = new File("WHOOPASS.TTF")
font( Font.createFont(Font.TRUETYPE_FONT,fontFile).deriveFont(58.0f) )
text( text: 'Groovy', x: (width/5)-5, y: height/10, borderColor: false ){
multiPaint {
colorPaint( color('blue') )
linearGradient( x2: 0, y2: 50 ){
stop( offset: 0, color: color('cyan').derive(alpha:0.3) )
stop( offset: 1, color: color('cyan').derive(alpha:0.8) )
}
}
}
text( text: 'Zone', x: (width/4)+10, y: height*7/10, borderColor: false ){
multiPaint {
colorPaint( color('blue') )
linearGradient( x2: 0, y2: 50 ){
stop( offset: 0, color: color('cyan').derive(alpha:0.8) )
stop( offset: 1, color: color('cyan').derive(alpha:0.3) )
}
}
}
Теперь, чтобы сделать последний штрих, давайте нарисуем белый текст перед синим, и все готово. Просто вставьте следующий фрагмент между определением шрифта и первой текстовой операцией
text( text: 'Groovy', x: (width/5)-5, y: (height/10), borderWidth: 6,
borderColor: 'white' )
text( text: 'Zone', x: (width/4)+10, y: height*7/10, borderWidth: 6,
borderColor: 'white')
Вот и все! Не стесняйтесь играть с цветами и другими формами. GraphicsBuilder включает базовое приложение с именем GraphicsPad, которое поможет вам создавать свои собственные рисунки. Эти рисунки можно экспортировать в автономные сценарии, аналогичные тем, которые используются для создания рисунков, которые вы видите в этом руководстве. Документальный сайт GraphicsBuilder содержит больше информации о доступных фигурах, красках, операциях и других вещах, которые вы можете сделать с GraphicsBuilder прямо сейчас.
Вы найдете полный скрипт в разделе ресурсов, просто не забудьте удалить расширение .txt или загрузить его с GroovyConsole и запустить его.
Надеюсь, вам понравилось читать этот урок так же, как и я.