【问题标题】:Drawing two 3D strings on Canvas?在 Canvas 上绘制两个 3D 字符串?
【发布时间】:2012-11-18 06:34:08
【问题描述】:

我必须在画布上绘制 2 个字符串。字符串必须使用 相同的坐标 绘制,第二个字符串必须是第一个字符串绕 Y 轴旋转 45 度的结果。结果必须如下所示:

这是我的代码:

Matrix matrix = new Matrix();
matrix = canvas.getMatrix();
mCamera = new Camera();


canvas.drawText("In the name of God", 30, 100, redPaint);
mCamera.rotateY(45);
mCamera.getMatrix(matrix);

matrix.preTranslate(30, 100);
//      matrix.postTranslate(-30, -100);

canvas.setMatrix(matrix);
canvas.drawText("In the name of God", 0, 0, greenPaint);

但是上面代码的结果是:

你可以看到字符串的坐标不同。那么我做错了什么?我猜是matrix.preTranslate()的参数不正确造成的。

更新

我将代码更改为:

canvas.drawText("In the name of God", 30, 100, redPaint);
mCamera.rotateY(45);
mCamera.getMatrix(matrix);
matrix.preTranslate(-30, -100);
matrix.postTranslate(30, 100);
canvas.setMatrix(matrix);
canvas.drawText("In the name of God", 0, 0, greenPaint);

或喜欢:

canvas.drawText("In the name of God", 30, 100, redPaint);
mCamera.rotateY(45);
mCamera.getMatrix(matrix);
matrix.preTranslate(-30, -100);
//matrix.postTranslate(30, 100);
canvas.setMatrix(matrix);
canvas.drawText("In the name of God", 0, 0, greenPaint);

或喜欢:

canvas.drawText("In the name of God", 30, 100, redPaint);
mCamera.rotateY(45);
mCamera.getMatrix(matrix);

matrix.preTranslate(-30, -100);
//      matrix.postTranslate(30, 100);
canvas.setMatrix(matrix);
canvas.drawText("In the name of God", 30, 100, greenPaint);

对于以上三个代码,结果如下所示:

我猜第二个文本超出了status bar 的范围或后面,所以它不可见。

然后将我的代码更改为:

mCamera.rotateY(45);
mCamera.getMatrix(matrix);
matrix.preTranslate(-30, -100);
matrix.postTranslate(30, 100);
canvas.setMatrix(matrix);
canvas.drawText("In the name of God", 30, 100, greenPaint);

结果:

【问题讨论】:

  • @eh9 我看到了上面的问题(如何在特定点旋转画布......),但我不明白他为什么使用canvas.translate。正如你之前所说,我认为当我们使用 Matrix.preTranslate() 时,我们将旋转的枢轴更改为新的原点。那么他为什么使用canvas.translate

标签: android matrix camera android-canvas


【解决方案1】:

感谢回复。我解决了这个问题。我必须使用canvas.concat() 而不是canvas.setMatrix。这是正确的代码:

Matrix matrix = new Matrix();
mCamera = new Camera();

canvas.drawText("In the name of God", 30, 100, redPaint);
mCamera.rotateY(60);
mCamera.getMatrix(matrix);

matrix.preTranslate(-30, -100);
matrix.postTranslate(30, 100);
canvas.concat(matrix);
canvas.drawText("In the name of God", 30, 100, greenPaint);

【讨论】:

  • 恭喜你找到了。这必须在名称最差的 API 选择中的最后 1%。
  • @eh9 我有一个新问题,你知道吗?我试图自己解决它,但我不能。我写在这个问题中:stackoverflow.com/questions/13548192/…
【解决方案2】:

试试这个:

Matrix matrix = new Matrix();
matrix = canvas.getMatrix();
mCamera = new Camera();


canvas.drawText("In the name of God", 30, 100, redPaint);
mCamera.translate(30, 100);
mCamera.rotateY(45);
mCamera.getMatrix(matrix);

canvas.setMatrix(matrix);
canvas.drawText("In the name of God", 0, 0, greenPaint);

我从不搞乱前翻译和后翻译,但你可以调试它并尝试做后翻译而不是预翻译并提供 (30, 100) 看看是否有效。

【讨论】:

  • 我尝试了您的代码,但只有第一个绘​​制的文本(带有红色油漆)可见。
  • 我也把mCamera.translate(30, 100);改成mCamera.translate(30, 100,0);
  • 你可以试试做代码,但不画红色文字,看看绿色文字是否正确显示?
  • 我尝试了没有绘制红色文本的代码,结果中没有绿色文本。我猜第二个文本超出了范围或在状态栏后面,所以它不可见。
  • 你提到了状态栏。也许您没有考虑状态栏。 Canvas 对状态栏一无所知,因此当您输入原始 X 和 Y 坐标时,它会与状态栏做坐标(即真正的 X 和 Y 坐标)。您能否尝试通过状态栏的高度来偏移 Y 值,例如执行 preTranslate(-30, -(100 + STATUS_BAR_HEIGHT));然后做一个 postTranslate(30, 100 + STATUS_BAR_HEIGHT);
【解决方案3】:

矩阵对象描述的旋转总是具有其旋转轴通过原点的属性。旋转轴上的每个点在旋转下都是不变的,这是一种奇特(且紧凑)的说法,即它不会改变。按照您描述所需结果的方式,您希望文本的左边缘不移动。这意味着文本的左边缘必须位于该不变轴上。

这就是pretranslate() 的用途。您需要将文本位置转换为原点的翻译。该平移的坐标是坐标的负数:

matrix.preTranslate(-30, -100);

此平移应用于文本,而不是旋转轴。这种混乱似乎是你问题的根源。要将文本放回原来的位置,请将postTranslate 与预翻译的负数一起使用,即与原始坐标一起使用。

为了更好地理解这一点,请阅读similarity transforms

【讨论】:

  • 我将matrix.preTranslate(30, 100); 更改为matrix.preTranslate(-30, -100);matrix.postTranslate(30, 100); 并尝试canvas.drawText("...", 0, 0, greenPaint);canvas.drawText("...", 30, 100, greenPaint);,但没有一个是正确的。
  • 结果是什么样的?请编辑您的问题。我完全有可能误读了 Android 文档。这样的东西有一个可怕的习惯,就是对坐标系草率。
  • 请再次查看我的问题,我添加了一些sn-p代码及其结果。
猜你喜欢
  • 1970-01-01
  • 2015-09-16
  • 1970-01-01
  • 2011-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多