Graphics 的translate(int x, int y) 函数

本文介绍了translate函数的作用原理,即通过改变绘图环境的坐标原点来实现图形的平移效果。利用这一特性,开发者可以更灵活地控制图像的绘制位置,并简化复杂的UI布局逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以前没有使用过translate(int x, int y)函数,新项目使用后,明白了使用原理

translate(int x, int y)
          Translates the origin of the graphics context to the point (x, y) in the current coordinate system.

就是把绘制区的x,y点坐标定义为坐标系的原点

比如之前绘制  

g.drawImage(img,x,y,0);

等价于

g.translate(x,y);

g.drawImage(img,0,0,0);

转变之后其他对Graphics的操作,也依赖于新的坐标系

比如

g.setClip(x,y,w,h);

等价于

g.translate(x,y);

g.setClip(0,0,w,h);

因此

g.setClip(x,y,w,h);

g.drawImage(img,x,y,0);

等价于

g.translate(x,y);

g.setClip(0,0,w,h);

g.drawImage(img,0,0,0);

 

基于translate函数的作用,就可以把Grphics绘制的一些功能,交给别人去做,提供一些方法或者接口,快速开发UI,

比如可以建立一个setX,setY之类的函数,对translate函数的参数进行操作,从而影响到Graphis的绘制位置及绘制区域,不过记得在使用完毕后,translate回来,使坐标系回归正常

 

 

