تتحدث هذه المقالة عن كيفية استخدام القماش لرسم تأثير مطر جميل، فلنلقي نظرة على التأثير النهائي أولاً.
الاداءات
يشرحانظر إلى الصورة لتحليل التأثيرات التي نحتاج إلى تحقيقها.
1. تأثير سقوط قطرة المطر، حرك الماوس للتحكم في اتجاه السقوط
2. تسقط قطرات المطر وتنتشر في قطرات ماء صغيرة، اتجاه حركة قطرات الماء الصغيرة هو نفس اتجاه حركة الماوس.
3. تقع قطرات المطر ضمن نطاق معين من إحداثيات الفأرة وتنتشر إلى قطرات ماء صغيرة، وبالمثل، فإن اتجاه حركة قطرات الماء الصغيرة هو نفس اتجاه حركة الفأرة.
حسنًا، دعونا نقسم التأثير بأكمله تقريبًا إلى ثلاثة تأثيرات، ونحقق هذه التأثيرات الثلاثة، وقد انتهينا.
دعونا نفعل ذلك خطوة بخطوة.
1. تأثير سقوط قطرة المطر، حرك الماوس للتحكم في اتجاه السقوطفكرة تحقيق التأثير بأكمله هي،
الوقت الأولياستخدم مصفوفة لحفظ كائنات قطرة المطر.
يحتوي كائن قطرة المطر على سمات مختلفة تستخدم لتمثيل الإحداثي x لقطرة المطر، والإحداثي y، والطول، وسرعة السقوط، واللون، وعلامة لتحديد ما إذا كان سيتم حذفه.
عند تحديث الرسوم المتحركةأضف عددًا معينًا من كائنات قطرة المطر إلى المصفوفة، ثم اجتاز المصفوفة، وقم بتعديل إحداثي x وإحداثي y لكل كائن قطرة مطر، واستخدم القماش لرسم نقطتين بناءً على إحداثيات كائن قطرة المطر، والتي تشكل معًا قطرة مطر.
لذا فإن المفتاح لتحقيق التأثير هو الإحداثيات
عند تهيئة قطرة المطرالإحداثي x لقطرة المطر: رقم عشوائي
إحداثيات قطرة المطر: -100، وذلك للسماح بدخول قطرات المطر من خارج المنطقة المرئية
عند تحديث الرسوم المتحركة إحداثيات قطرة المطر x:原x坐标的值+ speed * speedx
السرعة هي قيمة ثابتة تشير إلى سرعة سقوط قطرات المطر،
speedx هو متغير يتعلق باتجاه حركة الماوس، speedx = speedx + (maxspeedx - speedx) / 50
وmaxspeedx هي القيمة التي يتم الحصول عليها بناءً على اتجاه حركة الماوس.
maxspeedx = (e.clientX - canvasEl.clientWidth / 2) / (canvasEl.clientWidth / 2)
،
e.clientX: قيمة مسافة الماوس إلى يسار المنطقة المرئية
CanvasEl.clientWidth: عرض المنطقة المرئية بأكملها
بمعنى آخر، speedx هي قيمة تقترب تدريجيًا من maxspeedx
نطاق قيمة maxspeedx هو -1 إلى 1. كلما اقتربت قيمته من -1، كان الاتجاه أبعد إلى اليسار. كلما اقتربت القيمة من 1، كان الاتجاه أبعد إلى اليمين.
لماذا لا تستخدم فقط maxspeedx؟
وذلك لمنع قطرات المطر من تغيير اتجاهها بهذه السرعة، فبدلاً من تغيير الاتجاه فورًا بعد تغيير الماوس، يجب أن يكون هناك تأخير بسيط لجعله يبدو أفضل.
إذا كنت تستخدم maxspeedx، فإن التأثير سيكون مثل هذا
إذا كنت تستخدم speedx، فإن التأثير سيكون مثل هذا
إحداثي قطرة المطر y:原y坐标的值+ speed
السرعة هي نفسها المذكورة في الإحداثي x أعلاه وهي قيمة ثابتة تمثل سرعة سقوط قطرات المطر.
حسنًا، أخيرًا، أستخدم القماش لرسم نقطتين وفقًا لإحداثيات كائن قطرة المطر، ثم قم بتوصيلهما، ويتم رسم قطرة المطر.
إحداثيات النقطة الأولى بسيطة نسبيًا، يمكنك الحصول مباشرة على الإحداثيات x والإحداثيات y لكائن قطرة المطر، وهو إحداثيات هذه النقطة.
إحداثيات النقطة الثانية:
x坐标= 雨滴x坐标的值+ 雨滴长度* speedx
y坐标= 雨滴y坐标的值+ 雨滴长度
وأخيرًا، قم بتوصيل هاتين النقطتين، وسيكون هناك خط، وهو قطرة مطر.
عند ضبط الإحداثي x، يتم استخدام السرعة المتغيرة مرة أخرى لجعل اتجاه قطرة المطر واتجاه سقوط قطرة المطر متساويين.
عندما لا يتم استخدام speedx، يكون الأمر هكذا
عند استخدام speedx، هذا هو الحال
2. تسقط قطرات المطر وتنتشر في قطرات ماء صغيرة، اتجاه حركة قطرات الماء الصغيرة هو نفس اتجاه حركة الماوس.الفكرة هنا هي في الواقع مشابهة إلى حد ما للتأثير أعلاه.
الوقت الأولياستخدم مصفوفة لحفظ كائنات قطرة الماء الصغيرة.
قطرة الماء الصغيرة هي في الواقع قوس دائري.
يحتوي كائن قطرة الماء الصغيرة على سمات مختلفة تستخدم لتمثيل إحداثيات قطرة الماء الصغيرة، وسرعة حركة المحور السيني، وسرعة حركة المحور الصادي، ونصف قطر الدائرة، وعلم لتحديد ما إذا كان سيتم حذفه.
عند تحديث الرسوم المتحركةأضف عددًا معينًا من كائنات قطرة الماء الصغيرة إلى المصفوفة، ثم اجتاز المصفوفة، وقم بتعديل إحداثي x وإحداثي y لكل كائن قطرة ماء صغيرة، واستخدم القماش لرسم قوس بناءً على سمات الإحداثيات وسمات نصف القطر للكائنات الصغيرة كائن قطرة الماء.
ولذلك، فإن التركيز على تحقيق التأثير لا يزال على الإحداثيات
عند تهيئة قطرة ماء صغيرةتظهر قطرات الماء الصغيرة عندما تختفي قطرة المطر، لذا فإن إحداثيات قطرة الماء الصغيرة تعتمد أيضًا على إحداثيات قطرة المطر. عند حذف قطرة مطر، ستظهر بعض قطرات الماء الصغيرة، ويكون الاتجاه المتحرك لقطرة الماء الصغيرة أيضًا اتجاه سقوط قطرة المطر. Mouse اتجاه الحركة هو نفسه، لذا ستظل هناك حاجة إلى السرعة المتغيرة المذكورة أعلاه.
小水珠x坐标: 删除的雨滴x坐标+ 删除的雨滴长度* speedx
小水珠y坐标:删除的雨滴y坐标+ 删除的雨滴长度
نحتاج هنا إلى استخدام خاصيتين لجسم قطرة الماء الصغيرة vx (سرعة تغير قيمة المحور السيني) وvy (سرعة تغير قيمة المحور الصادي).
الإحداثي السيني لقطرة الماء الصغيرة
vx = vx + speedx / 2
小水珠的x坐标=原x坐标+ vx
,
Speedx: متغير يتعلق بإتجاه حركة الماوس المذكورة أعلاه، والوظيفة هنا هي التحكم في اتجاه حركة قطرات الماء الصغيرة في نفس اتجاه الاتجاهات الأخرى.
speedx / 2
، الغرض من القسمة على 2 هو جعل المسافة المتحركة لقطرات الماء الصغيرة على المحور السيني أقصر وتبدو أكثر واقعية.
الإحداثي y لقطرة الماء الصغيرة
vy = vy + gravity
小水珠的y坐标= 原y坐标+ vy;
vy: رقم سالب
الجاذبية: الجاذبية، رقم موجب، تم ضبطه على 0.5 في الكود الكامل
نظرًا لأن الإحداثي y الأصلي هو رقم موجب، فإن قيمة الإحداثي y لقطرة الماء الصغيرة ستنخفض أولاً ثم تزيد، وذلك لتحقيق التأثير المتمثل في ارتفاع قطرة الماء الصغيرة أولاً ثم انخفاضها
أخيرًا، ما عليك سوى استخدام القماش لرسم قوس استنادًا إلى سمات الإحداثيات وسمات نصف القطر لقطرة الماء الصغيرة، ويكون القوس عشوائيًا.
3. تقع قطرات المطر ضمن نطاق معين من إحداثيات الفأرة وتنتشر إلى قطرات ماء صغيرة، وبالمثل، فإن اتجاه حركة قطرات الماء الصغيرة هو نفس اتجاه حركة الفأرة.
من السهل تحديد حجم الدائرة في الصورة. افترض أن نصف قطر الدائرة هو 35. يمكننا الحصول على إحداثيات الفأرة بأخذ إحداثيات الفأرة كمركز للدائرة و35 كنصف القطر يمكننا تحديد حجم الدائرة.
النقطة الأساسية هي كيفية الحكم على ما إذا كانت قطرات المطر قد دخلت هذا النطاق، وهذا يتطلب استخدام نظرية فيثاغورس.
نظرًا لأن قطرة المطر عبارة عن خط يربط بين نقطتين لمعرفة ما إذا كانت قطرة المطر قد دخلت هذا النطاق، فأنت بحاجة إلى النظر إلى إحداثيات النقطة الموجودة أسفل قطرة المطر. ما هي مسافة الخط المستقيم من الفأرة هو طول قطعة الخط أ ب في الصورة.
نظرية فيثاغورس: مجموع مربعي ضلعي المثلث القائم الزاوية يساوي مربع الوتر.
AB = Math.sqrt(BC BC + AC AC)
BC = الإحداثي x لقطرة المطر - الإحداثي x للماوس
AC = تنسيق قطرة المطر y - تنسيق y بالماوس
يتم استخدام طريقة Math.sqrt() لحساب الجذر التربيعي لرقم ما
وبعد أن عرفنا مسافة الخط المستقيم من قطرة المطر إلى الفارة، قارنها بنصف قطر الدائرة، فإن كانت أكبر من نصف القطر، فهي ليست ضمن المدى، وإلا فهي كذلك.
إذا كان ضمن النطاق، فاحذف قطرات المطر وارسم بعض قطرات الماء الصغيرة.
تلخيص
ولتحقيق هذا التأثير تكمن المشكلة في الاتجاه، واتجاه قطرات المطر، واتجاه تساقط قطرات المطر، واتجاه حركة قطرات الماء الصغيرة، وهذه كلها مرتبطة باتجاه حركة الفأرة. استخدم القماش لرسم الخطوط بشكل مستمر بناءً على المسافة.
رمز كامل
<!doctype html><html lang=en><head> <meta charset=UTF-8> <style> * { هامش: 0; } </style></head><body> <canvas id =canvas style=position:Absolute; height: 100% width:100%;></canvas> <script> window.onload = main(); { // احصل على عنصر اللوحة القماشية var CanvasEl = document.getElementById('canvas'); var ctx = CanvasEl.getContext('2d'); // لون خلفية لوحة القماش var borderColor = '#000'; عرض المنطقة المرئية CanvasEl width = CanvasEl.clientWidth; // ارتفاع اللوحة القماشية يساوي ارتفاع المنطقة المرئية CanvasEl.height = CanvasEl.clientHeight; بعد سقوط قطرات المطر، تتناثر إلى قطرات ماء صغيرة على شكل أقواس var dropList = []; // الجاذبية // بعد سقوط قطرات المطر، تتناثر قطرات الماء الصغيرة أولاً ثم تسقط، وذلك بسبب الجاذبية بشكل أساسي بسبب المتغيرات var Gravity = 0.5; // احفظ مصفوفة قطرات المطر // كل قطرة مطر عبارة عن خط مرسوم var linelist = []; // mousePos[0 ] يمثل قيمة المحور السيني، يمثل mousePos[1] قيمة المحور الصادي var mousePos = [0, 0]; // بعد الماوس، ستختفي قطرات المطر في منطقة حجم mouseDis، مما يشكل تأثيرًا مبعثرًا // مع وجود mousePos كمركز للدائرة، يكون mouseDis هو نصف القطر، وسوف تنتشر قطرات المطر داخل هذا النطاق وتشكل العديد من قطرات الماء الصغيرة var mouseDis = 35; // قم بتحديث الرسم المتحرك مرة واحدة وارسم قطرات المطر lineNum كلما كانت قيمة lineNum أكبر ، كلما كان المطر أكثر كثافة lineNum = 3; // اتبع اتجاه الماوس لتغيير اتجاه المطر // بعد تحرك الماوس، سيتغير اتجاه المطر ببطء، اعتمادًا بشكل أساسي على السرعة المتغيرةx var speedx = 0; القيمة التي يمكن أن تأخذها speedx // عندما يكون speedx = maxspeedx، سيتغير اتجاه المطر فورًا مع اتجاه حركة الماوس var maxspeedx = 0; // عندما يتغير حجم الصفحة، قم بإعادة ضبط حجم اللوحة القماشية window.onresize = function () { CanvasEl.width = CanvasEl.clientWidth; يسار المنطقة المرئية لنافذة المتصفح المسافة // e.clientY هي المسافة من أعلى المنطقة المرئية لنافذة المتصفح mousePos[0] = e.clientX mousePos[1] = e.clientY; // اضبط قيمة maxspeedx من خلال موضع الماوس، نطاق القيمة هو -1 إلى 1 // قيمة maxspeedx مرتبطة بـ // 1. اتجاه قطرة المطر // 2. اتجاه سقوط قطرة المطر // 3. السرعة التي يتغير بها اتجاه سقوط قطرات المطر مع اتجاه حركة الماوس // 4. الاتجاه المتحرك لقطرات الماء الصغيرة // كلما اقتربت القيمة من 1، كان الاتجاه أبعد إلى اليمين // كلما اقتربت القيمة من -1، كان الاتجاه أبعد إلى اليسار maxspeedx = (e.clientX - CanvasEl.clientWidth / 2) / (canvasEl.clientWidth / 2)؛ // وفقًا للمعلمات، قم بإرجاع لون rgb المستخدم لتعيين لون قطرات المطر getRgb(r, g, b) { return rgb( + r + , + g + , + b + } // رسم قطرة مطر (خط) function createLine(e) { // إنشاء طول قطرة المطر بشكل عشوائي var temp = 0.25 * (50 + Math.random() * 100); // كائن خطي يمثل قطرة المطر var line = { // سرعة سقوط قطرة المطر: 5.5 * (Math.random() * 6 + 3)، / / تحديد ما إذا كنت تريد الحذف، إذا كانت القيمة صحيحة، احذفها die: false، // إحداثيات قطرة المطر x posx: e، // إحداثيات قطرة المطر y posy: -50، // طول قطرة المطر h: temp, // لون لون قطرات المطر: getRgb(Math.floor(temp * 255 / 75), Math.floor(temp * 255 / 75), Math.floor(temp * 255 / 75)) }; كائن الخط (قطرة المطر) المضاف إلى المصفوفة التي تحتوي على قطرات المطر linelist.push(line); ارسم قطرة ماء صغيرة (قطرات الماء الصغيرة بعد تفريق قطرات المطر هي أقواس) function createDrop(x, y) { // كائن قطرة يمثل قوسًا var drop = { // تحديد ما إذا كنت تريد الحذف أم لا، القيمة إذا كانت صحيحة، احذف يموت: خطأ، // إحداثي x لمركز القوس posx: x، // إحداثي y لمركز القوس posy: y، // vx يمثل السرعة التي تتغير بها قيمة المحور x vx: (Math.random ( ) - 0.5) * 8, // vy يمثل السرعة التي تتغير بها قيمة المحور y. نطاق القيمة هو: -3 إلى -9 vy: Math.random() * (-6) - 3, // The. نصف قطر القوس: Math Random() * 1.5 + 1 }; return drop; } // ارسم عددًا معينًا من قطرات الماء الصغيرة function madedrops(x, y) { // قم بإنشاء رقم بشكل عشوائي //maxi يمثل عدد قطرات الماء الصغيرة التي سيتم رسمها varmaxi = Math.floor(Math.random() * 5 + 5); for (var i = 0; i <maxi; i++) { dropList.push(createDrop(x, y) } } // ابدأ في استدعاء وظيفة التحديث لتحديث الرسوم المتحركة window.requestAnimationFrame(update); // تحديث وظيفة الرسوم المتحركة () { // إذا كان المصفوفة التي تحتوي على قطرات الماء الصغيرة تحتوي على محتوى if (dropList.length > 0) { // اجتياز المصفوفة التي تحتوي على قطرات ماء صغيرة dropList.forEach(function (e) { // Set e.vx، يمثل vx سرعة تغيير الإحداثيات x // (speedx)/2 is من أجل، اجعل المسافة المتحركة لقطرات الماء الصغيرة على المحور السيني أقصر وتبدو أكثر واقعية // أيضًا اجعل الاتجاه المتحرك لقطرات الماء الصغيرة هو نفس اتجاه قطرات المطر، واتجاه سقوط قطرات المطر، و الاتجاه المتحرك للماوس e.vx = e.vx + (speedx / 2); e.posx = e.posx + e.vx; // Set e.vy, vy يمثل سرعة تغيير إحداثي y // نطاق e.vy هو -3 إلى -9، وفي هذا الوقت يجب أن تكون قيمة e.posy (إحداثي y) موجبة، وبالتالي فإن قيمة e.posy ستنخفض أولاً ثم تزيد // أي أن قطرات المطر سوف تتفرق إلى قطرات ماء صغيرة، وسوف ترتفع قطرات الماء الصغيرة أولاً ثم بعد ذلك سقوط e.vy = e.vy + الجاذبية؛ + e.vy; // إذا كان الإحداثي y لقطرة الماء الصغيرة أكبر من ارتفاع المنطقة المرئية، فاضبط سمة القالب على القيمة الحقيقية // إذا تجاوزت قطرة الماء الصغيرة المنطقة المرئية، فاحذفها if (e. posy > CanvasEl.clientHeight) { e .die = true } }); } // حذف عضو المصفوفة الذي تكون سمة القالب صحيحة // حذف قطرات الماء الصغيرة خارج المنطقة المرئية for (var i = dropList.length - 1 ; أنا >= 0; (dropList[i].die) { dropList.splice(i, 1); } } // اضبط سرعة تغيير اتجاه المطر، نطاق القيمة: -1 إلى 1 // عندما يكون speedx = maxspeedx، سيتغير اتجاه المطر speedx مباشرة أثناء تحرك الماوس الاتجاه = speedx + (maxspeedx - speedx) / 50; // ارسم عددًا معينًا من قطرات المطر بناءً على قيمة lineNum for (var i = 0; i < lineNum; i++) { // استدعاء وظيفة createLine، المعلمة هي إحداثي x لقطرة المطر createLine(Math.random() * 2 * CanvasEl.width - (0.5 * CanvasEl.width) } // تعيين خط النهاية، أي تنتشر قطرات المطر لتشكل العديد من قطرات الماء الصغيرة الموضع var endLine = CanvasEl.clientHeight - Math.random() * CanvasEl.clientHeight / 5; اجتياز المصفوفة التي تحمل قطرات المطر linelist.forEach(function (e) { // استخدم نظرية فيثاغورس لتحديد النطاق الذي ستنتشر فيه قطرات المطر لتشكل قطرات ماء صغيرة // e.posx + speedx * eh هو الإحداثي x لـ قطرة المطر/ / e.posy + eh هو الإحداثي y لقطرة المطر var dis = Math.sqrt(((e.posx + speedx * eh) - mousePos[0]) * ((e.posx + speedx * eh) - mousePos[0]) + (e.posy + eh - mousePos[1]) * (e.posy + eh - mousePos[1])); // إذا كان في منطقة mouseDis، فاحذف قطرة المطر وارسمها بعض قطرات الماء الصغيرة (الأقواس) // أدرك تأثير لمس الفأرة لقطرات المطر وتشتت قطرات المطر إلى قطرات ماء صغيرة if (dis < mouseDis) { // احذف قطرات المطر e.die = true; // Draw بعض قطرات الماء الصغيرة (قوس دائري) madedrops(e.posx + speedx * eh, e.posy + eh); } // إذا تجاوزت قطرات المطر خط النهاية، فاحذف قطرات المطر وارسم بعض قطرات الماء الصغيرة (الأقواس) if ((e.posy + eh) > endLine) { e.die = true; madedrops(e.posx + speedx * eh, e.posy + eh } // إذا كان الإحداثي y لقطرة المطر أكبر من ارتفاع المنطقة المرئية، فاضبط القالب سمة صحيحة // إذا تجاوزت قطرة المطر المنطقة المرئية، فاحذفها if (e.posy >= CanvasEl.clientHeight) { e.die = true } else { // قم بزيادة قيمة إحداثي y لقطرة المطر تدريجيًا e.posy = e. posy + e.speed ; // تغيير إحداثي x لقطرة المطر // * يتم استخدام speedx للتحكم في اتجاه سقوط قطرة المطر // اجعل اتجاه سقوط قطرة المطر هو نفس اتجاه حركة الماوس e.posx = e .posx + e.speed * speedx } }); احذف أعضاء المصفوفة الذين تكون سمة القالب الخاصة بهم صحيحة // احذف قطرات المطر في منطقة الماوس، خلف خط النهاية، وخارج المنطقة المرئية for (var i = linelist.length - 1; i >= 0; i--) { if (linelist[i].die) { linelist.splice(i, 1) } } // Render render(); // وظيفة التقديم render() { // ارسم مستطيلًا بحجم المساحة المرئية ctx.fillStyle = الخلفية ctx.fillRect(0, 0, CanvasEl.width, CanvasEl.height); // ارسم تأثير قطرة المطر ctx. lineWidth = 5; linelist.forEach(function (line) { ctx.strokeStyle = line.color; ctx.beginPath(); ctx.moveTo(line.posx, line.posy); // * يستخدم speedx للتحكم في اتجاه قطرات المطر // اجعل اتجاه قطرات المطر هو نفس اتجاه حركة الماوس ctx.lineTo(line.posx + line. h * speedx, line.posy + line.h); ctx.stroke(); }); // ارسم قطرات المطر المنتشرة لتشكل قطرات ماء صغيرة ctx.lineWidth = 1; dropList.forEach(function (e) { ctx.beginPath(); ctx.arc(e.posx, e.posy, e.radius, Math.random() * Math.PI * 2, 1 * Math.PI); ctx.stroke(); }); // أزل التعليق ويمكنك رؤية نطاق الماوس/* ctx.beginPath(); mousePos[1], mouseDis, 0, 2 * Math.PI ctx.stroke(); */ } } </script></body></html>
ما ورد أعلاه هو المحتوى الكامل لهذه المقالة وآمل أن يكون مفيدًا لدراسة الجميع وآمل أيضًا أن يدعم الجميع شبكة VeVb Wulin.