21

شرح | طريقة رسم الصوت على الكانفاس باستخدام Javascript

  • Rashadoo

السلام على من اتبع الهدى

قبل البدء اريد ان اقول ان هذا الشرح هو تجربة لي فقط من اجل شيء معين لذلك ارجوا تقييم الشرح بالنسبة لشخص مبتدأ (لكن يعرف في الكانفاس).


لننشئ اولا ملف الـ html الاساسي ونضع بداخل الـ body عنصر الـ canvas الذي سنرسم عليه ولنعطه Id حتى نتمكن من التحكم به في جافاسكربت، ولنربط مع ملف الـ html ملف السكربت الذي سنكتب فيه اكواد الجافاسكربت


<html>
    <body>
        <canvas id="canvas"></canvas>
    </body>
    <script src="main.js"></script>
</html>

الآن نكون انتهينا من هذا الملف كلياً وكل عملنا القادم سيكون داخل ملف الجافاسكربت

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var width = canvas.width = window.innerWidth;
var height = canvas.height  = window.innerHeight;

قمت اولاً بجلب عنصر الكانفاس السابق عن طريق الـ Id ثم قمت بجلب RenderContext2D الخاص به، وهو السياق الذي سنتمكن عن طريقه الرسم على الكانفاس

ثم عرفت متغيرين، الطول والعرض، واسندت طول الكانفاس وعرضها اليهما وجعلت كلاً منهما مساوياً لطول وعرض الشاشة على التتالي.

الان لنقم بجلب المقطع الصوتي المراد رسمه

var audio = new Audio();
    audio.src = '1.mp3';
    audio.play();

في البداية عرفت متغير من نوع Audio ووضعت له الرابط الخاص به (أي مكان تواجده في الجهاز) ثم قلت له ان يشتغل ..

في هذه الخطوة سنقوم بكتابة الشيء الجديد وهو السياق الصوتي ومحلل الاصوات

var audCtx = new AudioContext(),

    analyser = audCtx.createAnalyser(),

    src = audCtx.createMediaElementSource(audio);

في البداية قمت بتعريف متغير على انه السياق الصوتي، وهو الذي يتحكم بإنشاء الوحدات الصوتية المرتبطة ببعضها، كما يقوم بترجمة الصوت وتنفيذه (واقصد بالترجمة هنا هو تحويل الصوت الى شيء يفهمه الحاسوب) اما عن المحلل فهو الذي سنستخدمه للحصول على ترددات الموجات الصوتية والتي سنستخدمها كأطوال لرسم الصوت اما عن الـ src فسنستخدمه لندل المحلل عن الصوت الذي نريد تحليله عن طريق تمريره كـ parameter .. اي سنقوم بربطهما معاً عن طريق الكود التالي

src.connect(analyser);
analyser.connect(audCtx.destination);

ربطت الصوت الذي عرفناه بالبداية بالمحلل، ثم ربطت المحلل بوجهة السياق الصوتي .. اي مثلاً مكبرات الصوت في جهاز حاسوبك


حان وقت كامب لازلو .. اقصد الرسم D: في الرسم سنقوم بتعريف مصفوفة من نوع Integer ونخزن فيها قيم الترددات ثم نرسم كل تردد على حسب طوله وسأستخدم requsetAnimationFrame للرسم، لكن اولاً سأقوم بتعرف بعض المتغيرات التي سأستخدمها في الرسم

var rectX; // represents the rectangle X on the canvas
var arr;   // the array which we will use to store the frequencies

الان لنعرف تابع الرسم وبداخله سنستخدم عدة توابع سأقوم بشرحها

function draw(){

    ctx.clearRect(0, 0, width, height);

    arr = new Uint8Array(analyser.frequencyBinCount);

    analyser.getByteFrequencyData(arr);

    for(var i = 0; i < 200; i++){

        barX = (width/2 - 300) + 3 * i;

        ctx.fillRect(barX, height/2, 2, -arr[i]);

    }

    window.requestAnimationFrame(draw);

}

draw();

