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

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


لننشئ اولا ملف الـ 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