التنسيق الشرطي - النسبة المئوية لتحويل اللون

StackOverflow https://stackoverflow.com/questions/25007

  •  09-06-2019
  •  | 
  •  

سؤال

ما هي أسهل طريقة لتحويل نسبة مئوية إلى لون يتراوح من الأخضر (100%) إلى الأحمر (0%)، والأصفر بنسبة 50%؟

أنا أستخدم 32 بت RGB عادي - لذا فإن كل مكون عبارة عن عدد صحيح بين 0 و255.أنا أفعل هذا باستخدام لغة C#، ولكن أعتقد أن اللغة لا تهم كثيرًا بالنسبة لمشكلة كهذه.

بناءً على إجابات ماريوس وأندي، أستخدم الحل التالي:

double red = (percent < 50) ? 255 : 256 - (percent - 50) * 5.12;
double green = (percent > 50) ? 255 : percent * 5.12;
var color = Color.FromArgb(255, (byte)red, (byte)green, 0);

يعمل بشكل مثالي - التعديل الوحيد الذي كان علي إجراؤه من حل Marius هو استخدام 256، مثل (255 - (في المائة - 50) * 5.12 العائد -1 عندما يكون 100%، مما يؤدي إلى ظهور اللون الأصفر لسبب ما في Silverlight (-1، 255، 0) ) -> أصفر ...

هل كانت مفيدة؟

المحلول

لقد قمت بإنشاء هذه الوظيفة في JavaScript.تقوم بإرجاع اللون عبارة عن سلسلة CSS.يأخذ النسبة المئوية كمتغير، مع نطاق من 0 إلى 100.يمكن إجراء الخوارزمية بأي لغة:

function setColor(p){
    var red = p<50 ? 255 : Math.round(256 - (p-50)*5.12);
    var green = p>50 ? 255 : Math.round((p)*5.12);
    return "rgb(" + red + "," + green + ",0)";
}

نصائح أخرى

ما تريد القيام به على الأرجح هو تعيين بعض النقاط من 0% إلى 100% في مساحة ألوان HSV أو HSL.من هناك يمكنك استيفاء الألوان (ويصادف أن اللون الأصفر يقع بين الأحمر والأخضر :) و تحويلها إلى RGB.سيعطيك ذلك تدرجًا لطيفًا بين الاثنين.

بافتراض أنك ستستخدم اللون كمؤشر للحالة ومن منظور واجهة المستخدم، ربما لا تكون هذه فكرة جيدة، نظرًا لأننا سيئون جدًا في رؤية تغييرات صغيرة في اللون.لذا فإن تقسيم القيمة، على سبيل المثال، إلى ثلاث إلى سبع مجموعات من شأنه أن يمنحك اختلافات أكثر وضوحًا عندما تتغير الأمور، على حساب بعض الدقة (والتي على الأرجح لن تتمكن من تقديرها على أي حال).

لذا، بغض النظر عن الرياضيات، في النهاية أوصي بجدول بحث يتضمن الألوان التالية حيث تكون v هي قيمة الإدخال:

#e7241d for v <= 12%
#ef832c for v > 12% and v <= 36%
#fffd46 for v > 36% and v <= 60%
#9cfa40 for v > 60% and v <= 84%
#60f83d for v > 84%

لقد تم تحويلها بسذاجة شديدة من قيم HSL (0.0، 1.0، 1.0)، (30.0، 1.0، 1.0)، (60.0، 1.0، 1.0)، (90.0، 1.0، 1.0)، (120.0، 1.0، 1.0)، و قد ترغب في ضبط الألوان إلى حد ما لتناسب أغراضك (البعض لا يحب أن اللونين الأحمر والأخضر ليسا "نقيين").

لطفا أنظر:

في الكود الزائف.

  • من 0 إلى 50% ستكون القيمة السداسية الخاصة بك هي FFxx00 حيث:

    XX = ( Percentage / 50 ) * 255 converted into hex.
    
  • من 50 إلى 100 ستكون القيمة السداسية الخاصة بك هي xxFF00 حيث:

    XX = ((100-Percentage) / 50) * 255 converted into hex.  
    

نأمل أن يساعد وهو مفهوم.

يعد هذا حلاً جميلاً ونظيفًا يعمل على تحسين الإجابة المقبولة حاليًا بثلاث طرق:

  1. يزيل الرقم السحري (5.12)، مما يسهل متابعة الكود.
  2. لن ينتج خطأ التقريب الذي يمنحك -1 عندما تكون النسبة 100%.
  3. يسمح لك بتخصيص الحد الأدنى والحد الأقصى لقيم RGB التي تستخدمها، بحيث يمكنك إنتاج نطاق أفتح أو أغمق من rgb(255, 0, 0) البسيط - rgb(0, 255, 0).

الكود الموضح هو C# ولكن من السهل تكييف الخوارزمية مع أي لغة أخرى.

private const int RGB_MAX = 255; // Reduce this for a darker range
private const int RGB_MIN = 0; // Increase this for a lighter range

private Color getColorFromPercentage(int percentage)
{
    // Work out the percentage of red and green to use (i.e. a percentage
    // of the range from RGB_MIN to RGB_MAX)
    var redPercent = Math.Min(200 - (percentage * 2), 100) / 100f;
    var greenPercent = Math.Min(percentage * 2, 100) / 100f;

    // Now convert those percentages to actual RGB values in the range
    // RGB_MIN - RGB_MAX
    var red = RGB_MIN + ((RGB_MAX - RGB_MIN) * redPercent);
    var green = RGB_MIN + ((RGB_MAX - RGB_MIN) * greenPercent);

    return Color.FromArgb(red, green, RGB_MIN);
}

