تطبق globalAlpha على الرسم الجديد؛ تكراره يغير نتيجة تركيبه فوق ما سبقه. في تجربتنا اختلف البكسل بعد مرتين رغم ثبات القيمة 0.25. [1]
الخلاصة السريعة
ثبتنا الظروف قبل المقارنة
أنشأنا لوحة صغيرة بعرض وارتفاع 20، واخترنا خلفية بيضاء أو زرقاء معتمة. فوقها رسمنا مستطيلا أحمر في الموضع نفسه، مرة أو مرتين. أخذنا العينة من نقطة داخل المستطيل، لا من حافته، وبدأنا لوحة جديدة لكل حالة.
سجلنا التنفيذ في Edge 155.0.4283.45. أعاد السياق مساحة sRGB ونوع اللون unorm8. اللون الأحمر والخلفية من اختيارنا، ولم نحمّل صورة خارجية أو نقس لون شاشة أو نرسل بيانات. أبقينا النقطة الواقعة خارج المستطيل للمقارنة مع لون الخلفية.
تقرأ getImageData() بيانات منطقة من اللوحة. اخترنا rgba-unorm8: أربع مكونات RGBA بثمانية بتات لكل مكون، داخل Uint8ClampedArray. [4]
ما الذي تغير بعد الرسم الثاني؟
فوق الأبيض، أعادت القراءة أولا [255,191,191,255]، ثم [255,143,143,255]. بقي المكون الأحمر عند 255، بينما انخفض الأخضر والأزرق في القراءة الثانية. لا نحتاج إلى وصف انطباعي مثل «أشد حمرة» وحده؛ نستطيع تحديد أي أعداد تغيرت.
فوق الأزرق رأينا [64,0,191,255] بعد مرة، ثم [112,0,143,255] بعد مرتين. إذن لم تعط قيمة الرسم نفسها النتيجة نفسها على الخلفيتين. وفي الحالات الأربع بقيت القراءة خارج المستطيل مساوية لخلفيتها الأصلية، وهو فحص موضعي إضافي لتجربتنا.
الجدول يعرض بايتات فعلية سجلناها. الرقم الأخير 255 هو ألفا البكسل الناتج في كل صف؛ ليس العدد الذي وضعناه في globalAlpha. قيمة الرسم المختارة كانت 0.25 طوال مرات رسم الأحمر، وقد سجلناها منفصلة عن المخرجات.
| الخلفية | المرات | RGBA المقاس |
|---|---|---|
| بيضاء | 1 | [255,191,191,255] |
| بيضاء | 2 | [255,143,143,255] |
| زرقاء | 1 | [64,0,191,255] |
| زرقاء | 2 | [112,0,143,255] |
احسب مساهمة الخلفية
لمصدر ألفاه 0.25 فوق خلفية معتمة، تختزل معادلة source-over إلى: اللون الجديد = 0.25 × لون المصدر + 0.75 × لون الخلفية. وألفا الناتج = 0.25 + 0.75 = 1. [3]
بعد مرتين يبقى وزن الخلفية 0.75 × 0.75 = 0.5625، أي 9/16، ويكون وزن الأحمر 7/16. لذلك لا نجمع قيمتي الرسم ببساطة لنقرر أن مساهمة الأحمر نصف اللون. [3]
للأزرق، حسبنا مستقلا القيم المثالية: بعد مرة [63.75,0,191.25]؛ وبعد مرتين [111.5625,0,143.4375]. أكبر فرق مطلق عن القياس 0.4375 في هذه الحالات. [3]
ميزنا الحساب من القياس. صيغة القراءة التي اخترناها تعيد مكونات بثمانية بتات؛ الأعداد الكسرية السابقة ليست البايتات التي سجلها برنامجنا. [4]

أعد التجربة بقيم معلنة
الشيفرة التالية تنشئ لوحة مستقلة لكل استدعاء. نفذنا الاستدعاءات الأربعة الموجودة في نهايتها، وقارناها بالجدول. الأرقام 10 و10 تحدد نقطة العينة المختارة، وحجم المنطقة المقروءة بكسل واحد. نتيجة الاستدعاء قائمة، وليست صورة شاشة.
للمقارنة، غيّر عاملا واحدا واحتفظ بالبقية. يمكنك إبقاء الخلفية الزرقاء ثم مقارنة مرة بمرتين، أو إبقاء عدد المرات واحدا ومقارنة الخلفيتين. سجل اسم الخلفية وعدد المرات بجانب الناتج كي لا تفقد شرط التجربة عندما تنقل القائمة.
function sample(bg,n) {
const c =
document.createElement("canvas");
c.width=c.height=20;
const x = c.getContext("2d",
{colorSpace:"srgb"});
x.globalAlpha=1;
x.fillStyle=bg;
x.fillRect(0,0,20,20);
x.globalCompositeOperation =
"source-over";
x.globalAlpha=0.25;
x.fillStyle="red";
for(let i=0;i<n;i++)
x.fillRect(2,2,16,16);
return [...x.getImageData(10,10,1,1,
{colorSpace:"srgb",
pixelFormat:"rgba-unorm8"}).data];
}
console.log(sample("white",1));
console.log(sample("white",2));
console.log(sample("blue",1));
console.log(sample("blue",2));ما الذي لا تقوله الأرقام؟
لم نفحص ألوانا شفافة في مصدر خارجي أو ملفا مصدرا. الخلفية في حسابنا معتمة، والعينة داخل شكل ممتلئ؛ تغيير هذه الشروط يحتاج إلى تجربة جديدة. كذلك لم نقارن متصفحات متعددة، فلا نجعل جدولنا وعدا ببايتات متطابقة في كل بيئة.
يفصل سجلنا بين ثلاث خانات: قيمة الرسم التي ضبطناها، واللون الذي حسبناه، والبايتات التي قرأناها. إبقاء الخانات منفصلة منعنا من تسمية 0.25 ألفا الناتج، أو نقل كسر من الحساب إلى الجدول على أنه مخرج نفذه المتصفح.
المراجع
- MDN — globalAlpha
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalAlpha - MDN — globalCompositeOperation
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation - W3C — Compositing and Blending
https://www.w3.org/TR/compositing-1/ - MDN — getImageData
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/getImageData
أُعدّ هذا المقال بمساعدة الذكاء الاصطناعي وراجعته أدوات ذكاء اصطناعي. لا يُنسب إلى مراجع بشري أو خبير مستقل. منهجية المحتوى.