اولاً

    ctx.clearRect(0, 0, width, height);

والذي يقوم بمحو ما كان مرسوماً على الكانفاس من 0 0 الى الطول والعرض، اي كل الكانفاس

    arr = new Uint8Array(analyser.frequencyBinCount);

وهي المصفوفة من نوع Integer (ليس شرطاً ويمكن استعمال float) لكن يجب ان تكون محددة النوع وبما اننا استخدمنا المنشئ Constructor لانشاها فنحن نحتاج لتحديد بعدها، وهنا نستخدم المحلل ليقوم بجلب عدد البايتات او يمكنك الاستغناء عن المحلل وكتابة 100 مثلاً .. اي انك ستخزن مئة بايت فيها فقط في كل مرة

    analyser.getByteFrequencyData(arr);

الان نستخدم المحلل ليقوم بتعبئة ترددات البايتات داخل المصفوفة السابقة

        barX = (width/2 - 300) + 3 * i;

        ctx.fillRect(barX, height/2, 2, -arr[i]);

الاول لتحديد اكسات (فواصل) المستطيل على الكانفاس والجزء الاول منه لتوسيطه في منتصف الكانفاس. اما السطر الثاني بهو لرسم المستطيل في الاكسات السابقة ومنتصف الشاشة (بالطول) وبعرض 2 بكسل وبارتفاع على حسب تردد الموجة الصوتية، والسالب لاني اريد المستطيل ان يرتسم للاعلى وليس للاسفل (الاحداثيات على التراتيب في الكانفاس معكوسة عن الواقع)

window.requestAnimationFrame(draw);

في النهاية نستخدمها لتتدعي التابع مرات عديدة في الثانية لنحصل على تحريك مثالي (حوالي 60 استدعاء في الثانية) وتختلف سرعتها من جهاز لآخر

واخير نستدعي التابع draw لينطلق .. واااااااااا هذا ما نحصل عليه .

الان يمكنك اللعب كما تشاء فيه كأن ترسم معكوس له تحته (فقط كرر سطر رسم المستطيل مع ازالة اشارة الناقص)

او اذا كنت تعرف بالكانفاس قليلاً اجعله على شكل دائرة وقمت بتغيير ألوانه :]

وعلى قولة الخليل كوميدي .. حطولي لايكات .. حطولي لايكات

الكود كامل على Ideone

يرجى الدخول لحسابك أو تسجيل حساب لتستطيع إضافة تعليق
حساب جديد دخول

التعليقات

قلت اريد feedback رجاءً

أعطيناك +11 ماذا تريد أيضًا ؟؟

اريد شخص يأتي وينتقد في كل صغيرة وكبيرة

كتبت المقال لاني اريد ان اجرب كتابة مقالات عن الالعاب في الكاديمية ولا اعتقد اني بالمستوى الكافي

يوسف سيد أضف ردا

حسنا، هذه الشيفرة المنقحة:

var canvas = document.getElementById('canvas'),
    ctx = canvas.getContext('2d'),
    width = canvas.width = (window.innerWidth || 200),
    height = canvas.height  = (window.innerHeight || 200),
    audio = {function () {
        var audio = new Audio();
        audio.src = '1.mp3';
        audio.play();
        return audio
    }}(),
    audCtx = new AudioContext(),
    analyser = audCtx.createAnalyser(),
    src = audCtx.createMediaElementSource(audio),

src.connect(analyser);
analyser.connect(audCtx.destination);

function draw(){
    var arr = new Uint8Array(analyser.frequencyBinCount); // the array which we will use to store the frequencies

    analyser.getByteFrequencyData(arr); 
    ctx.clearRect(0, 0, width, height);

    for(var i = 0; i < 200; i++){
        var barX = (width/2 - 300) + 3 * i;
        ctx.fillRect(barX, height/2, 2, -arr[i]);
    }

    window.requestAnimationFrame(draw); 
}

draw();

