java 2d 教程_Java 2D开发技巧之“灯光与阴影”

a4c26d1e5885305701be709a3d33442f.png

Java 2D开发技巧之“灯光与阴影”

(2016-12-14 02:12:25)

标签:

杂谈

一、 引言

在本文中,我们将向你展示如何为扁平形状添加一种灯光效果以实现一种类3D外观。

也许你比较满意于自己的文字表达能力,但一幅图片往往能够产生更好的效果。对于图形处理来说,也是如此;不妨请参考一下图1中的两种图形。在本文中,我将向你展示如何克服左边扁平形状所带来的烦恼而以一种更为光滑的更具舒服感的形状代替。

图1.普通扁平形状与施加Java 2D效果后的形状

二、 实现技术分析

借助于适当的颜色,你可以使用本文中介绍的技术来模拟一种彩色光闪耀"越过"你的形状,从而生成一种微妙的发光效果。我们是如何实现这一效果的呢?请分析下面的代码;在方法drawBorderGlow上面的注释更为细致地介绍了关键实现方法:

import java.awt.geom.*;

import java.awt.image.*;

private

java视频教程

http://www.kgc.cn/java/list-1-6-9-9-0.shtml

static final Color clrHi=new Color(255, 229, 63);

private static final Color clrLo=new Color(255, 105, 0);

private static final Color clrGlowInnerHi=new Color(253, 239,

175, 148);

private static final Color clrGlowInnerLo=new Color(255, 209,

0);

private static final Color clrGlowOuterHi=new Color(253, 239,

175, 124);

private static final Color clrGlowOuterLo=new Color(255, 179,

0);

private Shape createClipShape {

float border=20.0f;

float x1=border;

float y1=border;

float x2=width - border;

float y2=height - border;

float adj=3.0f; //帮助圆化类锐的拐角

float arc=8.0f;

float dcx=0.18f * width;

float cx1=x1-dcx;

float cy1=0.40f * height;

float cx2=x1 dcx;

float cy2=0.50f * height;

GeneralPath gp=new GeneralPath;

gp.moveTo(x1-adj, y1 adj);

gp.quadTo(x1, y1, x1 adj, y1);

gp.lineTo(x2-arc, y1);

gp.quadTo(x2, y1, x2, y1 arc);

gp.lineTo(x2, y2-arc);

gp.quadTo(x2, y2, x2-arc, y2);

gp.lineTo(x1 adj, y2);

gp.quadTo(x1, y2, x1, y2-adj);

gp.curveTo(cx2, cy2, cx1, cy1, x1-adj, y1 adj);

gp.closePath;

return gp;

}

private BufferedImage createClipImage(Shape s) {

// 创建一半透明的中间图像,我们可以使用它来实现软修剪效果

GraphicsConfiguration gc=g.getDeviceConfiguration;

BufferedImage img=gc.createCompatibleImage(width, height,

Transparency.TRANSLUCENT);

Graphics2D g2=img.createGraphics;

//清除图像,这样所有的像素都具有零alpha

g2.setComposite(AlphaComposite.Clear);

g2.fillRect(0, 0, width, height);

// 把我们的修剪形状生成到图像上。注意,我们启动了

// 反走样功能以实现软修剪效果。你可以

//尝试注释掉启动反走样的这一行,那么

//你会看到通常的生硬的修剪效果.

g2.setComposite(AlphaComposite.Src);

g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

RenderingHints.VALUE_ANTIALIAS_ON);

g2.setColor(Color.WHITE);

g2.fill(s);

g2.dispose;

return img;

}

private static Color getMixedColor(Color c1, float pct1, Color

c2, float pct2) {

float clr1=c1.getComponents(null);

float clr2=c2.getComponents(null);

for (int i=0; i < clr1.length; i ) {

clr1[i]=(clr1[i] * pct1) (clr2[i] * pct2);

}

return new Color(clr1[0], clr1[1], clr1[2], clr1[3]);

}

//下面是实现技巧:为了实现发光效果,我们开始使用一种"内部"颜色粗笔

