Как установить комбинированный цвет для перекрываемой области двух разных цветовых объектов?
Я создаю различные пользовательские представления с двумя разными цветами. Согласно моим функциям приложения пользователь будет перетаскивать эти объекты на экране, когда перетаскивание объектов будет перекрывать друг друга. Я хочу дифференцировать перекрываемую область, как установить комбинированный цвет для перекрываемой области.
Посмотрите на изображение ниже. Здесь я использую холст для создания этих пользовательских представлений. Два круга - это два разных вида.
![enter image description here]()
EDIT: Если я использую opacity 128, я могу видеть цвет фона, но мне нужен цвет комбинации совпадающих объектов.
Ответы
Ответ 1
Смешивание цветов, которое вы ищете, иногда называется Интуитивное смешивание цветов, или RYB Цвет Система:
RYB
лицензия CC
Цитата из эта статья Натана Госсетта и Баокуана Чена по алгоритмам интуитивного смешения цветов суммирует, как работает интуитивная система цвета:
"В этой модели красные, желтые и синие используются как чистые первичные цвета. Красное и желтое смешивание для формирования оранжевого, желтого и синего смесей с образованием зеленого, синего и красного микса для формирования фиолетового [...]. Это цвета, которые неквалифицированный зритель ожидал бы получить с помощью детской краски [...]. Кроме того, многие люди не думают о Белом как о смеси всех цветов, а о том, как отсутствие цвета (пустой холст). Более распространенное предположение заключалось бы в том, что смешивание многих цветов вместе приведет к мутному темно-коричневому цвету".
RYB не реализован в режимах Android blend и не может быть реально имитирован путем смешивания альфа/разных режимов смешивания.
Большинство приложений компьютерной графики используют цветовые пространства RGB или CMYK:
CMYK
лицензия CC
CMY основан на субтрактивном цвете. Субтрактивное смешивание цветов означает, что, начиная с белого цвета, при добавлении цвета результат становится темнее. CMYK используется для смешивания цветов в изображениях, предназначенных для печати, например. Photoshop и Illustrator.
RGB
лицензия 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
Ответ 6
Вы можете воспользоваться этой помощью -
http://www.learnopengles.com/android-lesson-five-an-introduction-to-blending/
и
www.pushing-pixels.org/category/android/page/6