android - 始终在屏幕上的固定点绘制一个点,即使在放大或缩小 Canvas 时也是如此? - 安卓

标签 android android-canvas android-drawable android-screen

我现在在 Canvas 上画一个点,可以放大或缩小。

据我所知,绘图函数canvas.drawCircle()接受 Canvas 坐标系中的坐标。此外,缩放 Canvas 时坐标保持不变。

例如之前你在 Canvas 坐标系中的(50, 50)处画了一个点,然后你放大 Canvas , Canvas 中的点坐标仍然是(50, 50)。但很明显,点已经被 w.r.t. 移动了。屏幕。

Canvas 缩放时,点应保持在屏幕上的相同位置。 * 在点移动 w.r.t. 之后到屏幕上,我想将它移回原来的位置 w.r.t.屏幕。*

我的onDraw()函数如下:

@Override
public void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    canvasWidth = canvas.getWidth();
    canvasHeight = canvas.getHeight();

    canvas.save();
    canvas.translate(mPosX, mPosY);
    canvas.scale(mScaleFactor, mScaleFactor);
    mImage.draw(canvas); // draw the map as the background

            Paint PointStyle = new Paint();
    PointStyle.setColor(Color.BLUE);
    PointStyle.setStyle(Paint.Style.FILL_AND_STROKE);
    PointStyle.setStrokeWidth(2);

    canvas.drawCircle(Constant.INITIAL_X, Constant.INITIAL_Y, 3, PointStyle);

    canvas.restore();
}

我尝试了以下方法在缩放后将点移回屏幕。

private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
    @Override
    public boolean onScale(ScaleGestureDetector detector) {

        mScaleFactor *= detector.getScaleFactor(); // accumulate the scale factors
        // Don't let the object get too small or too large.
        mScaleFactor = Math.max(1f, Math.min(mScaleFactor, 10.0f)); // 1 ~ 10

        float pinToCornerOnScreenXDistance = 0;
        float pinToCornerOnScreenYDistance = 0;
        float canvasToScreenDiffRatioX = 0;
        float canvasToScreenDiffRatioY = 0;
        float pinOnCanvasX = 0;
        float pinOnCanvasY = 0;

        // pin's location on the screen --> S:(336, 578)
        pinToCornerOnScreenXDistance = 336 - canvasLeftTopCornerOnScreenX;
        pinToCornerOnScreenYDistance = 578 - canvasLeftTopCornerOnScreenY;
        Log.d("Screen Diff", "X: " + pinToCornerOnScreenXDistance + " Y: " + pinToCornerOnScreenYDistance);

        canvasToScreenDiffRatioX = canvasWidth * mScaleFactor / 720; // screen of HTC One X --> 720*1280
        canvasToScreenDiffRatioY = canvasHeight * mScaleFactor / 1280;
        Log.d("Ratio", canvasToScreenDiffRatioX + " " + canvasToScreenDiffRatioY);

        pinOnCanvasX = 0 + pinToCornerOnScreenXDistance * canvasToScreenDiffRatioX; // canvas left top corner is the origin (0, 0)
        pinOnCanvasY = 0 + pinToCornerOnScreenYDistance * canvasToScreenDiffRatioY;
        Log.d("Pin on Canvas", "X: " + pinOnCanvasX + " Y: " + pinOnCanvasY);

        Constant.setInitialX(pinOnCanvasX);
        Constant.setInitialY(pinOnCanvasY);
        historyXSeries.set(0, Constant.INITIAL_X);
        historyYSeries.set(0, Constant.INITIAL_Y);

        invalidate();
        return true;
    }
}

这个想法是基于这样一个事实,即当我放大或缩小 Canvas 时,它的左上角永远不会移动。也就是说, Canvas 的顶角是缩放中心。

然后我在 Canvas 移动时成功地不断更新缩放中心的坐标。所以这样一来,无论我移动 Canvas 还是缩放 Canvas ,我的 canvasLeftTopCornerOnScreenXcanvasLeftTopCornerOnScreenY 中始终有缩放中心的坐标。

然后,我尝试利用 never-moved-during-scaling 缩放中心与我希望在此处放置点 (336, 578) 的所需位置之间的距离。我将其计算为 pinToCornerOnScreenDistance

顾名思义,就是屏幕上的距离。我必须将它缩放到 Canvas 距离以便我可以绘制点,因为绘图函数基于 Canvas 坐标系而不是屏幕坐标系。目前,该代码是特定于设备的,即目前仅适用于具有 1280*720 屏幕的 HTC One X。所以我按如下方式进行缩放:

canvasToScreenDiffRatioX = canvasWidth * mScaleFactor / 720;
canvasToScreenDiffRatioY = canvasHeight * mScaleFactor / 1280;

然后,最后我计算屏幕上点 (336, 578) 的新 Canvas 坐标,然后在那里绘制点。

但结果不正确。当我缩放 Canvas 时,我绘制的点无法保持在屏幕上的 (336, 578) 处。

谁能告诉我哪里出了问题? 或者提出另一种方法?

任何评论或回答将不胜感激!

最佳答案

您的应用是否使用全屏模式?否则,高度不是1280。但我不认为这是你的问题。

根据我的理解,我将代码改成

pinOnCanvasX = 336 / mScaleFactor;
pinOnCanvasY = 578 / mScaleFactor;

我假设当 mScaleFactor == 1 时, Canvas 上的引脚与屏幕上的引脚相同

关于android - 始终在屏幕上的固定点绘制一个点,即使在放大或缩小 Canvas 时也是如此? - 安卓,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17606756/

相关文章:

android - Drawable 被拉伸(stretch)以适应 View

android - Android-GraphView 中的 java.util.ConcurrentModificationException

android - RelativeLayout 未正确更新自定义 View 的宽度

android - 如何提高 Sqlite/Android 中 SELECT 查询的性能?

java - 重新创建一个对象而不删除最后一个

android - 在运行时构建一个 9 patch drawable

android - Jacoco 将 coverage.ec 转换为没有 coverage.em 的报告

android - Canvas.drawTextOnPath(...) 不适用于 Lollipop

android - b/w canvas.drawpath 和 canvas.drawline 的区别

Android收据/之字形可绘制/布局