تضم لغة HTML عناصر مخصصة لتضمين الوسائط المتعددة إلى صفحاتك مثل <audio>
و <video>
والتي تأتي مزوّدة بواجهة برمجية مخصصة للتحكم بتشغيلها وتقديمها وتأخيرها. لهذا سنتعرف في هذا المقال على طرق تنفيذ بعض المهام الشائعة كإنشاء أدوات تحكم متخصصة باستخدام الواجهة البرمجية HTMLMediaElement التي توفر عدة ميزات للتحكم في تشغيل الصوت و الفيديو برمجيًا .
ننصحك قبل المتابعة في قراءة هذه المقالات أن:
- تكون ملمًا بلغتي HTML و CSS.
- تكون ملمًا بلغة جافا سكريبت.
- تطلع على سلاسل المقالات السابقة التي ناقشت أساسيات جافا سكريبت والكائنات Prototype في جافا سكريبت.
- تطلع على أساسيات الواجهات البرمجية في طرف العميل.
عناصر HTML الخاصة بالصوت والفيديو
يسمح العنصران <video>
و <audio>
بإدراج مقاطع الصوت و الفيديو في صفحات الويب، وستبدو الطريقة النمطية ﻹنجاز اﻷمر كالتالي:
<video controls> <source src="rabbit320.mp4" type="video/mp4" /> <source src="rabbit320.webm" type="video/webm" /> <p> Your browser doesn't support HTML video. Here is a <a href="rabbit320.mp4">link to the video</a> instead. </p> </video>
تعرض الشيفرة السابقة مشغل فيديو في صفحتك كالتالي:
وأكثر ما يثير الاهتمام في الشيفرة السابقة هي السمة controls
التي تعرض أدوات التحكم الافتراضية مع مشغل الفيديو، وإن لم تستخدم هذه السمة فلن ترى عناصر التحكم على المشغل:
لهذه اﻷدوات إيجابيات، لكن من أبرز مشكلاتها هي اختلافها من متصفح إلى آخر وهذا أمر مربك إن حاولت دعم عدة متصفحات في شيفرتك. ومن المشكلات الكبيرة أيضًا أن أدوات التحكم اﻷصلية في معظم المتصفحات لا تدعم التحكم من خلال لوحة المفاتيح. ويمكن حل كلتا المشكلتين السابقتين بإخفاء أدوات التحكم الأصلية (عن طريق إزالة السمة controls
) وبرمجة أدوات تحكم خاصة بك باستخدام HTML و CSS وجافا سكريبت. وسنلقي نظرة في اﻷقسام التالية على اﻷدوات البسيطة المتاحة لهذا الغرض.
الواجهة البرمجية HTMLMediaElement
تزّودك بعض مواصفات الواجهة البرمجية HTMLMediaElement بميزات تسمح لك بالتحكم في مشغلات الصوت و الفيديو برمجيًا مثل التوابع ()HTMLMediaElement.play
و ()HTMLMediaElement.pause
وغيرها. وهاتان الواجهتان متاحتان للاستخدام مع العنصرين <audio>
و<video>
فهما متطابقان من ناحية العمل. لهذا سنوضح طريقة استخدام هذه الواجهات من خلال المثال التالي:
يبدو مثالنا عندما يكتمل مشابهًا للتالي:
نقطة الانطلاق
حتى نبدأ العمل، عليك تنزيل الملف المضغوط الخاص بالمثال ثم تستخرج محتوياته في مجلد جديد على حاسوبك. أما إن حمّلت مستودع اﻷمثلة بأكمله، ستجد المثال في المسار javascript/apis/video-audio/start/
.
إن حمّلت المثال على متصفحك سترى مشغل فيديو HTML نمطي مع أدوات التحكم الافتراضية.
التعرف على ملف HTML
عندما تفتح الملف index.html سترى عددًا من العناصر، وستلاحظ أن معظم الشيفرة تدور حول مشغل الفيديو وأدوات التحكم الخاصة به:
<div class="player"> <video controls> <source src="video/sintel-short.mp4" type="video/mp4" /> <source src="video/sintel-short.webm" type="video/webm" /> <!-- fallback content here --> </video> <div class="controls"> <button class="play" data-icon="P" aria-label="play pause toggle"></button> <button class="stop" data-icon="S" aria-label="stop"></button> <div class="timer"> <div></div> <span aria-label="timer">00:00</span> </div> <button class="rwd" data-icon="B" aria-label="rewind"></button> <button class="fwd" data-icon="F" aria-label="fast forward"></button> </div> </div>
-
وضعنا المشغل بأكمله داخل العنصر
<div>
حتى يُنسّق بالكامل عند الحاجة. -
يحتوي العنصر
<video>
على عنصرين من النوع<source>
كي نتمكن من تحميل تنسيقات مختلفة لمقطع الفيديو وفقًا للمتصفح الذي نستخدمه. - وربما تكون أدوات تحكم HTML هي اﻷكثر أهمية هنا:
-
لدينا أربعة أزرار
<button>
لتشغيل وإيقاف العرض مؤقتًا واﻹطفاء والتقديم للأمام والعودة للخلف. -
خصصنا لكل زر سمات هي اسم صنف التنسيق
class
وdata-icon
لتحديد اﻷيقونة التي تُعرض على الزر (سنرى كيف ننفذ ذلك لاحقًا) وaria-label
لتقديم وصف مفهوم عن عمل كل زر، وذلك لأننا لا نقدم عنوانًا مقروءًا ضمن وسم العنصر. ويُقرأ محتوى السمةaria-label
من قبل قارئات الشاشة عندما ينتقل التركيز إلى العناصر التي تمتلك هذه السمة. -
تضم الصفحة أيضًا مؤقتًا ضمن عنصر
<div>
يعرض الوقت المنقضي من مقطع الفيديو، ولتحسين تجربة المستخدم، زودنا المثال بآليتين لتحديد الوقت المنقضي: الأولى ضمن عنصر<span>
يعطي الوقت المنقضي بالدقائق والثواني، والثانية ضمن عنصر<div>
يضم شريط أفقي يزداد طوله عندما يتقدم عرض الفيديو. ولكي تأخذ فكرة عما ستكونه الصفحة بشكلها الكامل ألق نظرة هنا..
التعرف على ملف CSS
افتح اﻵن ملف CSS وألقِ نظرة عليه. لا يبدو هذا الملف معقدًا، لكننا سنشير إلى النقاط المهمة فيه. لاحظ بداية القاعدة controls.
:
.controls { visibility: hidden; opacity: 0.5; width: 400px; border-radius: 10px; position: absolute; bottom: 20px; left: 50%; margin-left: -200px; background-color: black; box-shadow: 3px 3px 5px black; transition: 1s all; display: flex; } .player:hover .controls, .player:focus-within .controls { opacity: 1; }
-
بدأنا بالخاصية
visibility
لمجموعة أدوات التحكم المخصصة وضبطناها علىhidden
، لكننا سنضبطها لاحقًا عبر جافا سكريبت لتكونvisible
ونزيل السمةcontrols
من العنصر<video>
. وذلك كي يبقى المستخدم قادرًا على تشغيل الفيديو باستخدام أدوات التحكم الافتراضية في حال فشل تحميل شيفرة جافا سكريبت لسبب ما. -
منحنا أدوات التحكم قتامة افتراضية
opacity
قيمتها 0.5، كي لا تشتت الانتباه عند عرض الفيديو، لكن عندما تمرر الفأرة فوق المشغّل أو تمنحه تركيز الدخل ستكون اﻷدوات كاملة القتامة. - نرتب اﻷزرار ضمن شريط التحكم باستخدام تخطيط الصندوق المرن display: flex لتسهيل ضبط مواقعها.
لنلق نظرة تاليًا على أيقونات اﻷزرار:
@font-face { font-family: "HeydingsControlsRegular"; src: url("fonts/heydings_controls-webfont.eot"); src: url("fonts/heydings_controls-webfont.eot?#iefix") format("embedded-opentype"), url("fonts/heydings_controls-webfont.woff") format("woff"), url("fonts/heydings_controls-webfont.ttf") format("truetype"); font-weight: normal; font-style: normal; } button:before { font-family: HeydingsControlsRegular; font-size: 20px; position: relative; content: attr(data-icon); color: #aaa; text-shadow: 1px 1px 0px black; }
استخدمنا بداية في أعلى ملف CSS الكتلة font-face@
لاستيراد خط ويب مخصص، وهذا الخط هو عبارة عن أيقونات بدلًا من الحرف اﻷبجدية وتستخدم لعرض أيقونات مختلفة يشيع استخدامها في التطبيقات.
نولد بعد ذلك محتوىً خاصًا لعرض اﻷيقونات على كل زر:
-
نستخدم المحدد
before::
لعرض المحتوى قبل كل زر<button>
. -
نستخدم الخاصية
content
لضبط المحتوى الذي يعرض في كل حالة ليكون نفسه محتوى السمةdata-icon
. ففي حالة زر التشغيل مثلًا، سيكون محتوى السمةdata-icon
هو المحرفP
(بشكله الكبير). -
نطبق خط ويب السابق على اﻷزرار باستخدام الخاصية
font-family
، وسيكون الحرفP
في هذا الخط عمليًا أيقونة التشغيل، وهكذا ستظهر على زر التشغيل أيقونة التشغيل.
إن الخطوط التي تعرض أيقونات جميلة ومفيدة ﻷسباب عديدة منها تقليل عدد طلبات HTTP لانك لن تحتاج إلى تحميل تلك اﻷيقونات على شكل ملفات صور، إضافة إلى إمكانية تكبير وتصغير اﻷيقونات بدقة وكذلك إمكانية استخدام خاصيات نصية لتنسيق تلك اﻷيقونات مثل color
و text-shadow
.
لنلق نظرة أيضًا على تنسيق المؤقت الزمني:
.timer { line-height: 38px; font-size: 10px; font-family: monospace; text-shadow: 1px 1px 0px black; color: white; flex: 5; position: relative; } .timer div { position: absolute; background-color: rgb(255 255 255 / 20%); left: 0; top: 0; width: 0; height: 38px; z-index: 2; } .timer span { position: absolute; z-index: 3; left: 19px; }
-
ضبطنا قيمة الخاصية
flex
للعنصرtimer.
الخارجي على القيمة 5 لتشغل أكبر مساحة من شريط التحكم. كما ضبطنا خاصية الموقع بالشكلposition:relative
كي نتمكن من ضبط العناصر ضمن العنصر الخارجي كما نشاء وبالنسبة إلى حدوده وليس حدود العنصر<body>
. -
ضبطنا موقع العنصر
<div>
الداخلي ليكون مطلقًاposition:absolute
لكي يظهر مباشرة في أعلى العنصر<div>
الخارجي. كما ضبطنا قيمة اتساع العنصر على الشكلwidth:0
كي لا يُرى العنصر إطلاقًا. وعندما يبدأ العرض نستخدم جافا سكريبت لزيادة اتساع العنصر. -
ضطنا موقع العنصر
<span>
ليكون مطلقًا وبالتالي سيكون بالقرب من الطرف اﻷيسر لشريط المؤقت. -
ضبطنا خاصية العلو
z-index
للكائن<div>
الداخلي والكائن<span>
كي يُعرض الشريط الزمني في الأعلى وتحته العنصر<div>
الداخلي، ونضمن بذلك أنك سترى كل المعلومات ولن يَحجِب صندوق آخر.
إنجاز شيفرة جافا سكريبت
بعد أن حضرنا واجهتي HTML و CSS، لا بد من كتاب شيفرة اﻷزرار المخصصة للتحكم بمشغل الفيديو.
-
أنشئ ملف جافا سكريبت جديد في نفس المجلد الذي يضم الملف index.html وسمِّه
custom-player.js
. - ضع الشيفرة التالية أعلى الملف:
const media = document.querySelector("video"); const controls = document.querySelector(".controls"); const play = document.querySelector(".play"); const stop = document.querySelector(".stop"); const rwd = document.querySelector(".rwd"); const fwd = document.querySelector(".fwd"); const timerWrapper = document.querySelector(".timer"); const timer = document.querySelector(".timer span"); const timerBar = document.querySelector(".timer div");
أنشأنا في الشيفرة السابقة ثوابت لتكون مراجع إلى الكائنات التي نريد التعامل معها، ولدينا ثلاثة مجموعات:
-
العنصر
<video>
وشريط التحكم. - أزرار التحكم "تشغيل/إيقاف مؤقت play/pause" و "للأمام rewind" و "للخلف fast forward".
-
غلاف المؤقت الخارجي
<div>
والعنصر<span>
الذي يعرض المؤقت والعنصر<div>
الخارجي الذي يزداد اتساعه عندما يتقدم الفيديو.
- ضع اﻵن الشيفرة التالية تحت سابقتها:
media.removeAttribute("controls"); controls.style.visibility = "visible";
تزيل الشيفرة السابقة مشغل الفيديو الافتراضي الخاص بالمتصفح ويُظهر أدوات التحكم المخصصة:
تشغيل وإيقاف الفيديو مؤقتًا
سننجز اﻵن شيفرة التحكم بزر التشغيل و اﻹيقاف المؤقت:
-
أضف بداية الشيفرة التالية في أسفل الشيفرة كي تُستدعى الدالة
()playPauseMedia
عند النقر على زر التشغيل:
play.addEventListener("click", playPauseMedia);
-
ولتعريف الدالة
()playPauseMedia
، أضف الشيفرة التالية إلى أسفل الشيفرة السابقة:
function playPauseMedia() { if (media.paused) { play.setAttribute("data-icon", "u"); media.play(); } else { play.setAttribute("data-icon", "P"); media.pause(); } }
نستخدم هنا عبارة if
للتحقق من توقف تشغيل الفيديو، وتعيد الخاصية HTMLMediaElement.paused
القيمة true
عند توقف التشغيل مؤقتًا بما في ذلك عند ضبطته على القيمة 0 بعد تحميله أول مرة. عند ذلك نضبط قيمة السمة data-icon
لزر التشغيل على u
التي تعرض بدورها أيقونة التشغيل المؤقت عليه، وتستدعي التابع ()HTMLMediaElement.play
لتشغيل الفيديو. وعند النقر على الزر مرة ثانية سيعود الزر كما كان، إذ تظهر أيقونة التشغيل وسيتوقف الفيديو بتنفيذ التابع ()HTMLMediaElement.paused
.
إيقاف عرض الفيديو
- نضيف بداية الشيفرة التي تتعامل مع إيقاف تشغيل الفيديو تحت الشيفرة السابقة:
stop.addEventListener("click", stopMedia); media.addEventListener("ended", stopMedia);
يضيف سطري الشيفرة مترصدي أحداث addEventListener
للتعامل مع الحدث click
الذي يوقف تشغيل الفيديو بتنفيذ الدالة ()stopMedia
عند النقر على زر اﻹيقاف. ولا بد من إيقاف التشغيل أيضًا عند إنتهاء المقطع، لهذا نترصد أيضًا الحدث ended
من خلال مترصد الحدث الثاني والذي ينفذ أيضًا الدالة ()stopMedia
عند انتهاء مقطع الفيديو.
-
نعرّف تاليًا الدالة
()stopMedia
، بإضاف اﻷسطر التالية بعد الدالة()playpauseMedia
:
function stopMedia() { media.pause(); media.currentTime = 0; play.setAttribute("data-icon", "P"); }
وبما أن الواجهة البرمجية HTMLMediaElement لا تقدم تابعًا مخصصًا ﻹيقاف عرض الفيديو، سنستخدم التابع ()pause
ﻹيقاف التشغيل مؤقتًا ثم نضبط قيمة الخاصية currentTime
على القيمة 0 ليعود الفيديو إلى البداية. فضبط قيمة هذه الخاصية (بالثواني) سينقل الموقع الحالي للفيديو إلى النقطة الزمنية المحددة. يبقى علينا فقط إظهار أيقونة التشغيل على زر التشغيل. وبصرف النظر عن وضع الفيديو سواءً كان قيد التشغيل أو أوقف مؤقتًا عند النقر على زر إيقاف التشغيل "Stop"، لابد أن تُظهر أن المشغل جاهز للعمل مجددًا.
التنقل بالفيديو إلى اﻷمام والخلف
ستجد العديد من الطرق لتقديم أو إعادة المشغل إلى نقطة زمنية محددة، وما سنعرضه حاليًا طريقة معقدة نوعًا ما في تنفيذ الأمر لتفادي اﻷخطاء التي قد تحدث عند النقر على أزرار مختلفة بترتيب غير متوقع.
- أضف مترصدي الحدث التاليين تحت تعريف المترصدين السابقين:
rwd.addEventListener("click", mediaBackward); fwd.addEventListener("click", mediaForward);
-
أضف الدالتين
()mediaBackWard
و()mediaForWard
التاليتين تحت الدوال السابقة، وستصبح الشيفرة كالتالي:
let intervalFwd; let intervalRwd; function mediaBackward() { clearInterval(intervalFwd); fwd.classList.remove("active"); if (rwd.classList.contains("active")) { rwd.classList.remove("active"); clearInterval(intervalRwd); media.play(); } else { rwd.classList.add("active"); media.pause(); intervalRwd = setInterval(windBackward, 200); } } function mediaForward() { clearInterval(intervalRwd); rwd.classList.remove("active"); if (fwd.classList.contains("active")) { fwd.classList.remove("active"); clearInterval(intervalFwd); media.play(); } else { fwd.classList.add("active"); media.pause(); intervalFwd = setInterval(windForward, 200); } }
هيأنا أولًا متغيرين intervalFwd
و intervlRwd
وسترى عملهما لاحقًا، كما ستلاحظ أن عمل الدالتين ()mediaBackWard
و ()mediaForWard
متطابق لكن بترتيب معكوس:
-
يجب تصفير اﻷصناف والمجالات التي ضبطناها عند تنفيذ وظيفة التقديم السريع للأمام، لأننا لو نقرنا على زر
rwd
بعد النقر على الرزfwd
من المفترض أن نلغي أي إعدادات خاصة بالتقديم السريع للمشغلfwd
واستبدالها بإعدادت التراجعrwd
، لأن المشغل سيخفق لو حاولنا النقر على كلا الزرين في نفس الوقت. -
استخدمنا عبارة
if
للتحقق من ضبط صنف الزرrwd
ليكونactive
في إشارة إلى أن الزر قد نُقر للتو. ويتمتع كل عنصر بالخاصيةclasslist
، وهي خاصية مفيدة تضم كل الأصناف التي يمتلكها العنصر وتقدم توابع ﻹزالة وإضافة اﻷصناف. وقد استخدمنا التابع()classList.contains
للتحقق من جود الصنفactive
ضمن أصناف الزر، وتعيد قيمة منطقيةtrue/false
. -
في حال كان
active
أحد أصناف العنصرrwd
نزيله باستخدام التابع()classList.remove
ثم نلغي قيمة الفاصل الزمني الذي ضُبط مسبقًا عندما نقرنا على الزر ومن ثم نستخدم التابع()HTMLMediaElement.play
ﻹلغاء العودة للخلف وتشغيل الفيديو بشكل طبيعي. -
إن لم يمتلك الزر تلك الخاصية نضيفها إليه باستخدام التابع
()clasList.add
ومن ثم نوقف الفيديو مؤقتًا باستخدام التابع()HTMLMediaElement.pause
. نضبط بعدها قيمة المتغيرintervalRwd
ليعادل القيمة المعادة من استدعاء الدالة()setInterval
. تُحدد هذه الدالة فترة زمنية معينة تنفذ بعد انقضائها الدالة التي تُمرر إليها كمعامل أول أما الفترة الزمنية فيحددها المعامل الثاني بالميلي ثانية. وهنا ننفذ الدالة كل 200 ميلي ثانية كي نعيد مشغل الفيديو إلى الخلف بوتيرة ثابتة. ولكي نوقف تنفيذ الدالة()setInterval
نستدعي الدالة()clearIterval
ممرين لها المتغيرintervalRwd
(الذي أسندت إليه الدالة()setInterval
). -
عرفنا أخيرًا الدالة
()windBackwrd
والدالة()windForward
اللتان تمررا إلى()setInterval
، لهذا أضف الشيفرة التالية تحت الدوال السابقة:
function windBackward() { if (media.currentTime <= 3) { rwd.classList.remove("active"); clearInterval(intervalRwd); stopMedia(); } else { media.currentTime -= 3; } } function windForward() { if (media.currentTime >= media.duration - 3) { fwd.classList.remove("active"); clearInterval(intervalFwd); stopMedia(); } else { media.currentTime += 3; } }
سنشرح تاليًا الدالة الأولى فقط لكون الدالتين متطابقتان من ناحية الشيفرة ومتعاكستان عملًا. وما فعلناه في الدالة ()windBackward
هو التالي (تذكر أنه بمجرد تفعيل الفاصل الزمني الذي سيتراجع فيه المشغل إلى الخلف ستُستدعى هذه الدالة كل 200 ميلي ثانية):
-
نبدأ الشيفرة بالعبارة
if
التي تتحقق أن المدة المنقضية من المقطع أقل من 3 ثانية، أي سيعود المشغل عند تراجعه إلى ما قبل نقطة البداية، وهذا ما يسبب سلوكًا غريبًا للمشغل. فلو كانت الحالة كذلك، نوقف تشغيل المقطع باستدعاء الدالة()stopMedia
ومن ثم نزيل الصنفactive
من قائمة أصناف الزرrwd
ونمحي قيمة المتغيرintervalRwd
ﻹيقاف عملية التراجع. وفي حال أهملنا هذه الخطوة اﻷخيرة سيستمر المشغل بالتراجع إلى ما لا نهاية. -
إن كان الوقت المنقضي أكبر من 3 ثانية، نزيل ثلاث ثوانٍ من الوقت الحالي باستخدام التعليمة
media.currentTime -=3
، أي نعيد مشغل الفيديو إلى ما قبل ثلاث ثوان وذلك كل 200 ميلي ثانية.
تحديث الوقت المنقضي
آخر ما سننفذه ﻹنجاز أدوات التحكم المخصصة بمشغل الفيديو هو تحديد الوقت المنقضي من زمن المقطع. لذا نشغّل دالة تحدّث الوقت الذي نعرضه في كل مرة يقع فيها الحدث timeupdate
المرتبط بالعنصر <video>
. أما تواتر عملية وقوع هذا الحدث، فتعتمد على المتصفح وقوة معالج جهازك.
أضف اﻵن السطر التالي الذي يعرّف مترصد تحديث زمن التشغيل:
media.addEventListener("timeupdate", setTime);
ولتعريف الدالة ()setTime
، أضف مايلي في أسفل ملف جافا سكريبت:
function setTime() { const minutes = Math.floor(media.currentTime / 60); const seconds = Math.floor(media.currentTime - minutes * 60); const minuteValue = minutes.toString().padStart(2, "0"); const secondValue = seconds.toString().padStart(2, "0"); const mediaTime = `${minuteValue}:${secondValue}`; timer.textContent = mediaTime; const barLength = timerWrapper.clientWidth * (media.currentTime / media.duration); timerBar.style.width = `${barLength}px`; }
هذه الدالة طويلة، لهذا سنناقشها خطوة خطوة:
-
نعمل بداية على تحديد الدقائق والثواني المنقضية من خلال قيمة
HTMLMediaElement.currentTime
. -
نهيئ بعد ذلك متغيرين إضافيين هما
minuteValue
وsecondValue
، ثم نستخدم التابع()padStart
لكي نمثّل قيمة الدقائق والثواني على شكل محرفين فقط حتى لو كانت القيمة رقمًا وحيدًا. -
أما الوقت الفعلي الذي سيُعرض فهو قيمة المتغير
minuteValue
تليه نقطتان متعامدتان ثم قيمة المتغيرsecondValue
. -
نضبط قيمة المؤقت
Node.textContent
لتعادل قيمة الوقت الحالي وبالتالي ستُعرض هذه القيمة على واجهة المشغّل. -
نحدد طول عنصر
<div>
الداخلي (الذي سيعرض شريط تقدم مقطع الفيديو) من خلال تحديد اتساع عنصر<div>
الخارجي (نأخذها من الخاصيةclientWidth
) ومن ثم ضرب هذه القيمة بالوقت الحاليHTMLMediaElement.currentTime
ونقسم على المدة الكلية لمقطع الفيديوHTMLMediaElement.duration
. -
نضبط قيمة اتساع العنصر
<div>
الداخلي ليعادل طول شريط تتبع تقدم الفيديو بعد إضافة القيمة "px" كي تشير إلى الاتساع مقدرًا بالبكسل.
إصلاح مشكلات التشغيل واﻹيقاف المؤقت للفيديو
هنالك مشكلة واحدة ولا بد من حلها. فعند النقر على زر التشغيل أو إيقاف الفيديو وزر التقديم أو التراجع، فلن يعمل هذا الزر! وما علينا إصلاحه هنا هو إلغاء وظائف التقدم أو التراجع عند النقر على زر التشغيل لمتابع العمل كما هو متوقع، وهذا أمر سهل.
أضف بداية الشيفرة التالية ضمن الدالة ()stopMedia
:
rwd.classList.remove("active"); fwd.classList.remove("active"); clearInterval(intervalRwd); clearInterval(intervalFwd);
أضف اﻵن نفس اﻷسطر في بداية الدالة ()playpauseMedia
(وقبل عبارة if
).
يمكنك اﻵن ازالة نفس الأسطر من الدالتين ()windBackwrd
و ()windForward
لأننا وضعنا هذه الوظيفة المشتركة بينهما في الدالة ()stopMedia
.
ملاحظة: يمكنك تحسين فعالية الشيفرة أكثر من خلال إنشاء دالة منفصلة تضم اﻷسطر السابقة ومن ثم استدعاء هذه الدالة عند الحاجة بدلًا من تكرار اﻷسطر عدة مرات في الشيفرة.
الخلاصة
تعلمنا في هذا المقال ما يكفي عن الواجهة HTMLMediaElement
التي تقدم كما كبيرًا من الوظائف ﻹنشاء مشغل وسائط متعددة، وما رأيناه هو مجرد جزء ضئيل من إمكانياتها.
إليك أخيرًا بعض الاقتراحات التي تساعد في تحسين مثالنا:
- يختل عمل المؤقت إن كانت مدة المقطع أكثر من ساعة (فلن يعرض الساعات بل الدقائق والثواني فقط). هل يمكنك تعديل الشيفرة لتعرض الساعات أيضًا؟
-
يمتلك العنصر
<audio>
نفس وظائفHTMLMediaElement
وبالتالي يمكنك تشغيل المقاطع الصوتية بسهولة، جرب لك. -
هل يمكنك إيجاد طريقة الانتقال إلى مكان ما من المقطع بالنقر على شريط تقدم الفيديو (العنصر
<div>
الداخلي). وكتلميح يمكنك إيجاد x و y لزوايا الشريط من خلال التابع()getBoundingClientRect
وإيجاد إحداثيي موقع مؤشر الفأرة من خلال كائن الحدث الذي ينتج عن حدث النقر على المستند. إليك مثالًا:
document.onclick = function (e) { console.log(e.x, e.y); };
ترجمة -وبتصرف- لمقال: Video and audio APIs
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.