来,让我们一起画个印章吧

这几天发现有哥们在介绍如何画出swing,正好我也受命做一个简单的印章.今天完工,抽出来一个典型的凑下热闹,让大家乐呵乐呵.

还是老习惯,不多说,上代码和图片.

 

主类:

package i2534.iteye.com;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Stroke;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import javax.imageio.ImageIO;

/**
 * 印章类.保存印章必须的参数和绘制方法.
 * 
 * @author i2534
 * 
 */
public class Seal {
	/**
	 * 印章名称距中心点偏移量,按照y轴方向
	 */
	private int nameOffset = 50;
	/**
	 * 印章宽度
	 */
	private int width = 230;
	/**
	 * 印章高度
	 */
	private int height = 230;
	/**
	 * 印章中心标志(默认为五角星)外接圆半径
	 */
	private float radius = 30;
	/**
	 * 印章所属单位的起始角度,以6点钟方向为中心,向两个方向平均扩展
	 */
	private float firmAngle = 120;
	/**
	 * 印章名称
	 */
	private String name = "取钱专用章";
	/**
	 * 印章名称颜色
	 */
	private Color nameColor = Color.RED;
	/**
	 * 印章所属单位
	 */
	private String firm = "中国人民银行";
	/**
	 * 印章所属单位颜色
	 */
	private Color firmColor = Color.RED;
	/**
	 * 印章名称字体信息
	 */
	private Font nameFont = new Font("宋体", Font.PLAIN, 16);
	/**
	 * 印章所属单位字体信息
	 */
	private Font firmFont = new Font("宋体", Font.PLAIN, 24);
	/**
	 * 单位字体的宽度缩放比率(百分比).此参数可以使字体看起来瘦长
	 */
	private float firmScale = 1.0F;
	/**
	 * 边框线宽
	 */
	private float borderWidth = 5F;
	/**
	 * 边框颜色
	 */
	private Color borderColor = Color.RED;
	/**
	 * 印章标记(默认为五角星)线宽
	 */
	private float signBorderWidth = 3F;
	/**
	 * 印章标记颜色
	 */
	private Color signBorderColor = Color.RED;
	/**
	 * 印章标记填充颜色
	 */
	private Color signFillColor = Color.RED;

	public void draw(Graphics2D g2d) {
		// 把绘制起点挪到圆中心点
		g2d.translate(width / 2, height / 2);

		Stroke stroke = g2d.getStroke();// 旧的线性
		// 填充五角星
		Polygon polygon = getPentaclePoints(radius);
		if (signFillColor != null) {
			g2d.setColor(signFillColor);
			g2d.fill(polygon);
		}

		// 绘制五角星边框
		g2d.setStroke(new BasicStroke(signBorderWidth));
		g2d.setColor(signBorderColor);
		g2d.draw(polygon);

		// 绘制印章边框
		g2d.setColor(borderColor);
		g2d.setStroke(new BasicStroke(borderWidth));
		g2d.drawOval(-width / 2, -height / 2, width, height);
		g2d.setStroke(stroke);

		// 绘制印章名称
		g2d.setFont(nameFont);
		g2d.setColor(nameColor);
		FontMetrics fm = g2d.getFontMetrics();
		int w = fm.stringWidth(name);// 名称宽度
		int h = fm.getHeight();// 名称高度
		int y = fm.getAscent() - h / 2;// 求得中心线经过字体的高度的一半时的字体的起绘点
		g2d.drawString(name, -w / 2, y + nameOffset);

		// 绘制印章单位
		g2d.setFont(firmFont);
		g2d.setColor(firmColor);
		fm = g2d.getFontMetrics();
		h = fm.getHeight();// 字高度

		int count = firm.length();// 字数
		int r = width / 2;// 半径,就假设此印章是个矩形,方便计算

		float angle = (360 - firmAngle) / (count - 1);// 字间角度
		float start = 90 + firmAngle / 2;// 以x轴正向为0,顺时针旋转
		double vr = Math.toRadians(90);// 垂直旋转弧度
		char[] chars = firm.toCharArray();
		for (int i = 0; i < count; i++) {
			char c = chars[i];// 需要绘制的字符
			int cw = fm.charWidth(c);// 此字符宽度
			float a = start + angle * i;// 现在角度

			double radians = Math.toRadians(a);
			g2d.rotate(radians);// 旋转坐标系,让要绘制的字符处于x正轴
			float x = r - h;// 绘制字符的x坐标为半径减去字高度
			// g2d.drawLine(0, 0, (int) x, 0);// debug
			g2d.translate(x, 0);// 移动到此位置,此时字和x轴垂直
			g2d.rotate(vr);// 旋转90度,让字平行于x轴
			g2d.scale(firmScale, 1);// 缩放字体宽度
			g2d.drawString(String.valueOf(c), -cw / 2, 0);// 此点为字的中心点
			// 将所有设置还原,等待绘制下一个
			g2d.scale(1 / firmScale, 1);
			g2d.rotate(-vr);
			g2d.translate(-x, 0);
			g2d.rotate(-radians);
		}
	}

