Подтвердить что ты не робот

Как установить комбинированный цвет для перекрываемой области двух разных цветовых объектов?

Я создаю различные пользовательские представления с двумя разными цветами. Согласно моим функциям приложения пользователь будет перетаскивать эти объекты на экране, когда перетаскивание объектов будет перекрывать друг друга. Я хочу дифференцировать перекрываемую область, как установить комбинированный цвет для перекрываемой области. Посмотрите на изображение ниже. Здесь я использую холст для создания этих пользовательских представлений. Два круга - это два разных вида.

enter image description here

EDIT: Если я использую opacity 128, я могу видеть цвет фона, но мне нужен цвет комбинации совпадающих объектов.

4b9b3361

Ответ 1

Смешивание цветов, которое вы ищете, иногда называется Интуитивное смешивание цветов, или RYB Цвет Система:

RYB

enter image description hereлицензия CC

Цитата из эта статья Натана Госсетта и Баокуана Чена по алгоритмам интуитивного смешения цветов суммирует, как работает интуитивная система цвета:

"В этой модели красные, желтые и синие используются как чистые первичные цвета. Красное и желтое смешивание для формирования оранжевого, желтого и синего смесей с образованием зеленого, синего и красного микса для формирования фиолетового [...]. Это цвета, которые неквалифицированный зритель ожидал бы получить с помощью детской краски [...]. Кроме того, многие люди не думают о Белом как о смеси всех цветов, а о том, как отсутствие цвета (пустой холст). Более распространенное предположение заключалось бы в том, что смешивание многих цветов вместе приведет к мутному темно-коричневому цвету".

RYB не реализован в режимах Android blend и не может быть реально имитирован путем смешивания альфа/разных режимов смешивания.

Большинство приложений компьютерной графики используют цветовые пространства RGB или CMYK:

CMYK

enter image description hereлицензия CC

CMY основан на субтрактивном цвете. Субтрактивное смешивание цветов означает, что, начиная с белого цвета, при добавлении цвета результат становится темнее. CMYK используется для смешивания цветов в изображениях, предназначенных для печати, например. Photoshop и Illustrator.

RGB

enter image description hereлицензия CC

RGB основан на добавочном цвете. Цвета на экране компьютера создаются с помощью света с использованием метода добавочного цвета. Смешивание добавочного цвета начинается с черного цвета и при добавлении большего количества цвета результат становится светлее и заканчивается белым цветом.

Этот сайт более подробно обсуждает CMYK и RGB.

Ни RGB, ни CMYK не смешивают синие и желтые зеленые или, вообще говоря, интуитивные цветовые смеси. Для внедрения цветовой системы RYB на Android было бы очень сложно. В статье Натана Госсетта и Баокуана Чена, приведенных выше, предлагается решение с алгоритмом, реализованным на C в самом конце статьи. Этот алгоритм может быть реализован в пользовательской смеси на Android. Drawable.setColorFilter() использует PorterDuffColorfilter, который расширяет ColorFilter. Подкласс ColorFilter, как обсуждалось в this. Вопрос должен быть сделан в с помощью NDK.

Методы обхода цвета CMYK

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

Начиная с этих .png файлов изображений, созданных в Adobe Illustrator:

enter image description here

enter image description here

с шестнадцатеричным значением цвета 0x00ffff (голубой) и 0xffff00 (желтый).

Добавьте их в свою папку с именами cyancircle.png и yellowcircle.png.

Настройте свой макет main.xml следующим образом:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" 
    android:background="#ffffff"
    android:padding="30dp">

<ImageView
    android:id="@+id/bluecircle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/cyancircle">
</ImageView>

<ImageView
    android:id="@+id/yellowcircle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/yellowcircle" 
    android:layout_marginTop="30dp">
</ImageView>     
</RelativeLayout>

Создайте свою деятельность:

import android.app.Activity;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.widget.ImageView;

public class PorterDuffTestActivity extends Activity {
/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ImageView yellowCircle = (ImageView)findViewById(R.id.yellowcircle);

        yellowCircle.getDrawable().setColorFilter(0x88ffff00, PorterDuff.Mode.MULTIPLY);
    }
}

Вывод:

enter image description here

Ограничение этого метода заключается в том, что альфа альфа-формы должна быть установлена ​​равной 50% ( "88" в "0x88ffff00" ). Для желтого цвета это хорошо работает, но для других цветов альфа-эффект может быть неприемлем (цвет может выглядеть другим цветом, например, красный становится розовым с низкими значениями альфа на белом фоне). Какой режим смешивания в конечном счете приемлем для вас, зависит от набора цветов, который вы собираетесь использовать, и будет проводить некоторые эксперименты. Также обратите внимание, что цвет фона может влиять на цвета кругов в режиме наложения. В этом примере фон установлен на белый.

Ответ 2

Я сделал еще один пример для 6 объектов.

enter image description here

