【问题标题】:How to draw a filled triangle in android canvas?如何在android画布中绘制一个实心三角形?
【发布时间】:2011-03-30 21:22:30
【问题描述】:

所以我在我的 draw 方法中使用下面的代码在 android 地图中绘制这个三角形:

paint.setARGB(255, 153, 29, 29);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setAntiAlias(true);

Path path = new Path();
path.moveTo(point1_returned.x, point1_returned.y);
path.lineTo(point2_returned.x, point2_returned.y);
path.moveTo(point2_returned.x, point2_returned.y);
path.lineTo(point3_returned.x, point3_returned.y);
path.moveTo(point3_returned.x, point3_returned.y);
path.lineTo(point1_returned.x, point1_returned.y);
path.close();

canvas.drawPath(path, paint);

pointX_returned 是我从字段中获取的坐标。它们基本上是纬度和经度。 结果是一个漂亮的三角形,但内部是空的,因此我可以看到地图。有没有办法以某种方式填充它?

【问题讨论】:

  • 正如我在回答中发布的那样,不要在每个 lineTo() 之后 moveTo(),仅此而已。
  • 我知道这是一个老问题,已经有一个(不正确的)接受的答案,你还发布了你的最终解决方案,它有效......但你没有说明它为什么有效,我希望我的评论可以节省我刚刚花在这上面的时间:)

标签: java android google-maps android-canvas


【解决方案1】:

好的,我已经完成了。我共享此代码以防其他人需要它:

super.draw(canvas, mapView, true);

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

paint.setStrokeWidth(2);
paint.setColor(android.graphics.Color.RED);     
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setAntiAlias(true);

Point point1_draw = new Point();        
Point point2_draw = new Point();    
Point point3_draw = new Point();

mapView.getProjection().toPixels(point1, point1_draw);
mapView.getProjection().toPixels(point2, point2_draw);
mapView.getProjection().toPixels(point3, point3_draw);

Path path = new Path();
path.setFillType(Path.FillType.EVEN_ODD);
path.moveTo(point1_draw.x,point1_draw.y);
path.lineTo(point2_draw.x,point2_draw.y);
path.lineTo(point3_draw.x,point3_draw.y);
path.lineTo(point1_draw.x,point1_draw.y);
path.close();

canvas.drawPath(path, paint);

//canvas.drawLine(point1_draw.x,point1_draw.y,point2_draw.x,point2_draw.y, paint);

return true;

感谢 Nicolas 的提示!

【讨论】:

  • 我很确定您不需要最后一个 lineTo()close() 会自动执行此操作。
  • @Timmmm 我已经测试过了,你是对的,不需要最后一行To()。谢谢。
  • 非常感谢。我不知道为什么我在绘制三角形时遇到了这么多问题,但在过去的 20 分钟里,我在这个小问题上遇到了各种错误。
  • 这里是复制粘贴的简单方法(基于@Pavel的代码):gist.github.com/ZirconCode/59cae1e2615279eafb29
  • 如果你把path改成实例变量,记得在canvas.drawPath()之后调用path.reset()
【解决方案2】:

您可能需要执行以下操作:

Paint red = new Paint();

red.setColor(android.graphics.Color.RED);
red.setStyle(Paint.Style.FILL);

并为您的路径使用此颜色,而不是您的 ARGB。确保路径的最后一点在第一个点结束,这也很有意义。

请告诉我它是否有效!

【讨论】:

  • 不幸的是,这没有帮助
  • @Nicolas 如果我们必须使用 RGB 值而不是使用预定义值来自定义颜色,那么用什么来代替 ARGB?
【解决方案3】:

你也可以使用顶点:

private static final int verticesColors[] = {
    Color.LTGRAY, Color.LTGRAY, Color.LTGRAY, 0xFF000000, 0xFF000000, 0xFF000000
};
float verts[] = {
    point1.x, point1.y, point2.x, point2.y, point3.x, point3.y
};
canvas.drawVertices(Canvas.VertexMode.TRIANGLES, verts.length, verts, 0, null, 0, verticesColors,   0, null, 0, 0, new Paint());

【讨论】:

  • 我认为这个解决方案不能处理填充形状。 (无法测试,我目前没有 IDE)
  • 这似乎是性能更高的解决方案,但不幸的是,硬件加速视图不支持此方法。您可以禁用硬件加速,但会失去其性能提升:developer.android.com/guide/topics/graphics/hardware-accel.html
【解决方案4】:

