Android Canvas меняет цвет пересечения форм и текстов - PullRequest
0 голосов
/ 26 мая 2018

Я пытаюсь изменить цвет пересечения фигур и текста с помощью Canvas.As you can see in the image У меня есть 2 фигуры и 1 текст с разными красками.

Это режим без PorterDuffXfermode и PorterDuffColorFilter, добавляемый к любой краске.Я хочу, чтобы пересечение фигур было определенного цвета, например белого, и текста красного или белого цвета, как на изображениях ниже.

В моем примере текст находится внизу, середина круга и прямоугольник выше, но он незначительный, яЯ просто пытаюсь выяснить, как это работает и как можно установить пересечение для определенного цвета.

Как вы можете видеть на этом изображении image фон черный, круги белыеи текст черный.Когда кружки перекрываются, пересечение окружностей становится черным, а перекрывающийся участок текста становится белым.

Я могу добиться этого с помощью

canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_OUT));

, если круг и прямоугольник одновременно белые, а фон черный.Когда я меняю цвет фона на любой другой цвет, текст не виден, фигуры черные.

Мне также интересно, как я могу получить аналогичные результаты, как на этом изображении on the image Может перекрывать разделыдля круга, прямоугольника и текста можно задать определенный цвет?

1 Ответ

0 голосов
/ 29 мая 2018

Android Canvas меняет цвет пересечения фигур и текстов

и:

"Если круг и прямоугольник одновременно белые, а фон черный. КогдаЯ изменяю цвет фона на любой другой цвет , текст не виден, фигуры черные. "

PorterDuff

  • (1)Да, мы можем с PorterDuff.Mode (Mode.ADD):

    PorterDuff.Mode mode = Mode.ADD;

  • (2)Canvas фон должен быть transparent, чтобы compositing работал.Если вам нужен любой другой цвет фона , тогда нам нужно сделать наложение на отдельно Canvas.Затем мы копируем чертеж в оригинал Canvas.

«Мне также интересно, как я могу получить аналогичные результаты, как в этом изображении»

Вот вывод кода (PorterDuff определяет цвет смешивания; O ():

code outputcode output

(Q1 :) «Можно ли установить перекрывающиеся участки для круга, прямоугольника и текста на определенный цвет?»

  • (A1 :) Да, это может бытьсделано (с большими усилиями). Почти закончено, но уверено, что может. Вот почти готовые изображения (в этом ответе мне пришлось использовать почти все вещи, должен быть более простым способом ...):

enter image description hereenter image description here

Код

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

    Paint paint          = new Paint();
    Paint paintClear     = new Paint();
    TextPaint textPaint  = new TextPaint();
    int width            = getWidth();
    int height           = getHeight();
    int x                = 100;
    int y                = 100;
    int radius           = 100;

    PorterDuff.Mode mode        = Mode.ADD;      // mode Mode.ADD

    paintClear.setStyle(Style.FILL); 
    paint.setStyle(Style.FILL); 
    textPaint.setAntiAlias(true); 
    textPaint.setTextSize(100 * getResources().getDisplayMetrics().density);
    textPaint.setColor(Color.GREEN);    
    textPaint.setStrokeWidth(3);     

    // ** clear canvas backgound to white**
    paintClear.setColor(Color.WHITE);
    canvas.drawPaint(paintClear); 
    //canvas.save();

    Bitmap compositeBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
    Canvas compositeCanvas = new Canvas(compositeBitmap);
    paintClear.setColor(Color.TRANSPARENT);
    compositeCanvas.drawPaint(paintClear); 

    // ** draw destination circle in red **
    paint.setColor(Color.RED);
    compositeCanvas.drawCircle(x+100, y+100, radius, paint);

    // ** set Xfermode **
    paint.setXfermode(new PorterDuffXfermode(mode));
    textPaint.setXfermode(new PorterDuffXfermode(mode));

    // ** draw source circle in blue **
    paint.setColor(Color.BLUE);
    compositeCanvas.drawCircle(x-0, y-0, radius, paint);

    // ** draw text in Green **
    compositeCanvas.save();
    compositeCanvas.rotate(-45, x, y+150);
    compositeCanvas.drawText("- 65,6", x, y+150, textPaint);
    compositeCanvas.restore();

    //copy compositeCanvas to canvas
    canvas.drawBitmap(compositeBitmap, 0, 0, null);
    //canvas.restore();
}//onDraw

Проверка пересечения

Использование RectF содержит и пересекается:

public Rect  mBound = new Rect(0  , 0  , 10 , 10);
public RectF a1     = new Rect(0f , 0f , 10f, 10f);
public RectF b1     = new Rect(5f , 5f , 20f, 20f);
public RectF c1     = new Rect(30f, 30f, 40f, 40f);