	/**
	 * 获取具有指定半径外接圆的五角星顶点
	 * 
	 * @param radius
	 *            圆半径
	 */
	private Polygon getPentaclePoints(float radius) {
		if (radius <= 0)
			return null;
		float lradius = radius * 0.381966f;// 根据radius求内圆半径
		double halfpi = Math.PI / 180f;
		Point[] points = new Point[10];
		for (int i = 0; i < points.length; i++) {
			if (i % 2 == 1)
				points[i] = new Point(
						(int) (Math.sin(halfpi * 36 * i) * radius),
						(int) (Math.cos(halfpi * 36 * i) * radius));
			else
				points[i] = new Point(
						(int) (Math.sin(halfpi * 36 * i) * lradius),
						(int) (Math.cos(halfpi * 36 * i) * lradius));
		}
		Polygon polygon = new Polygon();
		for (Point p : points) {
			polygon.addPoint(p.x, p.y);
		}
		return polygon;
	}

	/**
	 * 导出此印章为透明背景的图片字节数组.
	 * 
	 * @param format
	 *            图片类型,如果为null,则默认为png
	 * @return 数组
	 * @throws IOException
	 *             写出图像数据出现问题
	 */
	public byte[] export2pic(String format) throws IOException {
		int fix = 5;// 宽高修正,如果宽高就为图片宽高,可能边框线被切割
		BufferedImage bi = new BufferedImage(getWidth() + fix * 2, getHeight()
				+ fix * 2, BufferedImage.TYPE_INT_ARGB);
		Graphics2D g2d = bi.createGraphics();
		g2d.translate(fix, fix);
		this.draw(g2d);
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		ImageIO.write(bi, format == null ? "png" : format, baos);
		return baos.toByteArray();
	}

	public int getWidth() {
		return width;
	}

	public int getHeight() {
		return height;
	}

}

 

这个简单了,就是一个单纯的JFrame显示界面,拖拽出来的:

 

package i2534.iteye.com;

import java.awt.BorderLayout;

public class Main extends JFrame {

	private JPanel contentPane;
	private JPanel panel;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					Main frame = new Main();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public Main() {
		initComponents();
	}

	private void initComponents() {
		setTitle("刻 章 办 证");//刻 章 居然违禁词
                setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 450, 300);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(new BorderLayout(0, 0));
		contentPane.add(getPanel(), BorderLayout.CENTER);
	}

	private JPanel getPanel() {
		if (panel == null) {
			panel = new JPanel() {
				private Seal seal = new Seal();

				protected void paintComponent(java.awt.Graphics g) {
					super.paintComponent(g);

					g.translate((getWidth() - seal.getWidth()) / 2,
							(getHeight() - seal.getHeight()) / 2);

					seal.draw((Graphics2D) g);
				};
			};
			panel.setBackground(Color.WHITE);
		}
		return panel;
	}
}

 

运行结果:


 

经过老三提醒,可以使用

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

 进行抗锯齿处理.这个看需要自己酌情选择.

 

### 绘制带有印章效果的图形或文本 要在 HTML5 的 Canvas 上绘制一个具有印章效果的图形或文本,可以利用 `CanvasRenderingContext2D` 提供的功能。以下是具体方法: #### 设置布环境 首先需要获取到 `<canvas>` 元素及其上下文对象: ```javascript const canvas = document.getElementById('myCanvas'); const ctx = canvas.getContext('2d'); ``` #### 创建圆形背景 印章通常是一个圆圈包围的内容,可以通过 `arc()` 方法创建一个圆形路径并填充颜色: ```javascript ctx.beginPath(); ctx.arc(canvas.width / 2, canvas.height / 2, Math.min(canvas.width, canvas.height) * 0.4, 0, Math.PI * 2); ctx.closePath(); ctx.strokeStyle = 'red'; // 印章边缘的颜色 ctx.lineWidth = 5; ctx.stroke(); // 绘制边缘线条 ctx.fillStyle = '#ffebeb'; // 背景浅红色 ctx.fill(); // 填充内部区域 ``` #### 添加旋转文字 为了模拟传统印章中的环形文字,可以使用循环和三角函数计算每个字符的位置,并将其沿圆周分布: ```javascript function drawCircularText(text, radius, centerX, centerY) { const angleStep = (Math.PI * 2) / text.length; ctx.save(); ctx.textAlign = 'center'; ctx.font = 'bold 16px serif'; ctx.fillStyle = 'darkred'; for (let i = 0; i < text.length; i++) { let char = text[i]; let angle = -Math.PI / 2 + i * angleStep; // 开始位置调整为顶部 let x = centerX + Math.cos(angle) * radius; let y = centerY + Math.sin(angle) * radius; ctx.fillText(char, x, y); } ctx.restore(); } drawCircularText("公司名称", Math.min(canvas.width, canvas.height) * 0.35, canvas.width / 2, canvas.height / 2); ``` #### 中心放置主要文字 在印章中间添加主要内容(如名字或其他重要信息),可直接居中绘制: ```javascript ctx.save(); ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.font = 'bold 24px sans-serif'; ctx.fillStyle = 'black'; ctx.fillText("张三", canvas.width / 2, canvas.height / 2); // 主体文字 ctx.restore(); ``` 以上代码片段展示了如何构建一个简单的电子印章样式的图像[^1]。 #### 处理跨浏览器兼容性问题 需要注意的是,在某些旧版浏览器(尤其是 Internet Explorer)可能缺乏对原生 Canvas 的支持。在这种情况下,可以引入 explorercanvas 库作为解决方案[^3]: ```html <!--[if IE]> <script type="text/javascript" src="excanvas.js"></script> <![endif]--> ``` 最后提醒开发者们记得测试不同设备上的表现情况以确保一致性和用户体验良好。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值