使用@Pavel 的答案作为指导,如果您没有点但有起点 x、y 和高度和宽度,这是一个辅助方法。也可以绘制倒置/倒置 - 这对我很有用,因为它被用作垂直条形图的末端。

 private void drawTriangle(int x, int y, int width, int height, boolean inverted, Paint paint, Canvas canvas){

        Point p1 = new Point(x,y);
        int pointX = x + width/2;
        int pointY = inverted?  y + height : y - height;

        Point p2 = new Point(pointX,pointY);
        Point p3 = new Point(x+width,y);


        Path path = new Path();
        path.setFillType(Path.FillType.EVEN_ODD);
        path.moveTo(p1.x,p1.y);
        path.lineTo(p2.x,p2.y);
        path.lineTo(p3.x,p3.y);
        path.close();

        canvas.drawPath(path, paint);
    }

【讨论】:

    【解决方案5】:

    这个函数展示了如何从位图创建一个三角形。也就是说,创建三角形的裁剪图像。试试下面的代码或download demo example

     public static Bitmap getTriangleBitmap(Bitmap bitmap, int radius) {
            Bitmap finalBitmap;
            if (bitmap.getWidth() != radius || bitmap.getHeight() != radius)
                finalBitmap = Bitmap.createScaledBitmap(bitmap, radius, radius,
                        false);
            else
                finalBitmap = bitmap;
            Bitmap output = Bitmap.createBitmap(finalBitmap.getWidth(),
                    finalBitmap.getHeight(), Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(output);
    
            Paint paint = new Paint();
            final Rect rect = new Rect(0, 0, finalBitmap.getWidth(),
                    finalBitmap.getHeight());
    
            Point point1_draw = new Point(75, 0);
            Point point2_draw = new Point(0, 180);
            Point point3_draw = new Point(180, 180);
    
            Path path = new Path();
            path.moveTo(point1_draw.x, point1_draw.y);
            path.lineTo(point2_draw.x, point2_draw.y);
            path.lineTo(point3_draw.x, point3_draw.y);
            path.lineTo(point1_draw.x, point1_draw.y);
            path.close();
            canvas.drawARGB(0, 0, 0, 0);
            paint.setColor(Color.parseColor("#BAB399"));
            canvas.drawPath(path, paint);
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
            canvas.drawBitmap(finalBitmap, rect, rect, paint);
    
            return output;
        }
    

    上面的函数返回一个在画布上绘制的三角形图像。 Read more

    【讨论】:

      【解决方案6】:
      private void drawArrows(Point[] point, Canvas canvas, Paint paint) {
      
          float [] points  = new float[8];             
          points[0] = point[0].x;      
          points[1] = point[0].y;      
          points[2] = point[1].x;      
          points[3] = point[1].y;         
          points[4] = point[2].x;      
          points[5] = point[2].y;              
          points[6] = point[0].x;      
          points[7] = point[0].y;
      
          canvas.drawVertices(VertexMode.TRIANGLES, 8, points, 0, null, 0, null, 0, null, 0, 0, paint);
          Path path = new Path();
          path.moveTo(point[0].x , point[0].y);
          path.lineTo(point[1].x,point[1].y);
          path.lineTo(point[2].x,point[2].y);
          canvas.drawPath(path,paint);
      
      }
      

      【讨论】:

      • 这行得通!不要忘记使用 paint.setAntiAlias(true) 以获得平滑的三角形。
      • drawVertices 需要什么?
      【解决方案7】:

      您需要在第一次初始化之后删除 path.moveTo。

      Path path = new Path();
      path.moveTo(point1_returned.x, point1_returned.y);
      path.lineTo(point2_returned.x, point2_returned.y);
      path.lineTo(point3_returned.x, point3_returned.y);
      path.lineTo(point1_returned.x, point1_returned.y);
      path.close();
      

      【讨论】:

      • 我没有 3 个点,但只有一个点 x nad y 我如何从该点绘制一个三角形。
      【解决方案8】:

      不要在每个lineTo() 之后moveTo()

      换句话说,删除除第一个之外的所有moveTo()

      说真的,如果我只是复制粘贴 OP 的代码并删除不必要的 moveTo() 调用,它就可以工作。

      没有其他事情需要做。


      编辑:我知道 OP 已经发布了他的“最终工作解决方案”,但他没有说明 为什么 它有效。真正的原因让我很惊讶,所以我觉得有必要补充一个答案。

      【讨论】:

      • 您应该为此添加评论。这不是答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-22
      • 2015-01-08
      • 1970-01-01
      相关资源
      最近更新 更多