//和笔划需要的形状。然后,我们不断地把笔变细,

//并且不断地移向"外部"颜色,

//并且不断地提高颜色的不透明度以便使其朝向形状的内部看上去暗淡。

//我们使用已经生成到我们的目的图像上的"修剪形状",这样以来,

//SRC_ATOP规则就会修剪在我们的形状外部的笔划部分。

private void paintBorderGlow(Graphics2D g2, int glowWidth)

{

int gw=glowWidth*2;

for (int i=gw; i >=2; i-=2) {

float pct=(float)(gw - i) / (gw - 1);

Color mixHi=getMixedColor(clrGlowInnerHi, pct,clrGlowOuterHi,

1.0f - pct);

Color mixLo=getMixedColor(clrGlowInnerLo, pct,clrGlowOuterLo,

1.0f - pct);

g2.setPaint(new GradientPaint(0.0f, height*0.25f, mixHi,0.0f,

height, mixLo));

//g2.setColor(Color.WHITE);

g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,

pct));

g2.setStroke(new BasicStroke(i));

g2.draw(clipShape);

}

}

Shape clipShape=createClipShape;

//Shape clipShape=new Ellipse2D.Float(width/4, height/4, width/2,

height/2);

//把背景清除为白色

g.setColor(Color.WHITE);

g.fillRect(0, 0, width, height);

//设置修剪形状

BufferedImage clipImage=createClipImage(clipShape);

Graphics2D g2=clipImage.createGraphics;

//使用渐变填充形状

g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

RenderingHints.VALUE_ANTIALIAS_ON);

g2.setComposite(AlphaComposite.SrcAtop);

g2.setPaint(new GradientPaint(0, 0, clrHi, 0, height,

clrLo));

g2.fill(clipShape);

//应用边界发光效果

paintBorderGlow(g2, 8);

g2.dispose;

g.drawImage(clipImage, 0, 0, null);

注意,在上面的例子中,我把一些可选的代码行加上了注释。你可以去掉这些注释并观察它们对生成效果的影响。

注意:聪明的读者可以已经注意到,上面应用于paintBorderGlow方法中的技术也可以用于沿形状添加一种投影效果。你不妨先猜测一下如何实现这一点……好,时间到!不是在形状的顶部生成边缘(记住,修剪能够确保笔划仅影响形状的内部),我们可以预先绕着我们的形状生成一种可变的灰色边界。这意味着,阴影笔划将出现在我们的形状的外边;阴影笔划的内部将会通过我们的形状而有效地生成。

你可以把下面的一些代码插入到上面的例子中以便在相应的同一个形状上添加一种阴影边界效果:

private void paintBorderShadow(Graphics2D g2, int shadowWidth)

{

g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

int sw=shadowWidth*2;

for (int i=sw; i >=2; i-=2) {

float pct=(float)(sw - i) / (sw - 1);

g2.setColor(getMixedColor(Color.LIGHT_GRAY, pct,Color.WHITE,

1.0f-pct));

g2.setStroke(new BasicStroke(i));

g2.draw(clipShape);

}

}

//在我们绘制形状的其它部分前应用边界的阴影效果。

paintBorderShadow(g, 6);

下面图2是最终的结果图像:

图2.施加Java 2D效果后的最终结果形状

三、 小结

在本文中,我仅向你介绍了快速地添加一种阴影效果的方法。如果有时间的话,我很可能会使用一种亮灰色和一种非线性斜面来实现一种更为真实的效果。还要注意的是,这里介绍的仅是使用Java

2D实现投影效果的许多方法之一。注意,Romain在他的博客中已经讨论了多种不同的投影实现方法。SwingLabs成员在SwingX工程中也提供了一种DropShadowBorder实现;而DropShadowPanel当前正在开发中。

分享:

a4c26d1e5885305701be709a3d33442f.png喜欢

0

a4c26d1e5885305701be709a3d33442f.png赠金笔

加载中,请稍候......

评论加载中,请稍候...

发评论

登录名: 密码: 找回密码 注册记住登录状态

昵   称:

