【问题标题】:Android Canvas Coordinate SystemAndroid 画布坐标系
【发布时间】:2010-05-28 17:45:17
【问题描述】:

我正在尝试查找有关如何更改画布坐标系的信息。我有一些矢量数据想用圆和线之类的东西绘制到画布上,但数据的坐标系与画布坐标系不匹配。

有没有办法将我正在使用的单位映射到屏幕的单位?

我正在绘制一个不占用整个显示器的 ImageView。

如果我必须在每次绘图调用之前进行自己的计算,我如何找到我的 ImageView 的宽度和高度?

我尝试的 getWidth() 和 getHeight() 调用似乎返回了整个画布大小,而不是 ImageView 的大小,这没有帮助。

我看到一些矩阵的东西,这对我有用吗?

我尝试使用“public void scale(float sx, float sy)”,但这更像是像素级缩放,而不是通过扩展每个像素来实现矢量缩放功能。这意味着如果增加尺寸以适应屏幕,线条粗细也会增加。


更新:

经过一些研究,我开始认为没有办法将坐标系更改为其他坐标系。我需要将所有坐标映射到屏幕的像素坐标,并通过修改每个向量来实现。 getWidth() 和 getHeight() 现在似乎对我来说效果更好。我可以说出了什么问题,但我怀疑我不能在构造函数中使用这些方法。

【问题讨论】:

  • 是的,getWidth() 和 getHeight() 在构造函数中肯定不起作用。

标签: android drawing canvas coordinate-systems


【解决方案1】:

感谢您的回复。我几乎已经放弃了让它以我认为应该的方式工作。当然,我认为事情应该如何发生并不是它们确实如何发生。 :)

这基本上是它的工作原理,但在某些情况下它似乎偏离了一个像素,当事物落在我尚未弄清楚的某些边界条件上时,圆圈似乎缺少部分。就我个人而言,我认为这在应用程序代码中是不可接受的,并且应该在 Android 库中......眨眼眨眼,如果你为 Google 工作,请轻推轻推。 :)

private class LinearMapCanvas
{
    private final Canvas canvas_; // hold a wrapper to the actual canvas.

    // scaling and translating values:
    private double scale_;

    private int translateX_;
    private int translateY_;

// linear mapping from my coordinate system to the display's:
    private double mapX(final double x)
    {
    final double result = translateX_ + scale_*x;
    return result;
    }

    private double mapY(final double y)
    {
        final double result = translateY_ - scale_*y;
        return result;
    }

    public LinearMapCanvas(final Canvas canvas)
    {
        canvas_ = canvas;

// Find the extents of your drawing coordinates:
        final double minX = extentArray_[0];
    final double minY = extentArray_[1];
    final double maxX = extentArray_[2];
    final double maxY = extentArray_[3];

// deltas:
    final double dx = maxX - minX;
    final double dy = maxY - minY;

// The display's available pixels, accounting for margins and pen stroke width:
    final int width = width_ - strokeWidth_ - 2*margin_;
    final int height = height_ - strokeWidth_ - 2*margin_;

    final double scaleX = width / dx;
    final double scaleY = height / dy;

    scale_ = Math.min(scaleX , scaleY); // Pick the worst case, so the drawing fits

// Translate so the image is centered:
        translateX_ = (int)((width_ - (int)(scale_*dx))/2.0 - scale_*minX);
        translateY_ = (int)((height_ - (int)(scale_*dy))/2.0 + scale_*maxY);
    }

// wrappers around the canvas functions you use.  These are only two of many that would need to be wrapped.  Annoying and error prone, but beats any alternative I can find.
    public void drawCircle(final float cx, final float cy, final float radius, final Paint paint)
    {
    canvas_.drawCircle((float)mapX(cx), (float)mapY(cy), (float)(scale_*radius), paint);
    }

    public void drawLine(final float startX, final float startY, final float stopX, final float stopY, final Paint paint)
    {
    canvas_.drawLine((float)mapX(startX), (float)mapY(startY), (float)mapX(stopX), (float)mapY(stopY), paint);
    }
...
}

【讨论】:

  • 请原谅我的代码的代码格式。代码在我发布之前看起来很棒,但在 StackOverflow 之后似乎做了一些疯狂的事情。
【解决方案2】:

您可以使用画布矩阵的preScale() 方法将画布坐标缩放到您自己的单位。请注意,这也会缩放 Paint 的笔画宽度,这可能不是您想要的。

【讨论】:

    【解决方案3】:

    我所知道的在 Android 中即时制作自定义矢量图形的唯一方法是将所有内容绘制到图像文件中,然后将其放入 ImageView。我不确定我是否完全理解您的要求,但如果唯一的问题是缩放,ImageView 将使用android:scaleType="center" 作为ImageView 的属性将给定的任何图像缩放到自己的大小。

    至于改变坐标系,我怀疑这是可能的(虽然我还没有研究过)。不过,编写一个将数据系统映射到标准 Android 坐标系的函数可能相当简单。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-24
      • 2011-10-15
      • 1970-01-01
      • 2010-09-20
      • 1970-01-01
      • 2016-12-28
      • 1970-01-01
      相关资源
      最近更新 更多