ملحوظات

فيما يلي جدول بسيط يوضح بعض قيم النسب المئوية، والنسب الحمراء والخضراء المقابلة التي نريد إنتاجها:

VALUE   GREEN    RED       RESULTING COLOUR
 100%    100%     0%       green
  75%    100%    50%       yellowy green
  50%    100%   100%       yellow
  25%     50%   100%       orange
   0%      0%   100%       red

نأمل أن تتمكن من رؤية ذلك بوضوح تام

  • القيمة الخضراء هي 2x قيمة النسبة المئوية (لكن بحد أقصى 100)
  • الأحمر هو العكس:2x (100 - نسبة مئوية) (ولكن بحد أقصى 100)

لذلك تقوم الخوارزمية الخاصة بي بحساب القيم من جدول يبدو مثل هذا ...

VALUE   GREEN    RED
 100%    200%     0%
  75%    150%    50%
  50%    100%   100%
  25%     50%   150%
   0%      0%   200%

...ومن ثم يستخدم Math.Min() لجعلهم يصلون إلى 100٪.

لقد كتبت وظيفة بايثون هذه بناءً على كود جافا سكريبت.يستغرق نسبة مئوية كعلامة عشرية.لقد قمت أيضًا بتربيع القيمة للحفاظ على الألوان أكثر احمرارًا لفترة أطول على مقياس النسبة المئوية.قمت أيضًا بتضييق نطاق الألوان من 255 إلى 180 لإعطاء لون أحمر وأخضر داكن عند كل طرف.يمكن اللعب بها لإعطاء ألوان جميلة.أود أن أضيف لمسة برتقالية في المنتصف، لكن يجب أن أواصل العمل المناسب، يا صاح.

def getBarColour(value):
    red = int( (1 - (value*value) ) * 180 )
    green = int( (value * value )* 180 )

    red = "%02X" % red
    green = "%02X" % green

    return '#' + red + green +'00'

نظرًا لأن اللون الأصفر هو مزيج من اللونين الأحمر والأخضر، فمن المحتمل أن تبدأ به #F00 ثم حرك اللون الأخضر لأعلى حتى تصل #FF0, ، ثم مرر اللون الأحمر إلى الأسفل #0F0:

for (int i = 0; i < 100; i++) {
    var red = i < 50
        ? 255
        : 255 - (256.0 / 100 * ((i - 50) * 2));
    var green = i < 50
        ? 256.0 / 100 * (i * 2)
        : 255;
    var col = Color.FromArgb((int) red, (int) green, 0);
}

أستخدم إجراءات Python التالية للمزج بين الألوان:

def blendRGBHex(hex1, hex2, fraction):
    return RGBDecToHex(blendRGB(RGBHexToDec(hex1), 
                                RGBHexToDec(hex2), fraction))

def blendRGB(dec1, dec2, fraction):
    return [int(v1 + (v2-v1)*fraction) 
        for (v1, v2) in zip(dec1, dec2)]

def RGBHexToDec(hex):
    return [int(hex[n:n+2],16) for n in range(0,len(hex),2)]

def RGBDecToHex(dec):
    return "".join(["%02x"%d for d in dec])

على سبيل المثال:

>>> blendRGBHex("FF8080", "80FF80", 0.5)
"BFBF80"

يقوم روتين آخر بتغليف هذا لمزج بشكل جيد بين القيم الرقمية لـ "التنسيق الشرطي":

def colourRange(minV, minC, avgV, avgC, maxV, maxC, v):
    if v < minV: return minC
    if v > maxV: return maxC
    if v < avgV:
        return blendRGBHex(minC, avgC, (v - minV)/(avgV-minV))
    elif v > avgV:
        return blendRGBHex(avgC, maxC, (v - avgV)/(maxV-avgV))
    else:
        return avgC

لذلك، في حالة جوناس:

>>> colourRange(0, "FF0000", 50, "FFFF00", 100, "00FF00", 25)
"FF7F00"

الحل الخاص بي لـ ActionScript 3:

var red:Number = (percentage <= 50) ? 255 : 256 - (percentage - 50) * 5.12;
var green:Number = (percentage >= 50) ? 255 : percentage * 5.12;

var redHex:Number = Math.round(red) * 0x10000;
var greenHex:Number = Math.round(green) * 0x100;

var colorToReturn:uint = redHex + greenHex;

نظرًا لأنها R-G-B، فإن الألوان تتراوح من القيم الصحيحة -1 (الأبيض)، إلى -16777216 للأسود.مع الأحمر والأخضر والأصفر في مكان ما في منتصف ذلك.الأصفر هو في الواقع -256، بينما الأحمر هو -65536 والأخضر هو -16744448.لذا فإن اللون الأصفر في الواقع ليس بين الأحمر والأخضر في تدوين RGB.أعلم أنه من حيث الطول الموجي، فإن اللون الأخضر على جانب واحد، والأحمر على الجانب الآخر من الطيف، لكنني لم أر قط هذا النوع من الترميز المستخدم في أجهزة الكمبيوتر، لأن الطيف لا يمثل جميع الألوان المرئية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top