【问题标题】:How to draw watchface 'ticks' on a square watch?如何在方形手表上绘制表盘“刻度”?
【发布时间】:2016-04-17 07:26:38
【问题描述】:

我目前有这个 sn-p 在外部和 android wear 表盘周围生成刻度

float innerMainTickRadius = mCenterX - 35;
            for(int tickIndex = 0; tickIndex < 12; tickIndex++) {
                float tickRot = (float) (tickIndex * Math.PI * 2 / 12);
                float innerX = (float) Math.sin(tickRot) * innerMainTickRadius;
                float innerY = (float) -Math.cos(tickRot) * innerMainTickRadius;
                float outerX = (float) Math.sin(tickRot) * mCenterX;
                float outerY = (float) -Math.cos(tickRot) * mCenterX;
                canvas.drawLine(mCenterX + innerX, mCenterY + innerY, mCenterX + outerX, mCenterY + outerY, mTickPaint);
            }

它在圆形表盘上很好地生成刻度,但在正方形上却是这样: 但我希望它们不是圆形,而是更适合形状,例如:

有没有标准的方法来做到这一点?我猜我不能再使用触发了...

【问题讨论】:

    标签: android wear-os watch-face-api


    【解决方案1】:

    当然你使用几何和三角。例如,您在钟面上放置的任何要指向中心的线,因此一部分将是给定的 (x,y),而另一部分将是 arctan2(cy-y,cx-x),为您提供从指向中心 (cx,cy) 然后简单地在给定长度 r 的中心方向上画线,从 x,y 到 cos(angle) * r, sin(angle) * r .

    但是,给定您的示例图像,您可能希望绘制从 x,y 到 x+r,y 的线,然后按角度旋转画布,以便您可以绘制像这样调整的数字。请务必在调整画布矩阵之前执行 canvas.save(),并在调整后执行 canvas.restore()。

    这留下了您要从中绘制刻度的任何形状及其位置的数学计算。您可以在路径中执行此操作。因此,定义圆角矩形的路径,然后使用 PathMeasure 类获取 getPosTan(),然后忽略切线,只需使用它提供的位置来找到圆角矩形周围的位置。或者只是根据确定的形状将这些位置计算为通过线段或贝塞尔曲线的位置。

    例如:

    static final int TICKS = 12;
    static final float TICKLENGTH = 20;
    

    在绘图例程中,

        float left = cx - 50;
        float top = cy - 50;
        float right = cx + 50;
        float bottom = cy + 50;
        float ry = 20;
        float rx = 20;
        float width = right-left;
        float height = bottom-top;
        Path path = new Path();
        path.moveTo(right, top + ry);
        path.rQuadTo(0, -ry, -rx, -ry);
        path.rLineTo(-(width - (2 * rx)), 0);
        path.rQuadTo(-rx, 0, -rx, ry);
        path.rLineTo(0, (height - (2 * ry)));
        path.rQuadTo(0, ry, rx, ry);
        path.rLineTo((width - (2 * rx)), 0);
        path.rQuadTo(rx, 0, rx, -ry);
        path.rLineTo(0, -(height - (2 * ry)));
        path.close();
    
        PathMeasure pathMeasure = new PathMeasure();
        pathMeasure.setPath(path,true);
        float length = pathMeasure.getLength();
        float[] pos = new float[2];
        float r = TICKLENGTH;
        for (int i = 0; i < TICKS; i++) {
            pathMeasure.getPosTan(i * (length/TICKS),pos,null);
            double angle = Math.atan2(cy - pos[1], cx - pos[0]); //yes, y then x.
            double cos = Math.cos(angle);
            double sin = Math.sin(angle);
            canvas.drawLine(pos[0], pos[1], (float)(pos[0] + cos * r), (float)(pos[1] + sin * r), paint);
        }
    

    诚然,它看起来像:

    因此,要让它看起来像您的图像需要更多的工作。但是,这是完全可行的。路径测量技巧适用于任何形状。由于 Lollipop+ 的限制,我避免使用 path.addRoundRect。你可以看到我对这个问题的回答here。其他答案对于如何绘制圆角矩形形状非常有用。如果您想编写一个包络函数,您可以根据因子 t 将当前图片缩放到矩形的包络,因为它全天候运行。

    【讨论】:

    • 如果你有那个矢量模型,你可以只使用矢量图形并在绘制过程中把那个图标吹得那么大。在 SVG 中绘制您想要的内容,将其转换为 android 矢量图形,然后将可绘制对象绘制到画布上,它会非常小且不含糊。
    • 这实际上不是一个坏主意。我使用了您的第一个答案,最后通过一些调整效果很好
    【解决方案2】:

    角度现在是位置的函数。在这种情况下,我没有立即看到获得封闭表格的技巧。但在最一般的情况下,您最终可能只存储每个刻度线的位置,然后您只需绘制穿过该点和中心的线。所以第二个 i 的角度只是

    theta(i)=arctan(y_pos(i) / x_pos(i))
    

    假设中心的坐标为 (0,0)。在这种情况下,您只需要存储 8 个连续刻度的位置,因为面每 90 度是周期性的,并且也关于对角线对称。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-19
      • 2018-04-30
      • 2012-09-26
      • 1970-01-01
      • 1970-01-01
      • 2017-09-08
      相关资源
      最近更新 更多