评论并转载此博文

a4c26d1e5885305701be709a3d33442f.png

发评论

以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/344497.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java连接到mysql_[操作系统]Java如何连接到MySQL数据库的

[操作系统]Java如何连接到MySQL数据库的0 2016-05-01 15:00:15下载&#xff1a;mysql-connector-java-5.1.38.tar.gzhttp://dev.mysql.com/downloads/connector/j/tar zxvfmysql-connector-java-5.1.38.tar.gz解压后zhouspubuntu:~/Downloads$cd ./mysql-connector-java-5.1.38…

Spark Run本地设计模式

现在&#xff0c;许多Spark应用程序已成为遗留应用程序&#xff0c;很难在本地进行增强&#xff0c;测试和运行。 Spark具有很好的测试支持&#xff0c;但仍有许多Spark应用程序不可测试。 当您尝试运行一些旧的Spark应用程序时&#xff0c;我将分享一个常见错误。 Exceptio…

mysql导入创建表空间_oracle创建表空间 导入数据库

oracle2 然后是创建表空间创建表空间需要创建两个一个临时表空间 一个表空间--创建表空间create tablespace abc datafile ‘D:\tablespce\LANDHIGH_SFTMS.dbf‘ size 500m;--创建用户并指定表空间create user admin identified by admin default tablespace abc quota 500m …

Java线程的不同状态

介绍 在Java中&#xff0c;线程可以具有状态。 Thread.State枚举定义Java线程可以具有的不同状态。 该枚举定义了以下值– 新 可运行 已封锁 等候 TIMED_WAITING 已终止 在接下来的部分中&#xff0c;我将简要概述这些状态以及它们之间的可能过渡。 Java线程的状态 新 …

IDE日志分析方法pt。 2

介绍 在第一部分中&#xff0c;我解释了日志分析的理论方法&#xff0c;我认为这对维持工程师是最合适的。 这位工程师不需要在日志出现时立即对其进行分析&#xff0c;而是专注于对复杂问题的深入分析。 在第二部分中&#xff0c;我将展示一个复杂的模板可以涵盖许多搜索场景&…

java 面试指南_Java面试参考指南–第1部分

java 面试指南JAVA面向对象的概念 Java in基于面向对象的概念&#xff0c;它允许更高级别的抽象以实际方式解决任何问题。 面向对象的方法将实际对象中的问题解决方案概念化&#xff0c;更易于在整个应用程序中重用。 例如椅子&#xff0c;风扇&#xff0c;狗&#xff0c;电脑…

创建一个安全的Spring REST API

“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕&#xff1f; 尝试使用Okta API进行托管身份验证&#xff0c;授权和多因素身份验证。 “如果有用&#xff0c;它将被修改。” 这些智慧之言来自我的QA老师&#xff0c;他们…

java并发编程十 原子累加器和Unsafe

