في الآونة الأخيرة، كان لدى المؤلف متطلبات المحتوى: يتم عرض مجموعة من النصوص حول الحلقة، ويمكن للمستخدم إضافة النص سوف تشع الفأرة فوق النقطة الزرقاء الصغيرة فوق الحلقة المثلث ثم تعرض النص، فلنلقي نظرة على تأثير الرسوم المتحركة أولاً!
كما هو موضح في الصورة أعلاه، عندما يتم وضع الماوس على النقطة الزرقاء الصغيرة المقابلة، يجب أن ينبعث شعاع يشبه المثلث، ويتم عرض النص المقابل خارج المثلث، وتتحول النقطة الزرقاء الصغيرة إلى نقطة بيضاء صغيرة.
عندما يقوم المستخدم بإدخال المحتوى أعلاه، تتم إضافة المحتوى حول الحلقة أدناه. كما هو موضح في الصورة أعلاه.
كانت فكرة المؤلف الأصلية هي استخدام CSS لتنفيذها، تمامًا مثل القائمة الثانوية الديناميكية في الصورة أدناه.
ومع ذلك، نظرًا لأن المحتوى الموجود على حافة الحلقة متغير ويجب وضعه حول الحلقة، فقد يكون من الصعب تنفيذ CSS. واو، قرر المؤلف استخدام القماش لتحقيق ذلك. (لم يتعلم المؤلف القماش إلا مؤخرًا. إذا كان هناك أي خطأ، فأنا أقبل تصحيحاتك).
عملية التنفيذ:أولاً:
جزء html من الكود هو كما يلي:
<canvas style=margin-left: 50px;padding-top: 20px; Display:block; id=canvas > الإصدار الحالي من متصفحك لا يدعم اللوحة القماشية</canvas>
خطوات التنفيذ المحددة هي كما يلي:
1. ارسم دائرة كبيرة.
استخدم طريقة القماش: context.arc(x, y, radius, startAngle, endAngle [, anticlockwise]);
x، y: إحداثيات مركز الدائرة، نصف القطر: نصف قطر مركز الدائرة، زاوية البدء: رسم راديان البداية، زاوية النهاية: رسم راديان النهاية، [، عكس اتجاه عقارب الساعة]: معلمة اختيارية، سواء لرسم القوس في اتجاه عقارب الساعة أو عكس اتجاه عقارب الساعة.
لتسهيل الرسم، نقل المؤلف أصل اللوحة القماشية من الزاوية اليسرى العليا السابقة إلى وسط اللوحة القماشية.
نصف قطر الحلقة المحسوبة من قبل المؤلف هو r-80
Canvas.width = 500canvas.height = 500// احسب نصف قطر مركز اللوحة القماشية Let r = 500 / 2// انقل أصل اللوحة القماشية إلى مركز اللوحة القماشية عند تهيئة الواجهة ctx.translate(r ، ص) // حرك الفرشاة للدوران
الكود المحدد هو كما يلي:
// تهيئة القماش Let Canvas = document.getElementById('canvas')let ctx= Canvas.getContext('2d')let نسبة = getPixelRato(ctx)canvas.width = 500canvas.height = 500// احسب نصف قطر المركز من اللوحة القماشية Let r = 500 / 2// عند تهيئة الواجهة، انقل أصل اللوحة القماشية إلى مركز اللوحة القماشية ctx.translate(r,r) // انقل الفرشاة إلى الدائرة ctx.lineWidth = 3; // اضبط عرض خط الفرشاة ctx.beginPath(); // ابدأ الفرشاة // ارسم لون الحافة المتدرج لحافة الدائرة var arcColor = ctx.createLinearGradient(-170, -170, 0, 170)arcColor.addColorStop(0, '#8ec1ff')arcColor.addColorStop(0.2, '#83beff')arcColor.addColorStop(0.5, '#75b1ff')arcColor.addColorStop(0.7,'#5998ff')arcColor.addColorStop(1, '#2065ff')ctx .strokeStyle= arcColor;// اضبط لون الفرشاة ctx.arc(0,0,r - 80,0,2*Math.PI,false) // ارسم دائرة، الإحداثيات 0،0، نصف القطر 250-80، دائرة كاملة (0 -360 درجة)، خطأ يعني في اتجاه عقارب الساعة ctx. ClosePath ()ctx.stroke () // الرسم
نتائج الرسم هي كما يلي
2. ارسم صورة الخلفية في منتصف الحلقة (أصل اللوحة القماشية الحالية هو مركز اللوحة القماشية)
drawImage(صورة، dx، dy، dWidth، dHeight)
الصورة: مصدر صورة Canvas، مثل صورة <img>، وصورة SVG، وعنصر Canvas نفسه، وما إلى ذلك.
dx, dy: قم بتخطيط منطقة على لوحة Canvas لوضع الصور. dx هي الإحداثيات الأفقية والرأسية للزاوية اليسرى العليا لهذه المنطقة.
dWidth، dHeight: قم بتخطيط منطقة على لوحة Canvas لوضع الصور وعرض هذه المنطقة وارتفاعها.
يتم حساب الإحداثيات التالية من قبل المؤلف
Let image = new Image()image.src = 'image/quan.png'image.onload = () => { // انقل الأصل إلى المركز ctx.drawImage(image,-140,-140,280,280)}
نتائج الرسم هي كما يلي:
3. ارسم نصًا ونقاطًا صغيرة على الحلقة (أصل اللوحة القماشية الحالية هو مركز اللوحة القماشية)
رسم الأهداف للنص والنقاط الصغيرة:
3.1 يتم عرض النقاط الصغيرة بالتساوي على الحلقة الكبيرة
3.2 النص مبعثر قليلاً خارج النقاط الصغيرة
حل:1. يستخدم المؤلف مصفوفة لتخزين الكلمات الحالية
Let textArr = ['بحر وسماء واسعة','قدرات فنية','أموال قوية','التحكم في الصيانة','العيش والعمل في سلام ورضا','مشاهدة الزهور','إنهاء اللمسات النهائية',' تخلص من الخبث، "اذهب ضد الريح"، "التطوير الوظيفي"]
2. نظرًا لأن عدد النقاط الصغيرة وعدد الكلمات متساويان، فإن عدد كل منهما هو طول المصفوفة textArr أعلاه.
3. راديان الدائرة الكاملة هو 2π. لجعل النقاط الصغيرة تقسم الحلقة بالتساوي، يقوم المؤلف أولاً بحساب راديان النقطة التي تقع فيها كل نقطة صغيرة.
for(let i = 0;i<lengths;i++){ // حساب الراديان Let rad = 2*Math.PI/lengths*i}
4. وفقًا للوظائف المثلثية، يمكن حساب إحداثيات (x، y) للنقطة الصغيرة الحالية على اللوحة القماشية (أصل اللوحة القماشية الحالية هو مركز اللوحة القماشية)
ومن بينها، العلاقة بين الراديان والنقطة الصغيرة والحلقة ونصف قطر الحلقة وأصل القماش، رسم المؤلف صورة لوصفها.
حساب إحداثيات النص:
// احسب إحداثيات مركز الدائرة الصغيرة Let x = (r - 40)*Math.cos(rad)let y = (r - 40)*Math.sin(rad)
حساب إحداثيات النقطة الصغيرة: لأن مركز النقطة الصغيرة يجب أن يقع على الحلقة، فإن الإحداثيات الأفقية والرأسية المحسوبة هي،
// احسب إحداثيات النص Let x = (r - 80)*Math.cos(rad) Let y = (r - 80)*Math.sin(rad)
الكود المحدد هو كما يلي:
// رسم النص ctx.font = '13px Arial'ctx.textAlign = 'center'ctx.textBaseline = 'middle'ctx.fillStyle=#000000let lengths = textArr.lengthtextArr.forEach(function(text,i){ // راديان Let rad = 2*Math.PI/lengths*i // احسب إحداثيات مركز الدائرة الصغيرة Let x = (r - 40)*Math.cos(rad) Let y = (r - 40)*Math.sin(rad) ctx.fillText(text,x+0.5,y+0.5)});// ارسم نقاطًا صغيرة for(let i) = 0;i<lengths;i++){ // // Let rad = 2*Math.PI/lengths*i Let x = (r - 80)*Math.cos(rad) Let y = (r - 80)*Math.sin(rad)// // ارسم نقاطًا رمادية صغيرة شفافة على الحافة ctx.beginPath() ctx.fillStyle = 'rgba(226,235,250, 0.8)' ctx.arc(x,y,8,0,2*Math.PI,false) ctx. ClosePath() ctx.fill() // ارسم نقاطًا زرقاء صغيرة ctx.beginPath() ctx.fillStyle = '#208fe5' ctx.arc(x,y,4,0,2*Math.PI,false) ctx. ClosePath() ctx .يملأ() }
نتائج الرسم هي كما يلي:
4. ارسم مثلثًا خارج كل نقطة صغيرة (أصل اللوحة القماشية الحالية هو مركز اللوحة القماشية)
4.1 لأنك تريد رسم شكل مثلث، فإن فكرة رسم المثلث هي رسم خطوط على كلا الجانبين بحيث يكون مركز النقطة الصغيرة الحالية هو نقطة البداية، ثم استخدم ctx.fill() لإغلاق الشكل و املأ الجزء الداخلي بلون متدرج.
ارسم مثلثًا: يتم حساب الإحداثيات من تلقاء نفسها. يضيف المؤلف ويطرح 35 على الإحداثي و70 على الإحداثي (كما تريد، هاهاها)
// ابدأ الفرشاة ctx.beginPath() ctx.moveTo(x,y) ctx.lineTo(x-35,y+70) ctx.lineTo(x+35,y+70) ctx. ClosePath()
ارسم النص الموجود أسفل المثلث: (لتمييزه عن النص السابق، استخدمت اللون الأحمر للنص الخاص بي هنا)
ctx.fillStyle= '#e3211c' ctx.fillText(textArr[i],x,y+75)
الكود المحدد هو كما يلي:
for(let i = 0;i<lengths;i++){ // // Let rad = 2*Math.PI/lengths*i Let x = (r - 80)*Math.cos(rad) Let y = (r) - 80)*Math.sin(rad) // // ارسم مثلث // // ctx.rotate( -Math.PI / 4) ctx.beginPath() // ابدأ الفرشاة ctx.moveTo(x,y) ctx.lineTo(x-35,y+70) ctx.lineTo(x+35,y+70) ctx. ClosePath() // // تعيين التدرج اللوني- - ->أضف اللون من المركز إلى الجانبين var sColor = ctx.createLinearGradient (x,y,x+18,y+50) sColor.addColorStop(0,'rgba(106,128,243,0.5)') sColor.addColorStop(0.6,'rgba(83,183,243,0.5)') sColor.addColorStop(0.7,'rgba(129,200,224,0.5)') sColor.addColorStop(0.8,'rgba(130,219,251,0.5)') sColor.addColorStop(1,'rgba(195,228,223,0.5)') ctx.fillStyle= sColor ctx.fill() ctx.fillStyle= '#e3211c' ctx.fillText(textArr[i],x,y+75)}
نتائج الرسم هي كما يلي:
4.2 الشرط هو أن اتجاه كل مثلث هو أن ينتشر للخارج، والآن اتجاه المثلثات هو للأسفل، لذلك أنت الآن بحاجة إلى استخدام طريقة تدوير القماش.
ctx.save() ctx.translate(x,y) // تتمركز زاوية الدوران على كل نقطة صغيرة ctx.rotate( rad - Math.PI/2 ) // لأن النقطة الصغيرة ctx.translate(- x, - ذ) . حذف التعليمات البرمجية لرسم المثلثات والنص .
يمكن أن نرى من الحساب أنه إذا أخذنا مركز النقطة الصغيرة كنقطة بداية للدوران، فإن قوس دوران المثلث يجب أن يكون قوس النقطة الصغيرة الحالية ناقص π/2، لأن موضع بداية الدوران دائمًا يبدأ من الاتجاه الموجب لمحور الإحداثي السيني، أي أنه يبدأ عند 0 راديان، لكن المثلثات الآن جميعها عند π/2 راديان، لذا:
راديان الدوران = راديان النقطة الصغيرة - π/2
تذكر استخدام طريقة تخزين حالة Canvas save() عند التدوير.
تقوم Restore() بإخراج حالة Canvas المخزنة من أعلى المكدس بدورها. إذا لم تكن هناك حالة Canvas مخزنة، فلن يكون هناك أي تغيير في تنفيذ هذه الطريقة.
تأكد من تذكر استخدام طريقة الاستعادة () في النهاية، عند هذه النقطة، ذرف المؤلف دموع الندم. . .
كود محدد:
for(let i = 0;i<lengths;i++){ // // Let rad = 2*Math.PI/lengths*i Let x = (r - 80)*Math.cos(rad) Let y = (r) - 80)*Math.sin(rad) // ارسم مثلث ctx.save() // تتمركز زاوية الدوران على كل نقطة صغيرة لأن النقاط الصغيرة في البداية ctx.translate(x,y) ctx.rotate( rad - Math.PI/2 ) ctx.translate(-x, -y) // ابدأ الفرشاة ctx.beginPath() ctx.moveTo(x,y) ctx.lineTo(x-35,y+ 70 ) ctx.lineTo(x+35,y+70) ctx.ClosePath() //تعيين التدرج اللوني--->إضافة لون var من المركز إلى الجانبين sColor = ctx.createLinearGradient (x,y,x+18,y+50) sColor.addColorStop(0,'rgba(106,128,243,0.5)') sColor.addColorStop(0.6,'rgba(83,183,243,0.5)') sColor.addColorStop(0.7,'rgba(129,200,224,0.5)') sColor.addColorStop(0.8,'rgba(130,219,251,0.5)') sColor.addColorStop(1,'rgba(195,228,223,0.5)') ctx.fillStyle= sColor ctx.fill() ctx.fillStyle= '#e3211c' ctx.fillText(textArr[i],x,y+75) ctx.restore()}
ارسم النتيجة:
نلقي نظرة فاحصة، ماذا؟ ؟ ؟ بعض النصوص مقلوبة بسبب مشاكل التدوير، ومن خلال الملاحظة تكون النتيجة أنه عندما يكون الراديان أكبر من π، يصبح النص مقلوبًا.
لقد حان الوقت لكتابة موجة من الأحكام. . . .
كيفية تدوير النص:
وظيفة تدويرContext(ctx, x, y, Degree) { // تدوير النص ctx.translate(x, y) // ctx.rotate(degree * Math.PI / 180) ctx.rotate(degree) ctx.translate(-x ، -y) }
حدد النقاط الصغيرة التي يكون راديانها أكبر من π
if (rad > Math.PI) { // لأن النص يجب أن يُعرض على حافة المثلث، يجب أن يدور النص مع المثلث بحيث يمكن الاحتفاظ به دائمًا على حافة المثلث // بعد التدوير ، سيظهر النص عندما يكون الراديان أكبر من π. قم بعكس المشكلة، لذا قم بتدوير النص ctx.save() ctx.beginPath() // تدوير النص RotateContext(ctx, x, y+75, Math.PI) ctx.font = '13px Arial' ctx.textAlign = 'center' ctx.fillStyle = #ff2238 ctx.fillText(textArr[i], x, y+ 75) ctx.restore()} else { ctx.fillStyle = '#ff2238' ctx.fillText(textArr[i) ]، س، ص + 75)}
نتائج الرسم هي كما يلي:
نتطلع إلى النصر، ونحن على وشك النجاح. على الأقل لدينا تخطيط تقريبي. الثورة لم تنجح بعد، وما زال الرفاق بحاجة إلى العمل الجاد! !
5. فيما يلي التنفيذ. عندما يكون الماوس فوق النقطة الصغيرة، يتم عرض المثلث الموجود على الحافة والنص الموجود على حافة المثلث، ولكن لا يتم عرض النص الموجود على حافة الدائرة.
فكرة:1. قم بربط حدث إدخال الماوس باللوحة القماشية
2. حدد ما إذا كانت إحداثيات موضع الماوس الحالي على اللوحة القماشية مساوية للإحداثيات القريبة من نقطة صغيرة. إذا كان الأمر كذلك، فاعرض المثلث المقابل للنقطة الصغيرة.
5.1 ربط حدث mousemove باللوحة القماشية: يكون الماوس فوق الحدث
Canvas.addEventListener('mousemove',clickEvent)
5.2 احسب الإحداثيات الحالية للماوس على اللوحة القماشية
طريقة الحساب هي: استخدم الإحداثيات الحالية للماوس على DOM لطرح المسافة من يسار اللوحة القماشية أو أعلىها لحساب مسافة اللوحة القماشية.
طريقة drawOne في الشكل أدناه هي طريقة الرسم، والتي سيتم مناقشتها لاحقًا في المقالة.
function clickEvent() { // إحداثيات موضع الفأرة Let x = events.clientX - Canvas.getBoundingClientRect().left Let y = events.clientY - Canvas.getBoundingClientRect().top drawOne(x,y)}
5.3، لأن إحداثيات الماوس على اللوحة القماشية المحسوبة أعلاه يتم حسابها باستخدام الزاوية اليسرى العليا من اللوحة القماشية كأصل، ولكن أصل اللوحة القماشية الحالية قد انتقل بالفعل إلى مركز اللوحة القماشية (250,250)، لذلك عند استخدامها لتحديد ما إذا كانت النقرة عبارة عن نقاط صغيرة أنت بحاجة إلى طرح 250 من الإحداثيات الأفقية والرأسية للمقارنة بإحداثيات النقطة الصغيرة على اللوحة الحالية عندما كنت أحكم، وجدت مشكلة لا أعرف سبب الاختلاف في الاتجاه y المؤلف هو 260 بدلاً من 250. لذلك طرح المؤلف 260 في الاتجاه y.
الرمز هو كما يلي:
من بينها، Cx، Cy هي إحداثيات الماوس على اللوحة القماشية (الزاوية العلوية اليسرى من اللوحة القماشية هي الأصل)، x، y هي إحداثيات النقطة الصغيرة الحالية،
قام المؤلف مباشرة بحساب موضع 15 بكسل بالقرب من مركز النقطة الصغيرة، وتم عرض جميع المثلثات، وتحولت النقطة الصغيرة إلى اللون الأبيض.
الشيء الأكثر أهمية هو أنك تحتاج إلى مسح اللوحة القماشية السابقة في كل مرة تقوم فيها بإعادة الرسم: تذكر استخدام طريقة ClearRect لمسح اللوحة القماشية
دع XX = Cx - 250دع YY = Cy- 260دع leftX = x - 15دع اليمينX = x + 15دع topY = y - 15دع BottomY = y + 15if (XX >= leftX && XX <= rightX && YY <= BottomY && YY > = topY ) {// تم النقر عليه. . . . . . //اكتب رمز الرسم في المنتصف}
الكود يتبعه رابط:
6. حدد إدخالاً على الواجهة واربط حدث التغيير بالإدخال.
التنفيذ: تتم إعادة رسم الواجهة في كل مرة تتغير فيها القيمة في الإدخال.
كود أتش تي أم أل:
<نوع الإدخال=معرف النص=نمط inpt=margin-left: 100px;margin-top: 50px placeholder=يرجى الإدخال...>
رمز شبيبة:
Let inpt = document.getElementById('inpt') inpt.addEventListener('change', function () { if (inpt.value !== '') { textArr.push(inpt.value) drawAll(2) // هذا الطريقة هي طريقة الرسم، سيتم إعطاء الكود المصدري لاحقًا في المقالة }})
7. توجد مشكلة في كل مرة تنقر فيها على الواجهة وتعيد رسم الواجهة، ستظهر حالة وميض.
كما هو موضح أدناه:
في كل مرة تقوم فيها بالتمرير، نظرًا لأن إحداثيات الماوس تتغير، تحتاج إلى مسح المحتوى حول الحلقة وإعادة رسمها. لذلك تحتاج إلى مسح اللوحة القماشية لتحقيق التأثيرات الديناميكية.
يُستخدم ClearRect() بشكل شائع في رسم الرسوم المتحركة على القماش، حيث يقوم بمسح محتوى القماش بشكل مستمر ثم يرسمه لتشكيل تأثير الرسوم المتحركة.
يمكن لـ ClearRect() أن يجعل المنطقة المستطيلة في لوحة قماش عنصر Canvas شفافة.
context.clearRect(x, y, width, height);
x، y: إحداثيات x، y للزاوية اليسرى العليا للمستطيل.
العرض والارتفاع: عرض وارتفاع المساحة المستطيلة التي تم تطهيرها.
نظرًا لأن ClearRect() يمكنه فقط مسح المنطقة المستطيلة من اللوحة القماشية، ففي كل مرة يتم مسحها، سيتم مسح صورة الخلفية الموجودة في المنتصف معًا.
لذلك، يجب إعادة تحميل صورة الخلفية في كل مرة، ويستغرق تحميل الصورة وقتًا معينًا، لذلك ستومض في كل مرة تظهر فيها.
حل:drawImage(صورة، dx، dy، dWidth، dHeight)
صورة المعلمة: مصدر صورة Canvas، مثل صورة <img>، وصورة SVG، وعنصر Canvas نفسه، وما إلى ذلك.
ثم يمكنك استخدام قماش آخر لتخزين الصور مؤقتًا.
استخدم لوحة قماشية إضافية لرسم صورة الخلفية، ولكن بالنسبة إلى اللوحة القماشية غير المعروضة في الواجهة: عرض: لا شيء، ثم استخدمها لمسح اللوحة القماشية وعرض كائن اللوحة القماشية المخزن مؤقتًا مباشرةً في منتصف اللوحة القماشية المراد عرضها، أي أنه ليست هناك حاجة إلى أن تحميل الصور مرة واحدة يستغرق وقتًا طويلاً.
كود أتش تي أم أل:
<عرض القماش=280 الارتفاع=280 style=margin-left: 50px;padding-top: 20px;
رمز شبيبة:
// استخدم التخزين المؤقت لحل مشكلة وميض الصور المعاد رسمها var tempCanvas = document.getElementById('canvas2')const tempCtx = tempCanvas.getContext('2d')tempCanvas.width = 280; tempCanvas.height = 280let image = new Image( )image.src = 'image/quan.png'image.onload = () => { // ينتقل الأصل إلى المركز tempCtx.drawImage(image,0,0,280,280)}
بعد مسح اللوحة القماشية، ارسم اللوحة القماشية المخزنة مؤقتًا: tempCanvas مباشرة عند إعادة رسم الصورة.
// ارسم اللوحة القماشية المخزنة مؤقتًا مباشرةً على الواجهة (يتم تخزين واجهة الإطارات المتوسطة مؤقتًا) ctx.drawImage(tempCanvas,-140,-140)
حسنًا، لقد نجحت، وهذه هي صورة النتيجة:
عنوان الكود المصدري هو كما يلي:
https://github.com/Linefate/Dynamic-effect-of-canvas-ring.git
تلخيصما ورد أعلاه هو مقدمة المحرر لاستخدام قماش html5 لرسم الرسوم المتحركة الحلقية، وآمل أن يكون ذلك مفيدًا لك. إذا كانت لديك أي أسئلة، فيرجى ترك رسالة لي وسيقوم المحرر بالرد عليك في الوقت المناسب. أود أيضًا أن أشكر الجميع على دعمكم لموقع VeVb للفنون القتالية!