int boolean hit       = false;
int boolean intersect = false;
hit = hitTest(20,15); // returns false
hit = hitTest(5,5);   // returns true 
intersect = intersectsTest(a1,b1);// returns true
intersect = intersectsTest(a1,c1);// returns false

public boolean hitTest(int x, int y) 
{
    return mBound.contains(x, y); 
}//
// Returns true if the two specified rectangles intersect
public boolean intersectsTest(RectF a, RectF b) 
{
    return intersects ( a, b);
}//

Заметки

Вы указали, что хотите узнать больше о цветном рисовании, вот некоторые вещи, с которыми я играл.

Эксперименты с setColorFilter и ColorMatrixColorFilter:

textPaint.setColorFilter(new ColorMatrixColorFilter(getColorMatrix5()));//custom 5

//custom 5
private ColorMatrix getColorMatrix5() 
{
    ColorMatrix colorMatrix = new ColorMatrix();
    colorMatrix.setSaturation(0);//make it greyscale
    ColorMatrix blueMatrix = new ColorMatrix(new float[] {
        0, 0, 0, 0, 0, // red
        0, 0, 0, 0, 0, // green
        1, 1, 1, 1, 1, // blue
        1, 1, 1, 1, 1  // alpha
    });
    // Convert, then scale and clamp
    colorMatrix.postConcat(blueMatrix);
    return colorMatrix;
}//getColorMatrix1

Настройка PorterDuff

Звучит так, будто вам нужно Custom PorterDuff.Вот некоторый код, чтобы дать вам представление о том, как его написать (Android использует библиотеку, написанную на C++).

public class MyPorterDuffMode
{

    public Bitmap applyOverlayMode(Bitmap srcBmp, Bitmap destBmp)
    {
        int width          = srcBmp.getWidth();
        int height         = srcBmp.getHeight();
        int srcPixels[]    = new int[width * height];
        int destPixels[]   = new int[width * height];
        int resultPixels[] = new int[width * height];
        int aS   = 0, rS = 0, gS = 0, bS = 0;
        int rgbS = 0;
        int aD   = 0, rD = 0, gD = 0, bD = 0;
        int rgbD = 0;

        try
        {
            srcBmp.getPixels(srcPixels, 0, width, 0, 0, width, height);
            destBmp.getPixels(destPixels, 0, width, 0, 0, width, height);
            srcBmp.recycle();
            destBmp.recycle();
        }
        catch(IllegalArgumentException e)
        {
        }
        catch(ArrayIndexOutOfBoundsException e)
        {
        }

        for(int y = 0; y < height; y++)
        {
            for(int x = 0; x < width; x++)
            {
                rgbS = srcPixels[y*width + x];
                aS = (rgbS >> 24) & 0xff;
                rS = (rgbS >> 16) & 0xff;
                gS = (rgbS >>  8) & 0xff;
                bS = (rgbS      ) & 0xff;

                rgbD = destPixels[y*width + x];
                aD = ((rgbD >> 24) & 0xff);
                rD = (rgbD >> 16) & 0xff;
                gD = (rgbD >>  8) & 0xff;
                bD = (rgbD      )  & 0xff;

                //overlay-mode
                rS = overlay_byte(rD, rS, aS, aD);
                gS = overlay_byte(gD, gS, aS, aD);
                bS = overlay_byte(bD, bS, aS, aD);
                aS = aS + aD - Math.round((aS * aD)/255f);

                resultPixels[y*width + x] = ((int)aS << 24) | ((int)rS << 16) | ((int)gS << 8) | (int)bS;
            }
        }
        return Bitmap.createBitmap(resultPixels, width, height, srcBmp.getConfig());
    }

    // kOverlay_Mode
    int overlay_byte(int sc, int dc, int sa, int da) 
    {
        int tmp = sc * (255 - da) + dc * (255 - sa);
        int rc;
        if (2 * dc <= da) 
        {
            rc = 2 * sc * dc;
        } 
        else 
        {
            rc = sa * da - 2 * (da - dc) * (sa - sc);
        }
        return clamp_div255round(rc + tmp);
    }

    int clamp_div255round(int prod) 
    {
        if (prod <= 0) 
        {
            return 0;
        } 
        else if (prod >= 255*255) 
        {
            return 255;
        } 
        else 
        {
            return Math.round((float)prod/255);
        }
    }

}//class MyPorterDuffMode

Ссылка на код

См. PorterDuff , PorterDuff.Mode, PorterDuffXfermode, ColorFilter, ColorMatrix , ColorMatrixColorFilter , PorterDuffColorFilter , Canvas, Color.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...