文章目录 原子累加器cas 锁原理之伪共享 UnsafeUnsafe CAS 操作 原子累加器 累加器性能比较 private static <T> void demo(Supplier<T> adderSupplier, Consumer<T> action) {T adder adderSupplier.get();long start System.nanoTime();List<Thread…

具有ELK的APIGEE API网关日志管理(Elastic Search,Logstash和Kibana)

在本文中&#xff0c;我们将看到如何使用 Elastic Search &#xff0c; Logstash 和 Kibana 管理APIGEE API网关生成的日志 。 下图突出显示了日志数据如何流经ELK堆栈以进行数据可视化和监视。 作为API网关的一部分&#xff0c;我们将使用MessageLogging策略在代理流&#xf…

java 80_【JavaWeb】80:js基础详解

今天是刘小爱自学Java的第80天。感谢你的观看&#xff0c;谢谢你。话不多说&#xff0c;开始今天的学习&#xff1a;JavaScript是一门编程语言&#xff0c;但凡是编程语言&#xff0c;其在基本语法上都是大同小异的。我们学了Java&#xff0c;那么再学习其它语言时&#xff0c;…

php manager iis 8,PHPManager2下载

PHP Manager 2.x 理论支持win10,win8,win7,Windows Server2008,Windows Server2012,Windows Server2012R2,Windows Server2016,,Windows Server2019与其对应的IIS版本.--PHP Manager 2.4 for IIS10,IIS8,IIS7 下载简单但功能强大具有独特功能的工具&#xff0c;可以处理所有细节…

企业知识库:从信息管理到知识创新的转变

在当今这个信息爆炸的时代&#xff0c;企业知识库的建设已经成为了企业持续发展的重要基石。从传统的信息管理到现代的知识创新&#xff0c;企业知识库的角色和功能也在不断地演变和升级。本文将探讨企业知识库的发展历程&#xff0c;以及如何实现从信息管理到知识创新的转变。…

php封装的数据库操作文件夹,PHP中对数据库操作的封装_php

现在我们把其封装在dbfz.inc中&#xff0c;其设计如下&#xff1a;$#60;?class dbInterface{ var $dbID1; //用于确定当前操作的数据库&#xff0c;当dbID为1代表mysql,当为 2代表 SQL Server&#xff0c;为3时为ODBC或其它。var $dbHost; //数据库所在主机域名var $dbUsernam…

Spring框架架构

这是Spring Framework Architecture的概述。 了解Spring Framework的各个组成部分如何组织以及如何相互联系。 如果您想了解什么是Spring框架及其功能&#xff0c;请阅读Spring框架简介 。 总览 Spring是一个模块化框架 。 它不是作为一个软件包或多个模块捆绑在一起的。 各种…

php中n12br,PHP常见字符串操作函数与用法总结

一、字符串的格式化1、字符串的格式化trim()函数可以去除字符串的开始位置和结束位置的空格&#xff0c;并将结果字符串返回&#xff0c;默认情况下去除的字符是换行符和回车符(\n和\r),水平和垂直制表符(\t和X0B)ltrim()函数只从字符的开始处(左边)去除空格rtrim()函数只从函数…

面向切面编程应用_应用面向方面的编程

面向切面编程应用1.引言 面向方面编程的主要目标是将跨领域关注点分离。 当我们谈论跨领域的关注时&#xff0c;我们指的是在我们的系统或应用程序中的多个地方使用的通用功能。 这些概念包括&#xff1a; 记录中 交易管理 错误处理 监控方式 安全 实现这种分离的方法是将…

centos 安装php扩展gd,linux(centos)下为php添加添加GD扩展

yum -y install libjpeglibjpeg-devel libpng libpng-devel freetype freetype-devel 安装依赖库yum -y install libjpeg-devel1.首先切换到php源码目录&#xff1a;/usr/local/php-5.6.29/ext/gd2.利用phpize生成gd扩展文件,/usr/local/php/bin/mipsel-linux-phpize, ls 或者 …

弹簧启动执行器教程

朋友您好&#xff0c;在本教程中&#xff0c;我们将学习弹簧执行器及其所有功能。 1.什么是弹簧执行器&#xff1f; 2.如何在Maven项目或Gradle项目中添加弹簧执行器&#xff1f; 3.创建一个具有Spring Actuator依赖项的Spring Boot项目。 4.使用弹簧执行器端点监视应用程序…

php xls 邮件,PHPMailer发送邮件

PHPMailer是一个封装好的PHP邮件发送类&#xff0c;支持发送HTML内容的电子邮件&#xff0c;以及图片附件&#xff0c;前提要设置好邮件服务器就能实现邮件发送功能。HTML首先我们先放置一个收件箱的输入框和一个发送邮件按钮&#xff1a;收件人&#xff1a;jQuery$(function()…

引导性GCP:带有Google Cloud Pub / Sub的Spring Cloud Stream

我最近在Sprint Central的工程博客上阅读了Josh Long的Bootiful GCP系列 &#xff0c;特别喜欢关于使用Google Cloud的Pub / Sub的第四部分 。 我受到该系列的启发&#xff0c;同时我还在为我的一个新项目评估Spring Cloud Stream。 我以为&#xff0c;我会继续讨论乔希&#x…