Ключевые моменты:

  • Метод onDraw не будет переопределяться для представлений объектов, а фон также будет установлен на прозрачность

    setBackgroundColor (Color.TRANSPARENT);

  • Но метод onDraw будет переименован в onDrawEx, который вызывается из Overlay View.

    public void onDrawEx (холст холста) {

  • Наложение вида передаст пользовательский холст для рисования. перед тем, как перейти к просмотру объекта, он сделает необходимый перевод.

        mOverlayView = new View(this){
        @Override
        protected void onDraw(Canvas canvas) {
            Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888);
            Canvas canvasBitmap = new Canvas(bitmap);
            ViewGroup viewGroup = (ViewGroup)getParent();
            for(int i = 0 ; i < viewGroup.getChildCount()-1;i++){
                ObjectView objectView = (ObjectView) viewGroup.getChildAt(i);
                canvasBitmap.save();
                canvasBitmap.translate(objectView.getTranslationX(), objectView.getTranslationY());
                objectView.onDrawEx(canvasBitmap);
                canvasBitmap.restore();
            }
            canvas.drawBitmap(bitmap, 0, 0, new Paint());
        }
    };
    
  • используйте mPaint.setXfermode(новый PorterDuffXfermode (Mode.ADD)); для добавления цветов. Но все объекты должны использовать цвета, такие как 0xFF000030,0xFF0000C0,0xFF003000,0xFF00C000,0xFF300000,0xC00000, тогда только для всех возможных перекрытий мы можем получить разные цвета. это зависит от максимального количества объектов.

        int k = 0 ;
    for(int i = 0 ; i < 2;i++,k++){
        int color = 0xFF000000|(0x000030<<i*2);
        frameLayout.addView(new ObjectView(this,color,k*50,k*50,k), new FrameLayout.LayoutParams(50, 50));
    }
    for(int i = 0 ; i < 2;i++,k++){
        int color = 0xFF000000|(0x003000<<i*2);
        frameLayout.addView(new ObjectView(this,color,k*50,k*50,k), new FrameLayout.LayoutParams(50, 50));
    }
    for(int i = 0 ; i < 2;i++,k++){
        int color = 0xFF000000|(0x300000<<i*2);
        frameLayout.addView(new ObjectView(this,color,k*50,k*50,k), new FrameLayout.LayoutParams(50, 50));
    }
    

Здесь я изменен для поддержки версии 8

использовать

mPaint.setXfermode(new PixelXorXfermode(0x00000000));

для

mPaint.setXfermode(new PorterDuffXfermode(Mode.ADD));

Я использовал параметр компоновки для перевода.

Ответ 3

Простейшим решением, которое я могу думать, было бы просто использовать альфа-канал, установив каждый на 0,5 прозрачности, либо в коде, либо в xml. Затем цвета должны исчезать друг в друга, когда они перекрываются. Это означает, что цвета в неперекрывающихся разделах будут немного затухающими, и в зависимости от того, какой фон у вас за фигурами, может показаться не очень хорошим, чтобы они были абсолютно прозрачными.

Ответ 4

Я создал образец Activity с двумя представлениями DemoDrawShapeActivity, где в view2 я использую canvas.clipPath и canvas.translate

чтобы работать, я устанавливаю минимальную версию sdk 4

enter image description here

protected void onDraw(Canvas canvas) {
    Paint paint = new Paint();
    paint.setColor(Color.RED);
    path2.addCircle(getWidth()/2, getHeight()/2, getWidth()/2, Direction.CCW);
    canvas.drawPath(path2, paint);
    canvas.clipPath(path2);
    canvas.save();
    canvas.translate(-getTranslationX()+view1.getTranslationX(), -getTranslationY()+view1.getTranslationY());

    paint.setColor(Color.BLUE|Color.RED);
    canvas.drawPath(path1, paint);
    canvas.restore();

}

вы можете отредактировать paint.setColor(Color.BLUE | Color.RED); чтобы получить необходимый цвет в соответствии с вашей логикой.

Я использую setTranslationX setTranslationY для перемещения представлений.

        public boolean onTouchEvent(MotionEvent event) {
                switch(event.getActionMasked()){
                case MotionEvent.ACTION_UP:
                    touched[0]=touched[1]=false;
                case MotionEvent.ACTION_DOWN:
                case MotionEvent.ACTION_MOVE:
                    if(touched[1]){
                        view2.setTranslationX(event.getX()-view2.getWidth()/2);
                        view2.setTranslationY(event.getY()-view2.getHeight()/2);
                    }else if(touched[0]){
                        view1.setTranslationX(event.getX()-view1.getWidth()/2);
                        view1.setTranslationY(event.getY()-view1.getHeight()/2);
                        view2.invalidate();
                    }
                }
                return true;
            }

Ответ 5

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

Вот все варианты компоновки http://developer.android.com/reference/android/graphics/PorterDuffXfermode.html

И их объяснения от Mozilla https://developer.mozilla.org/en/Canvas_tutorial/Compositing