import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Camera; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.LinearGradient; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PointF; import android.graphics.Shader; import android.util.AttributeSet; import android.view.View; import android.view.animation.LinearInterpolator; import androidx.annotation.Nullable; import java.util.ArrayList; import java.util.List; /** * @Description: 网格线 * @Author: alex * @CreateDate: 2025/7/9 16:03 */ public class LyricGridView extends View { private Paint gridPaint; private Paint controlPointPaint; private Path gridPath; private int gridSize = 100; // 网格尺寸 (行数和列数) private LinearGradient gradient; private List<PointF> controlPoints = new ArrayList<>(); private List<Boolean> randomizedPoints = new ArrayList<>(); private float rotationAngle = 15f; // 网格旋转角度() private float floatAmplitude = 20f; // 浮动幅度 private float floatPhase = 0f; // 浮动相位 private ValueAnimator floatAnimator; // 浮动动画控制器 Camera camera = new Camera(); Matrix canvasMatrix = new Matrix(); public LyricGridView(Context context) { super(context); init(); } public LyricGridView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } private void init() { // 网格线画笔设置 gridPaint = new Paint(Paint.ANTI_ALIAS_FLAG); gridPaint.setStyle(Paint.Style.STROKE); gridPaint.setStrokeWidth(1f); gridPaint.setColor(Color.parseColor("#80FFFFFF")); // 半透明白色 // 控制点画笔设置 controlPointPaint = new Paint(Paint.ANTI_ALIAS_FLAG); controlPointPaint.setStyle(Paint.Style.FILL); controlPointPaint.setColor(Color.parseColor("#cccccc")); gridPath = new Path(); // 初始化浮动动画 setupFloatAnimation(); } private void setupFloatAnimation() { floatAnimator = ValueAnimator.ofFloat(0, 2 * (float) Math.PI); floatAnimator.setDuration(5000); // 3秒完成一个完整周期 floatAnimator.setRepeatCount(ValueAnimator.INFINITE); floatAnimator.setInterpolator(new LinearInterpolator()); floatAnimator.addUpdateListener(animation -> { floatPhase = (float) animation.getAnimatedValue(); invalidate(); // 触发重绘 }); floatAnimator.start(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); // 设置渐变的方向是从右到左 gradient = new LinearGradient( w, 0, // 起始点(右侧) 0, 0, // 结束点(左侧) Color.parseColor("#cccccc"), Color.parseColor("#00000000"), // 黑色 -> 透明 Shader.TileMode.CLAMP ); // 更新画笔的着色器 gridPaint.setShader(gradient); generateControlPoints(w, h); buildBezierGrid(w, h); } private void generateControlPoints(int width, int height) { controlPoints.clear(); randomizedPoints.clear(); // 清空随机标记 float cellWidth = width / (float) gridSize; float cellHeight = height / (float) gridSize; // 生成网格点并添加随机偏移作为贝塞尔控制点 for (int row = 0; row <= gridSize; row++) { for (int col = 0; col <= gridSize; col++) { float x = col * cellWidth; float y = row * cellWidth; // 添加随机偏移(实际应用中可替换为自定义控制点) float offsetX = (float) (Math.random() * 10 - 5); float offsetY = (float) (Math.random() * 10 - 5); boolean isRandomized = false; // 边界约束 if (col == 0 || col == gridSize) offsetX = 0; if (row == 0 || row == gridSize) offsetY = 0; // 只有50%的点会被随机偏移 if (Math.random() > 0.95) { isRandomized = true; } offsetY = 0; offsetX = 0; controlPoints.add(new PointF(x + offsetX, y + offsetY)); randomizedPoints.add(isRandomized); // 记录随机状态 } } } private void buildBezierGrid(int width, int height) { gridPath.reset(); // 绘制横向曲线 for (int row = 0; row <= gridSize; row++) { for (int col = 0; col < gridSize; col++) { int index = row * (gridSize + 1) + col; PointF start = controlPoints.get(index); PointF end = controlPoints.get(index + 1); if (col == 0) { gridPath.moveTo(start.x, start.y); } gridPath.lineTo(end.x, end.y); } } // 绘制纵向曲线 for (int col = 0; col <= gridSize; col++) { for (int row = 0; row < gridSize; row++) { int index = row * (gridSize + 1) + col; PointF start = controlPoints.get(index); PointF end = controlPoints.get(index + gridSize + 1); if (row == 0) { gridPath.moveTo(start.x, start.y); } gridPath.lineTo(end.x, end.y); } } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 保存当前画布状态 canvas.save(); // 计算浮动偏移量 (使用正弦函数创造波浪效果) float floatOffset = floatAmplitude * (float) Math.sin(floatPhase * 0.5f); // 计算中心点坐标 float centerX = getWidth() / 2f; float centerY = getHeight() / 2f; camera.save(); camera.rotateX(40f); camera.getMatrix(canvasMatrix); camera.restore(); // 应用3D旋转(保持水平位置不变) canvasMatrix.preTranslate(-centerX, 0); canvasMatrix.postTranslate(centerX, 0); // 应用3D变换到Canvas canvas.concat(canvasMatrix); // 应用旋转变换(以中心点为轴心) // canvas.rotate(rotationAngle, centerX, centerY); canvas.translate((getWidth() / (float) gridSize) * 10, -(getWidth() / (float) gridSize) * 8); canvas.translate(floatOffset, 0); // 添加垂直浮动 // 绘制贝塞尔曲线网格 gridPaint.setAlpha(150); // 增加透明度 canvas.drawPath(gridPath, gridPaint); // // 绘制控制点(可选) // for (PointF point : controlPoints) { // canvas.drawCircle(point.x, point.y, 4, controlPointPaint); // } // 获取屏幕宽度的一半 float screenHalf = getWidth() / 3f; // 只绘制被随机偏移的控制点 for (int i = 0; i < controlPoints.size(); i++) { PointF point = controlPoints.get(i); if (randomizedPoints.get(i) && point.x > screenHalf) { // 只绘制被随机偏移的点 canvas.drawCircle(point.x, point.y, 1, controlPointPaint); } } // 恢复画布状态 canvas.restore(); } // 设置网格密度 public void setGridSize(int size) { this.gridSize = Math.max(2, size); requestLayout(); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (floatAnimator != null) { floatAnimator.cancel(); } } public void setDrawingEnabled(boolean enabled) { if (enabled) { setVisibility(VISIBLE); if (floatAnimator != null && !floatAnimator.isRunning()) { setupFloatAnimation(); } } else { setVisibility(GONE); if (floatAnimator != null) { floatAnimator.cancel(); } } } } 3d旋转后网格变形的原因
最新发布
07-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值