الملاحظات:

  1. من الأفضل عند تعريف متغيرات تعريف أكثر من مُتغيير مرة واحدة إتبع var a, b ..؛ لكن ليس هنالك مشكلة إن عرفت كل مُتغيير على حدى لتعريف المتعلم، المشكلة أنك استخدمت الطريقتين.

  2. أحيانًا تترك فراغًا وآخرى لا!، استخدم تصميم واحد لشيفرتك،

كذلك لا تثبت على طريقة واحدة لتسمية المتغيرات مرة تستخدم اسمًا مختصرًا ومرة كاملًا.

  1. يوجد بعض المتغيرات تعرفها في سياق أعلى تعرفها عامة في الشيفرة وأنت ستسخدمها في الدالة فقط كarr من الهام عدم إنشاء المُتغير كل مرة تستخدم فيها الشيفرة، ولا أقول أن تعرف المتغيرات في الدالة كل مرة، لكن arr تحتاج إلى تعريفها كل مرة لذا لا تعرفها خارجًا.

  2. حاول التحسين من لغتك؛ إن أردت النشر؛ هذا أهم من تطوير معرفتك البرمجية -عن تجربة، أمور مثل همزة القطع، والوصل وعدم التفريق بينهم، استخدام الكلمات المناسبة في السياق المناسب مثلًا أعتقد -> أظن.

  3. حاولت قراءة الدرس كشخصٍ لا يفهم أي شيء فيه فلم يتضح ماذا تريد أن تقول نصائح بهذا الشأن:

    1. حاول ربط المعلومات ببعضها، ولا تقل سنقوم وسنفعل، ولم توضح ماذا فعلت سابقًا وماذا ستفعل لاحقًا!
    2. تدرج في الأهداف، واستخدم النقاط 1. إنشاء مساحة الرسم، 2. تشغيل الصوت ..
    3. ضع أي ملاحظات تراها مفيدة، مثلًا هذه الشيفرة يجب أن تعمل بعد تحميل الصفحة سواءً من اضافتها إلى أخر جسم الصفحة body، أو بعد الحدث load لنافذة الصفحة(أقصد window)؛ لكي تستطيع العمل على الcanvas بعد عمله من المتصفح.
    4. ابحث عن علامات الترقيم، واستخدامتها.

أسأل الله أن يوفقك إلى كل خيرٍ، حمستني لقراءة مقالًا قادمًا لك أفضل بكثير.

يوسف سيد أضف ردا

آسف بدلًا من

{function () {
     var audio = new Audio();
     audio.src = '1.mp3';
     audio.play();
     return audio
 }}(),

اكتب 

(function () {
     var audio = new Audio();
     audio.src = '1.mp3';
     audio.play();
     return audio
 })(),

أسأل الله أن يوفقك إلى كل خيرٍ، حمستني لقراءة مقالًا قادمًا لك أفضل بكثير.

وراءك و راءك و الزمن طويل :)

يوسف سيد أضف ردا

-- عدل ---

جعلتني أتردد أليس المصدر يرفع المفعول به؟

حسنا فهمتُ الآن، من قراءة إعراب قوله تعالى {ولولا دفْع الله}

هو مضاف إليه مجرور، و المشتقات تعمل عمل فعلها بشروط

نعم هذا ما فهمته هنا "حسنا فهمتُ الآن، من قراءة إعراب قوله تعالى {ولولا دفْع الله}

" ما زلتُ في بدايتي في هذا العلم ...

ما زلتُ في بدايتي في هذا العلم ...

طيب هذا آخر تعقب لي لأخطائك النحوية حتى يشتد عودك و تستوي على سوقك و نلتقي بعدها.. :)

ماهو الكانفاس باللغة العربية

الكانفاس تطلق على قطعة القماش وغالباً ما يرسم عليه بالالوان الزيتية واعتقد من هنا أتت تسمية هذا العنصر

اي هو عنصر للرسم

في Microsoft Word ترجم إلى لوحة الرسم القماشية

للأسف لم يعمل، هل بالإمكان ارفاق ملف zip للمثال كاملاً؟

يعمل فقط في firefox