mirax-player
Advanced tools
Comparing version 2.3.4 to 3.0.0-alpha.1
@@ -1,150 +0,168 @@ | ||
function miraxplayer(video) { | ||
// Check if the control elements have already been created | ||
const existingControls = document.querySelector('.mirax-theme'); | ||
if (existingControls) { | ||
return; | ||
} | ||
import './miraxplayerUI.js'; | ||
function miraxplayer(videoClip, playerTheme, progressTheme) { | ||
// Check if the control elements have already been created | ||
const existingControls = videoClip.parentNode.querySelector('.mirax-theme'); | ||
if (existingControls) { | ||
return; | ||
} | ||
// Create control elements | ||
const controlDiv = document.createElement('div'); | ||
controlDiv.className = 'mirax-theme'; | ||
// Check if the page is loaded | ||
document.onreadystatechange = function() { | ||
// If the page is loaded | ||
if (document.readyState == 'loaded' || document.readyState == 'complete') { | ||
// Get the video element | ||
const video = document.querySelector('.mirax-player'); | ||
// Check if the video is loaded | ||
if (video.readyState == 0) { | ||
// Create a text element | ||
const videoText = document.createElement('p'); | ||
// Set the text content | ||
videoText.textContent = 'Video not found'; | ||
// Set the class name | ||
videoText.className = 'video-text'; | ||
// Append the text element to the video element's parent node | ||
video.parentNode.appendChild(videoText); | ||
const controlDiv = document.createElement("div"); | ||
controlDiv.className = "mirax-theme"; | ||
controlDiv.style.backgroundColor = playerTheme; | ||
// Append the control div to the videoClip element's parent node | ||
videoClip.parentNode.appendChild(controlDiv); | ||
//**********************************************// | ||
// | ||
// PIP ( Picture in Picture ) | ||
// | ||
//*********************************************// | ||
const pipButton = document.createElement('mirax'); | ||
pipButton.className = 'pip-button'; | ||
controlDiv.appendChild(pipButton); | ||
pipButton.addEventListener('click', () => { | ||
if (document.pictureInPictureElement) { | ||
// Exit PiP | ||
document.exitPictureInPicture(); | ||
} else if (videoClip !== document.pictureInPictureElement) { | ||
// Request PiP | ||
videoClip.requestPictureInPicture(); | ||
} | ||
}); | ||
videoClip.addEventListener('enterpictureinpicture', handleEnterPiP); | ||
videoClip.addEventListener('leavepictureinpicture', handleLeavePiP); | ||
function handleEnterPiP(event) { | ||
// Update UI or perform actions when entering PiP | ||
console.log('Entered PiP mode'); | ||
} | ||
} | ||
}; | ||
// Append the control div to the video element's parent node | ||
video.parentNode.appendChild(controlDiv); | ||
const pipButton = document.createElement('mirax'); | ||
pipButton.className = 'pip-button'; | ||
controlDiv.appendChild(pipButton); | ||
pipButton.addEventListener('click', () => { | ||
if (document.pictureInPictureElement) { | ||
// Exit PiP | ||
document.exitPictureInPicture(); | ||
} else if (video !== document.pictureInPictureElement) { | ||
// Request PiP | ||
video.requestPictureInPicture(); | ||
function handleLeavePiP(event) { | ||
// Update UI or perform actions when leaving PiP | ||
console.log('Exited PiP mode'); | ||
} | ||
}); | ||
video.addEventListener('enterpictureinpicture', handleEnterPiP); | ||
video.addEventListener('leavepictureinpicture', handleLeavePiP); | ||
function handleEnterPiP(event) { | ||
// Update UI or perform actions when entering PiP | ||
console.log('Entered PiP mode'); | ||
} | ||
document.addEventListener('keydown', (event) => { | ||
// Check if Alt+P is pressed | ||
if (event.altKey && event.code === 'KeyP') { | ||
// Toggle PiP mode | ||
if (document.pictureInPictureElement) { | ||
document.exitPictureInPicture(); | ||
} else { | ||
videoClip.requestPictureInPicture(); | ||
} | ||
} | ||
}); | ||
function handleLeavePiP(event) { | ||
// Update UI or perform actions when leaving PiP | ||
console.log('Exited PiP mode'); | ||
} | ||
document.addEventListener('keydown', (event) => { | ||
// Check if Alt+P is pressed | ||
if (event.altKey && event.code === 'KeyP') { | ||
// Toggle PiP mode | ||
if (document.pictureInPictureElement) { | ||
document.exitPictureInPicture(); | ||
//______________________________________________________________________ | ||
//**********************************************// | ||
// | ||
// Play Button | ||
// | ||
//*********************************************// | ||
// Define event listener and function for the play button | ||
const playButton = document.createElement('mirax'); | ||
playButton.className = 'play-button'; | ||
playButton.addEventListener('click', playerButton); | ||
controlDiv.appendChild(playButton); | ||
function playerButton() { | ||
if (videoClip.paused) { | ||
videoClip.play(); | ||
playButton.classList.add("pause"); // Add the pause class name | ||
} else { | ||
video.requestPictureInPicture(); | ||
videoClip.pause(); | ||
playButton.classList.remove("pause"); // Remove the pause class name | ||
} | ||
} | ||
}); | ||
video.addEventListener('dblclick', toggleFullscreen); | ||
// Define event listener and function for the play button | ||
const playButton = document.createElement('mirax'); | ||
playButton.className = 'play-button'; | ||
playButton.addEventListener('click', playerButton); | ||
controlDiv.appendChild(playButton); | ||
function playerButton() { | ||
if (video.paused) { | ||
video.play(); | ||
playButton.classList.add("pause"); // Add the pause class name | ||
} else { | ||
video.pause(); | ||
playButton.classList.remove("pause"); // Remove the pause class name | ||
// Add event listener to the video element itself to toggle play state | ||
videoClip.addEventListener('click', () => { | ||
if (videoClip.paused) { | ||
videoClip.play(); | ||
playButton.classList.add("pause"); | ||
} else { | ||
videoClip.pause(); | ||
playButton.classList.remove("pause"); | ||
} | ||
}); | ||
// Update the styles or UI of the play button based on video state | ||
function updatePlayButton() { | ||
if (videoClip.paused) { | ||
playButton.classList.remove("pause"); | ||
} else { | ||
playButton.classList.add("pause"); | ||
} | ||
} | ||
} | ||
// Add event listener to the video element itself to toggle play state | ||
video.addEventListener('click', () => { | ||
if (video.paused) { | ||
video.play(); | ||
playButton.classList.add("pause"); | ||
} else { | ||
video.pause(); | ||
playButton.classList.remove("pause"); | ||
// Listen to video play and pause events | ||
videoClip.addEventListener('play', updatePlayButton); | ||
videoClip.addEventListener('pause', updatePlayButton); | ||
//______________________________________________________________________ | ||
//**********************************************// | ||
// | ||
// Play video - press space bar | ||
// | ||
//*********************************************// | ||
// Add keydown event listener to the document | ||
document.addEventListener('keydown', function(event) { | ||
// Check if the pressed key is the space bar | ||
if (event.code === 'Space') { | ||
// Prevent the default action of scrolling | ||
event.preventDefault(); | ||
// Call the same function that you use for the play button | ||
playerButton(); | ||
} | ||
}); | ||
// Update the styles or UI of the play button based on video state | ||
function updatePlayButton() { | ||
if (video.paused) { | ||
playButton.classList.remove("pause"); | ||
} else { | ||
playButton.classList.add("pause"); | ||
} | ||
} | ||
// Listen to video play and pause events | ||
video.addEventListener('play', updatePlayButton); | ||
video.addEventListener('pause', updatePlayButton); | ||
// Add keydown event listener to the document | ||
document.addEventListener('keydown', function(event) { | ||
// Check if the pressed key is the space bar | ||
if (event.code === 'Space') { | ||
// Prevent the default action of scrolling | ||
event.preventDefault(); | ||
// Call the same function that you use for the play button | ||
playerButton(); | ||
} | ||
}); | ||
//______________________________________________________________________ | ||
//**********************************************// | ||
// | ||
// Volume slider | ||
// | ||
//*********************************************// | ||
let prevVolume = 1; | ||
// Create the volume input element | ||
const volumeInput = document.createElement('input'); | ||
@@ -157,650 +175,301 @@ volumeInput.type = 'range'; | ||
volumeInput.defaultValue = '1'; | ||
// Add event listener to update volume | ||
volumeInput.addEventListener('input', function() { | ||
video.volume = parseFloat(this.value); | ||
videoClip.volume = parseFloat(this.value); | ||
}); | ||
controlDiv.appendChild(volumeInput); | ||
// Create a div element for the speaker icon container | ||
// Create a div element for the speaker icon container | ||
const speakerIconContainer = document.createElement('div'); | ||
speakerIconContainer.className = 'speaker-icon'; | ||
speakerIconContainer.style.width = '20px'; | ||
speakerIconContainer.style.height = '50px'; | ||
speakerIconContainer.style.position = 'absolute'; | ||
speakerIconContainer.style.left = '33px'; // Set the left property to 0 | ||
speakerIconContainer.style.right = 'auto'; // Set the right property to auto | ||
// The rest of the code is the same as before | ||
// Create a div element for the speaker box | ||
const speakerBox = document.createElement('div'); | ||
speakerBox.className = 'box'; | ||
speakerBox.style.width = '6px'; | ||
speakerBox.style.height = '6px'; | ||
speakerBox.style.backgroundColor = 'white'; | ||
speakerBox.style.borderRadius = '2px'; | ||
speakerBox.style.position = 'absolute'; | ||
speakerBox.style.left = '2px'; | ||
speakerBox.style.top = '22px'; | ||
// Create a div element for the speaker cone | ||
// Create a div element for the speaker cone | ||
const speakerCone = document.createElement('div'); | ||
speakerCone.className = 'cone'; | ||
speakerCone.style.width = '0'; | ||
speakerCone.style.height = '0'; | ||
speakerCone.style.borderTop = '6px solid transparent'; | ||
speakerCone.style.borderBottom = '6px solid transparent'; | ||
speakerCone.style.borderRight = '13px solid white'; // Swap the border-left and border-right properties | ||
speakerCone.style.borderLeft = '0'; // Swap the border-left and border-right properties | ||
speakerCone.style.position = 'absolute'; | ||
speakerCone.style.top = '19px'; | ||
// Append the speaker box and cone to the speaker icon container | ||
speakerIconContainer.appendChild(speakerBox); | ||
speakerIconContainer.appendChild(speakerCone); | ||
// Append the speaker icon container to the controlDiv | ||
controlDiv.appendChild(speakerIconContainer); | ||
// Create a span element for the x symbol | ||
const xSymbol = document.createElement('span'); | ||
xSymbol.className = 'x-symbol'; | ||
xSymbol.textContent = 'x'; | ||
xSymbol.style.fontSize = '12px'; | ||
xSymbol.style.color = 'gray'; | ||
xSymbol.style.position = 'absolute'; | ||
xSymbol.style.left = '17px'; | ||
xSymbol.style.top = '18px'; | ||
xSymbol.style.fontFamily = 'Arial, Corbel'; | ||
xSymbol.style.color = 'white'; | ||
xSymbol.style.display = 'none'; // Hide the x symbol by default | ||
// Append the x symbol to the speaker icon container | ||
speakerIconContainer.appendChild(xSymbol); | ||
// Add event listener to update volume and x symbol | ||
volumeInput.addEventListener('input', function() { | ||
video.volume = parseFloat(this.value); | ||
// If the volume is zero, show the x symbol | ||
if (video.volume === 0) { | ||
xSymbol.style.display = 'block'; | ||
} | ||
// Otherwise, hide the x symbol | ||
else { | ||
xSymbol.style.display = 'none'; | ||
} | ||
}); | ||
// The rest of the code is the same as before | ||
const progressBar = document.createElement('progress'); | ||
progressBar.className = 'progress-bar'; | ||
progressBar.min = '0'; | ||
progressBar.max = '100'; | ||
progressBar.value = '0'; | ||
controlDiv.appendChild(progressBar); | ||
video.addEventListener('timeupdate', function() { | ||
const percentPlayed = (video.currentTime / video.duration) * 100; | ||
progressBar.value = percentPlayed; | ||
controlDiv.appendChild(volumeInput); | ||
//______________________________________________________________________ | ||
//**********************************************// | ||
// | ||
// Speaker UI icon | ||
// | ||
//*********************************************// | ||
// Create a div element for the speaker icon container | ||
const speakerIconContainer = document.createElement('div'); | ||
speakerIconContainer.className = 'speaker-icon'; | ||
speakerIconContainer.style.width = '20px'; | ||
speakerIconContainer.style.height = '50px'; | ||
speakerIconContainer.style.position = 'absolute'; | ||
speakerIconContainer.style.left = '33px'; // Set the left property to 0 | ||
speakerIconContainer.style.right = 'auto'; // Set the right property to auto | ||
speakerIconContainer.style.cursor = 'pointer'; | ||
// Create a div element for the speaker box | ||
const speakerBox = document.createElement('div'); | ||
speakerBox.className = 'box'; | ||
speakerBox.style.width = '6px'; | ||
speakerBox.style.height = '6px'; | ||
speakerBox.style.backgroundColor = 'white'; | ||
speakerBox.style.borderRadius = '2px'; | ||
speakerBox.style.position = 'absolute'; | ||
speakerBox.style.left = '2px'; | ||
speakerBox.style.top = '22px'; | ||
// Create a div element for the speaker cone | ||
const speakerCone = document.createElement('div'); | ||
speakerCone.className = 'cone'; | ||
speakerCone.style.width = '0'; | ||
speakerCone.style.height = '0'; | ||
speakerCone.style.borderTop = '6px solid transparent'; | ||
speakerCone.style.borderBottom = '6px solid transparent'; | ||
speakerCone.style.borderRight = '13px solid white'; // Swap the border-left and border-right properties | ||
speakerCone.style.borderLeft = '0'; // Swap the border-left and border-right properties | ||
speakerCone.style.position = 'absolute'; | ||
speakerCone.style.top = '19px'; | ||
// Append the speaker box and cone to the speaker icon container | ||
speakerIconContainer.appendChild(speakerBox); | ||
speakerIconContainer.appendChild(speakerCone); | ||
// Append the speaker icon container to the controlDiv | ||
controlDiv.appendChild(speakerIconContainer); | ||
//______________________________________________________________________ | ||
//**********************************************// | ||
// | ||
// Mute - x appear | ||
// | ||
//*********************************************// | ||
// Create a span element for the x symbol | ||
const xSymbol = document.createElement('span'); | ||
xSymbol.className = 'x-symbol'; | ||
xSymbol.textContent = 'x'; | ||
xSymbol.style.fontSize = '12px'; | ||
xSymbol.style.color = 'white'; // Set the color to white once | ||
xSymbol.style.position = 'absolute'; | ||
xSymbol.style.left = '17px'; | ||
xSymbol.style.top = '18px'; | ||
xSymbol.style.fontFamily = 'Arial, Corbel'; | ||
xSymbol.style.display = 'none'; // Hide the x symbol by default | ||
// Append the x symbol to the speaker icon container | ||
speakerIconContainer.appendChild(xSymbol); | ||
// Add event listener to update volume and x symbol | ||
volumeInput.addEventListener('input', function() { | ||
// Use the video element directly | ||
videoClip.volume = parseFloat(this.value); | ||
// If the volume is zero, show the x symbol | ||
if (videoClip.volume === 0) { | ||
xSymbol.style.display = 'block'; | ||
} | ||
// Otherwise, hide the x symbol | ||
else { | ||
xSymbol.style.display = 'none'; | ||
} | ||
}); | ||
progressBar.addEventListener('mousedown', function(e) { | ||
const rect = progressBar.getBoundingClientRect(); | ||
const offsetX = e.clientX - rect.left; | ||
const newProgress = (offsetX / rect.width) * 100; | ||
video.currentTime = (newProgress / 100) * video.duration; | ||
const onMouseMove = function(e) { | ||
// Add event listener to the speaker icon container | ||
speakerIconContainer.addEventListener("click", function() { | ||
// Toggle the mute state of the video element | ||
videoClip.muted = !videoClip.muted; | ||
// Change the color of the speaker icon based on the mute state | ||
if (videoClip.muted) { | ||
// Set the color to gray | ||
speakerBox.style.backgroundColor = "gray"; | ||
speakerCone.style.borderRightColor = "gray"; | ||
xSymbol.style.display = 'block'; | ||
// Store the current volume value before setting it to zero | ||
prevVolume = volumeInput.value; | ||
volumeInput.value = '0'; | ||
videoClip.volume = 0; | ||
} else { | ||
// Set the color to white | ||
speakerBox.style.backgroundColor = "white"; | ||
speakerCone.style.borderRightColor = "white"; | ||
xSymbol.style.display = 'none'; | ||
// Restore the previous volume value after unmuting | ||
volumeInput.value = prevVolume; | ||
videoClip.volume = parseFloat(prevVolume); | ||
} | ||
}); | ||
//**********************************************// | ||
// | ||
// Progress bar slider | ||
// | ||
//*********************************************// | ||
const progressBar = document.createElement('progress'); | ||
progressBar.className = 'progress-bar'; | ||
progressBar.min = '0'; | ||
progressBar.max = '100'; | ||
progressBar.value = '0'; | ||
controlDiv.appendChild(progressBar); | ||
videoClip.addEventListener('timeupdate', function() { | ||
const percentPlayed = (videoClip.currentTime / videoClip.duration) * 100; | ||
progressBar.value = percentPlayed; | ||
}); | ||
progressBar.addEventListener('mousedown', function(e) { | ||
const rect = progressBar.getBoundingClientRect(); | ||
const offsetX = e.clientX - rect.left; | ||
const newProgress = (offsetX / rect.width) * 100; | ||
video.currentTime = (newProgress / 100) * video.duration; | ||
}; | ||
const onMouseUp = function() { | ||
document.removeEventListener('mousemove', onMouseMove); | ||
document.removeEventListener('mouseup', onMouseUp); | ||
}; | ||
document.addEventListener('mousemove', onMouseMove); | ||
document.addEventListener('mouseup', onMouseUp); | ||
}); | ||
// After creating the currentTimeDiv | ||
const currentTimeDiv = document.createElement('div'); | ||
currentTimeDiv.className = 'current-time'; | ||
controlDiv.appendChild(currentTimeDiv); | ||
// Listen to the timeupdate event to update the current time | ||
video.addEventListener('timeupdate', updateCurrentTime); | ||
// Function to update the current time in the currentTimeDiv | ||
function updateCurrentTime() { | ||
const currentTime = formatTime(video.currentTime); | ||
currentTimeDiv.textContent = currentTime; | ||
} | ||
// Function to format time in mm:ss format | ||
function formatTime(timeInSeconds) { | ||
const minutes = Math.floor(timeInSeconds / 60); | ||
const seconds = Math.floor(timeInSeconds % 60); | ||
return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`; | ||
} | ||
// ... | ||
// Function to format time in HH:MM:SS | ||
function formatTime(seconds) { | ||
const hours = Math.floor(seconds / 3600); | ||
const minutes = Math.floor((seconds % 3600) / 60); | ||
const secs = Math.floor(seconds % 60); | ||
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`; | ||
} | ||
// Function to update current time | ||
function updateCurrentTime() { | ||
currentTimeDiv.textContent = formatTime(video.currentTime); | ||
} | ||
// Set initial content of currentTimeDiv | ||
currentTimeDiv.textContent = formatTime(0); | ||
// Listen to the timeupdate event to update the current time | ||
video.addEventListener('timeupdate', updateCurrentTime); | ||
// Function to format time in HH:MM:SS format | ||
function formatTimex(seconds) { | ||
const date = new Date(null); | ||
date.setSeconds(seconds); | ||
return date.toISOString().substr(11, 8); | ||
} | ||
// Function to update time duration | ||
function updateDuration() { | ||
if (!isNaN(video.duration)) { // Check if the duration is available (not NaN) | ||
const formattedDuration = formatTimex(video.duration); | ||
const timeDurationDiv = document.querySelector('.time-duration'); | ||
if (timeDurationDiv) { | ||
videoClip.currentTime = (newProgress / 100) * videoClip.duration; | ||
const onMouseMove = function(e) { | ||
const offsetX = e.clientX - rect.left; | ||
const newProgress = (offsetX / rect.width) * 100; | ||
videoClip.currentTime = (newProgress / 100) * videoClip.duration; | ||
}; | ||
const onMouseUp = function() { | ||
document.removeEventListener('mousemove', onMouseMove); | ||
document.removeEventListener('mouseup', onMouseUp); | ||
}; | ||
document.addEventListener('mousemove', onMouseMove); | ||
document.addEventListener('mouseup', onMouseUp); | ||
}); | ||
// After creating the currentTimeDiv | ||
const currentTimeDiv = document.createElement('div'); | ||
currentTimeDiv.className = 'current-time'; | ||
controlDiv.appendChild(currentTimeDiv); | ||
// Listen to the timeupdate event to update the current time | ||
videoClip.addEventListener('timeupdate', updateCurrentTime); | ||
// Function to update the current time in the currentTimeDiv | ||
function updateCurrentTime() { | ||
const currentTime = formatTime(videoClip.currentTime); | ||
currentTimeDiv.textContent = currentTime; | ||
} | ||
// Function to format time in mm:ss format | ||
function formatTime(timeInSeconds) { | ||
const minutes = Math.floor(timeInSeconds / 60); | ||
const seconds = Math.floor(timeInSeconds % 60); | ||
return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`; | ||
} | ||
// Function to format time in HH:MM:SS | ||
function formatTime(seconds) { | ||
const hours = Math.floor(seconds / 3600); | ||
const minutes = Math.floor((seconds % 3600) / 60); | ||
const secs = Math.floor(seconds % 60); | ||
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`; | ||
} | ||
// Function to update current time | ||
function updateCurrentTime() { | ||
currentTimeDiv.textContent = formatTime(videoClip.currentTime); | ||
} | ||
// Set initial content of currentTimeDiv | ||
currentTimeDiv.textContent = formatTime(0); | ||
// Listen to the timeupdate event to update the current time | ||
videoClip.addEventListener('timeupdate', updateCurrentTime); | ||
// Function to format time in HH:MM:SS format | ||
function formatTimex(seconds) { | ||
const date = new Date(null); | ||
date.setSeconds(seconds); | ||
return date.toISOString().substr(11, 8); | ||
} | ||
// Function to update time duration | ||
function updateDuration(videoClip, timeDurationDiv) { | ||
if (!isNaN(videoClip.duration)) { | ||
const formattedDuration = formatTimex(videoClip.duration); | ||
timeDurationDiv.textContent = formattedDuration; | ||
} | ||
} | ||
} | ||
const timeDurationDiv = document.createElement('div'); | ||
timeDurationDiv.className = 'time-duration'; | ||
controlDiv.appendChild(timeDurationDiv); | ||
// Listen to the loadedmetadata event to update the duration | ||
video.addEventListener('loadedmetadata', updateDuration); | ||
const fullscreenButton = document.createElement('mirax'); | ||
fullscreenButton.className = 'fullscreen'; | ||
controlDiv.appendChild(fullscreenButton); | ||
fullscreenButton.addEventListener('click', toggleFullscreen); | ||
const timeDurationDiv = document.createElement('div'); | ||
timeDurationDiv.className = 'time-duration'; | ||
controlDiv.appendChild(timeDurationDiv); | ||
videoClip.addEventListener('loadedmetadata', () => updateDuration(videoClip, timeDurationDiv)); | ||
function toggleFullscreen() { | ||
if (video.requestFullscreen) { | ||
if (document.fullscreenElement) { | ||
document.exitFullscreen(); | ||
} else { | ||
video.requestFullscreen(); | ||
} | ||
//**********************************************// | ||
// | ||
// Progress bar value color | ||
// | ||
//*********************************************// | ||
var color_progress_bar = progressTheme; | ||
const inputProgressBar = document.createElement('style'); | ||
document.head.appendChild(inputProgressBar); | ||
const inputProgressBarStyle = ` | ||
progress::-webkit-progress-bar { | ||
background-color: rgba(205, 228, 235, 0.1); | ||
} | ||
progress::-webkit-progress-value { | ||
background-color: ${color_progress_bar}; | ||
} | ||
progress[value]::-moz-progress-bar { | ||
background-color: ${color_progress_bar}; | ||
} | ||
} | ||
} | ||
// Define the content string | ||
const content_fullscreen = "\\02752"; | ||
const content_play = "\\25B6"; | ||
const content_pause = "\\2590" + "\\A0" + "\\258C"; | ||
const content_speaker = "\\1F508"; | ||
const content_pip = "\\0393"; | ||
const miraxStyle = document.createElement('style'); | ||
document.head.appendChild(miraxStyle); | ||
const styles = ` | ||
.mirax-player { | ||
max-width: 740px; | ||
width: 100%; /* This ensures the video fills its container while respecting max-width */ | ||
height: auto; /* This maintains the video's aspect ratio */ | ||
min-height:100px; | ||
max-height:580px; | ||
background-color: #000000; | ||
margin: 0 auto; | ||
} | ||
/* Hide the control div by default */ | ||
.mirax-theme { | ||
display: none; | ||
} | ||
/* Show the control div when hovering over the video or itself */ | ||
.mirax-player:hover + .mirax-theme, | ||
.mirax-theme:hover { | ||
display: block; | ||
margin: 0 auto; | ||
position: relative; | ||
width: 100%; | ||
height: 20px; | ||
max-width:740px; | ||
margin-top:-34px; | ||
bottom: 0; | ||
left: 0; | ||
background-color: rgba(0, 0, 0, 0.5); | ||
color: #fff; | ||
padding-top:5px; | ||
padding-bottom:5px; | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
} | ||
.play-button { | ||
position: relative; | ||
margin-left: 20px; | ||
transform: translateX(-50%); | ||
background: none; | ||
color: #fff; | ||
border-style: none; | ||
border-radius: 0; | ||
cursor: pointer; | ||
font-size: 13px; | ||
transition: background-color 0.3s ease, transform 0.3s ease; | ||
} | ||
progress::-ms-fill { | ||
background-color: ${color_progress_bar}; | ||
} | ||
`; | ||
inputProgressBar.appendChild(document.createTextNode(inputProgressBarStyle)); | ||
.play-button:hover { | ||
background:none; | ||
} | ||
.play-button::before { | ||
content: "${content_play}"; | ||
font-size:13px; | ||
} | ||
.play-button.pause::before { | ||
content: "${content_pause}"; | ||
color:white; | ||
font-size:10px; | ||
} | ||
/* Style the volume slider */ | ||
.volume-slider { | ||
position: absolute; | ||
float: left; | ||
margin-left:59px; | ||
width:100%; | ||
max-width:50px; | ||
height: 5px; | ||
outline: none; | ||
border-radius: 0; | ||
cursor: pointer; | ||
-webkit-appearance: none; /* Remove default appearance for Chrome, Safari and Opera */ | ||
-moz-appearance: none; /* Remove default appearance for Firefox */ | ||
appearance: none; /* Remove default appearance for Edge */ | ||
} | ||
.volume-slider::-moz-range-track { | ||
height: 10px; | ||
background-color: rgba(255, 255, 255, 0.1); | ||
border: none; | ||
-webkit-appearance: none; /* Remove default appearance for Chrome, Safari and Opera */ | ||
-moz-appearance: none; /* Remove default appearance for Firefox */ | ||
appearance: none; /* Remove default appearance for Edge */ | ||
} | ||
.volume-slider::-moz-range-thumb { | ||
width: 5px; | ||
height: 10px; | ||
border-style:none; | ||
border-radius:0%; | ||
background-color: rgba(0, 0, 0, 0.5); | ||
cursor: pointer; | ||
-webkit-appearance: none; /* Remove default appearance for Chrome, Safari and Opera */ | ||
-moz-appearance: none; /* Remove default appearance for Firefox */ | ||
appearance: none; /* Remove default appearance for Edge */ | ||
} | ||
.volume-slider::-moz-range-progress { | ||
height: 10px; | ||
background-color: rgba(255, 255, 255, 0.1); /* Change the color of the half bar */ | ||
-webkit-appearance: none; /* Remove default appearance for Chrome, Safari and Opera */ | ||
-moz-appearance: none; /* Remove default appearance for Firefox */ | ||
appearance: none; /* Remove default appearance for Edge */ | ||
} | ||
/* Styling for the track */ | ||
.volume-slider::-webkit-slider-runnable-track { | ||
height: 10px; | ||
background-color: rgba(205, 228, 235, 0.1); | ||
border: none; | ||
-webkit-appearance: none; /* Remove default appearance for Chrome, Safari and Opera */ | ||
-moz-appearance: none; /* Remove default appearance for Firefox */ | ||
appearance: none; /* Remove default appearance for Edge */ | ||
} | ||
/* Styling for the thumb */ | ||
.volume-slider::-webkit-slider-thumb { | ||
width: 5px; | ||
height: 10px; | ||
border-style: none; | ||
border-radius: 0%; | ||
background-color: rgba(0, 0, 0, 0.5); | ||
cursor: pointer; | ||
-webkit-appearance: none; /* Remove default appearance for Chrome, Safari and Opera */ | ||
-moz-appearance: none; /* Remove default appearance for Firefox */ | ||
appearance: none; /* Remove default appearance for Edge */ | ||
} | ||
/* Styling for the progress */ | ||
.volume-slider::-webkit-progress-value { | ||
height: 10px; | ||
background-color: rgba(205, 228, 235, 0.1); | ||
-webkit-appearance: none; /* Remove default appearance for Chrome, Safari and Opera */ | ||
-moz-appearance: none; /* Remove default appearance for Firefox */ | ||
appearance: none; /* Remove default appearance for Edge */ | ||
} | ||
.volume-slider :hover { | ||
opacity: 0.5; | ||
} | ||
/* .speaker-icon { | ||
position: absolute; | ||
float: left; | ||
margin-top:-25px; | ||
margin-left:32px; | ||
} | ||
.speaker-icon::before { | ||
position: absolute; | ||
content: "${content_speaker}"; | ||
font-size: 17px; | ||
//**********************************************// | ||
// | ||
// Double Click Fullscreen | ||
// | ||
//*********************************************// | ||
} */ | ||
.current-time { | ||
position: absolute; | ||
float: left; | ||
margin-left:118px; | ||
font-family: "Lucida Console", "Arial", monospace; | ||
margin-top: 2px; | ||
font-size:12px; | ||
} | ||
.time-duration { | ||
min-width:40px; | ||
width: 100%; | ||
max-width: 70px; | ||
position: absolute; | ||
right: 0; | ||
margin-right:20px; | ||
font-family: "Lucida Console", "Arial", monospace; | ||
margin-top: 2px; | ||
font-size:12px; | ||
} | ||
.progress-bar { | ||
position: absolute; | ||
width: 100%; | ||
max-width:425px; | ||
float: left; | ||
margin-left: 196px; | ||
background-color: rgba(205, 228, 235, 0.1); | ||
border-style: none; | ||
} | ||
progress::-webkit-progress-value { | ||
background-color: rgba(240, 255, 254, 0.3); | ||
} | ||
progress::-webkit-progress-bar { | ||
background-color: rgba(205, 228, 235, 0.1); | ||
} | ||
progress[value]::-moz-progress-bar { | ||
background-color: rgba(240, 255, 254, 0.3); | ||
} | ||
progress::-ms-fill { | ||
background-color: rgba(240, 255, 254, 0.3); | ||
} | ||
.pip-button { | ||
min-width:20px; | ||
width: 100%; | ||
max-width: 30px; | ||
position: absolute; | ||
right:0; | ||
margin-top: 4px; | ||
margin-right:81px; | ||
height: 20px; | ||
background: none; | ||
color: #fff; | ||
border-style: none; | ||
border-radius: 0; | ||
cursor: pointer; | ||
transition: color 0.3s ease; | ||
font-size:15px; | ||
} | ||
videoClip.addEventListener('dblclick', toggleFullscreen); | ||
.pip-button::before { | ||
content: "${content_pip}"; | ||
} | ||
.pip-button:hover{ | ||
opacity: 0.5; | ||
} | ||
.fullscreen { | ||
min-width:20px; | ||
width: 100%; | ||
max-width: 30px; | ||
position: absolute; | ||
right:0; | ||
height: 20px; | ||
background: none; | ||
color: #fff; | ||
border-style: none; | ||
border-radius: 0; | ||
cursor: pointer; | ||
transition: color 0.3s ease; | ||
font-size:15px; | ||
} | ||
.fullscreen:hover { | ||
color: #bbdeff; | ||
} | ||
//______________________________________________________________________ | ||
.fullscreen::before { | ||
content: "${content_fullscreen}"; | ||
} | ||
/* Style the text elements */ | ||
.video-text, .input-text { | ||
position: absolute; | ||
top: 50%; | ||
left: 50%; | ||
transform: translate(-50%, -50%); | ||
color: white; | ||
background: black; | ||
padding: 10px; | ||
margin: 10px; | ||
width:auto; | ||
font-family: "Lucida Console", "Arial", monospace; | ||
} | ||
.video-text, .input-text { | ||
//**********************************************// | ||
// | ||
// Fullscreen Button | ||
// | ||
//*********************************************// | ||
background-image: url('https://raw.githubusercontent.com/demjhonsilver/mirax-player/main/img/logo.png'); | ||
background-position: center center; | ||
background-repeat: no-repeat; | ||
min-width:100px; | ||
width:50%; | ||
max-width:300px; | ||
min-height:150px; | ||
height: auto; | ||
max-height:190px; | ||
} | ||
`; | ||
miraxStyle.appendChild(document.createTextNode(styles)); | ||
// __________________________________________________________ | ||
const miraxStyleMediaQuery = document.createElement('style'); | ||
document.head.appendChild(miraxStyleMediaQuery); | ||
// Define the media query and its associated CSS rules | ||
const mediaQuery = ` | ||
@media (max-width: 740px) { | ||
.progress-bar { | ||
min-width:30px; | ||
width: 40%; | ||
background-color: rgba(205, 228, 235, 0.1); | ||
} | ||
} | ||
`; | ||
miraxStyleMediaQuery.appendChild(document.createTextNode(mediaQuery)); | ||
// __________________________________________________________ | ||
const miraxStyleMediaQuery2 = document.createElement('style'); | ||
document.head.appendChild(miraxStyleMediaQuery2); | ||
// Define the media query and its associated CSS rules | ||
const mediaQuery2 = ` | ||
@media (max-width: 540px) { | ||
.progress-bar { | ||
min-width:30px; | ||
width: 30%; | ||
background-color: rgba(205, 228, 235, 0.1); | ||
} | ||
} | ||
`; | ||
miraxStyleMediaQuery2.appendChild(document.createTextNode(mediaQuery2)); | ||
// __________________________________________________________ | ||
const miraxStyleMediaQuery3 = document.createElement('style'); | ||
document.head.appendChild(miraxStyleMediaQuery3); | ||
// Define the media query and its associated CSS rules | ||
const mediaQuery3 = ` | ||
@media (max-width: 540px) { | ||
.progress-bar { | ||
margin-left: 160px; | ||
min-width:30px; | ||
width: 17%; | ||
background-color: rgba(205, 228, 235, 0.1); | ||
} | ||
const fullscreenButton = document.createElement('mirax'); | ||
fullscreenButton.className = 'fullscreen'; | ||
controlDiv.appendChild(fullscreenButton); | ||
.volume-slider { | ||
position: fixed; | ||
float: left; | ||
margin-left: 53px; | ||
margin-top:3px; | ||
width:90%; | ||
max-width:40px; | ||
height: 10px; | ||
fullscreenButton.addEventListener('click', toggleFullscreen); | ||
function toggleFullscreen() { | ||
if (videoClip.requestFullscreen) { | ||
if (document.fullscreenElement) { | ||
document.exitFullscreen(); | ||
} else { | ||
videoClip.requestFullscreen(); | ||
} | ||
} | ||
} | ||
.current-time { | ||
margin-left:96px; | ||
} | ||
.video-text, .input-text { | ||
width:100%; | ||
max-width:240px; | ||
min-height:110px; | ||
height: auto; | ||
max-height:120px; | ||
} | ||
} | ||
`; | ||
miraxStyleMediaQuery3.appendChild(document.createTextNode(mediaQuery3)); | ||
/* # Mirax Player core license | ||
@@ -807,0 +476,0 @@ |
//index.js - This is your package's entry point | ||
export { default as miraxplayer } from './dist/MiraxPlayer'; | ||
export { default as miraxErrorHandler } from './dist/ErrorHandler'; | ||
@@ -5,0 +6,0 @@ |
{ | ||
"name": "mirax-player", | ||
"version": "2.3.4", | ||
"description": "Mirax Player is a video player has compatibility of typescript and javascript for React, Vue, Angular and Svelte.", | ||
"version": "3.0.0-alpha.1", | ||
"description": "Mirax Player is a video player that is compatible with TypeScript and JavaScript for React, Vue, Angular and Svelte.", | ||
"main": "index.js", | ||
@@ -6,0 +6,0 @@ "scripts": { |
551
README.md
@@ -36,5 +36,2 @@ <p align="center"> | ||
- [React](#react) | ||
- [Vue](#vue) | ||
- [Angular](#angular) | ||
- [Svelte](#svelte) | ||
- [Style](#style) | ||
@@ -48,3 +45,3 @@ - [Colors](#colors) | ||
Mirax Player is a video player has compatibility of typescript and javascript for React, Vue, Angular and Svelte. You can customize the theme color of the video player. Robust and easy to implement with readability syntax and light-weight. | ||
Mirax Player is a video player that is compatible with TypeScript and JavaScript for React, Vue, Angular and Svelte. You can customize the theme color of the video player. It is robust and easy to implement, featuring readable syntax and lightweight design. It was written in pure JavaScript but can be implemented in both TypeScript and JavaScript. | ||
@@ -55,2 +52,12 @@ ![React](https://img.shields.io/badge/react-%2320232a.svg?style=for-the-badge&logo=react&logoColor=%2361DAFB) | ||
![Svelte](https://img.shields.io/badge/svelte-%23f1413d.svg?style=for-the-badge&logo=svelte&logoColor=white) | ||
Frameworks / Library | Tested Versions | JavaScript | TypeScript | | ||
---- | ------------------ | ----------- | ------------ | | ||
React | React 18 & above | `Yes` | `Yes` | | ||
Vue | Vue 3 & above | `Yes` | `Yes` | | ||
Angular | Angular 16 & above| `No` | `Yes` | | ||
Svelte | Svelte 4 & above | `Yes` | `Yes` | | ||
------------ | ||
@@ -87,3 +94,3 @@ Supported scripts: | ||
`click` ▶ | Play & Pause | The video will play or pause | All browsers | ||
`alt+p or cmd+p` | PiP | Picture in Picture screen | `!firefox auto pip icon` | ||
`alt+p or cmd+p` | PiP | Picture in Picture screen | `!firefox but auto appear PiP icon` | ||
`click` Γ | PiP | Picture in Picture screen | All browsers | ||
@@ -98,260 +105,87 @@ `double click the video` | Fullscreen | It will set as fullscreen mode | All browsers | ||
In your component | ||
------------------ | ||
Mirax Player version 3 has major changes: | ||
Then use it from Mirax Player: | ||
-------------- | ||
- You can now declare value of colors inside to your component app. | ||
```js | ||
- Mirax Player can now play multiple videos. | ||
//both react,vue, angular and svelte importing syntax | ||
- Adding `miraxErrorHandler` in separate function. | ||
import { miraxplayer } from 'mirax-player'; | ||
// for React (video file stored: public/clip.mp4) | ||
const video = useRef(null); | ||
// | ||
// for Vue (video file stored: public/clip.mp4) | ||
const video = ref(null); | ||
// | ||
// for Angular (video file stored: src/assets/clip.mp4) | ||
@ViewChild('video', { static: true }) video!: ElementRef<HTMLVideoElement>; | ||
// | ||
// for Svelte (video file stored: public/clip.mp4) | ||
let video; | ||
// | ||
``` | ||
Sources | Usage | Themes | React | Vue | Angular | Svelte | | ||
---- | ---------------------- | ----------- | ------- | --------- | ------ | -------- | ||
`Local or hosted one video File` | Video Player | Yes | Tested | Not yet | Not yet | Not yet | | ||
`Local or hosted multiple video files` | Video Player | Yes | Tested | Not yet | Not yet | Not yet | | ||
## React | ||
------------------ | ||
You need to use useRef in React hooks: | ||
----------- | ||
```js | ||
"Reminder: This is an alpha test." | ||
import React, { useEffect, useRef } from 'react'; | ||
import { miraxplayer } from 'mirax-player'; | ||
------------ | ||
const ExampleComponent = () => { | ||
const video = useRef(null); | ||
useEffect(() => { | ||
if (video.current) { | ||
miraxplayer(video.current); | ||
} | ||
}, []); | ||
"Soon, it will also be available in Vue, Angular, and Svelte." | ||
return ( | ||
<div className='whatever'> | ||
<video ref={video} className="mirax-player" src="clip.mp4"></video> | ||
</div> | ||
); | ||
}; | ||
export default ExampleComponent; | ||
-------- | ||
syntax for importing Mirax Player : | ||
```js | ||
``` | ||
Typescript: React | ||
--------- | ||
// Importing syntax for React, Vue, Angular, and Svelte: | ||
```js | ||
import React, { useEffect, useRef } from 'react'; | ||
import { miraxplayer } from 'mirax-player'; | ||
const ExampleComponent: React.FC = () => { | ||
const video = useRef<HTMLVideoElement>(null); | ||
useEffect(() => { | ||
if (video.current) { | ||
miraxplayer(video.current); | ||
} | ||
}, []); | ||
return ( | ||
<div className='whatever'> | ||
<video ref={video} className="mirax-player" src="clip.mp4"></video> | ||
</div> | ||
); | ||
}; | ||
export default ExampleComponent; | ||
``` | ||
## Vue | ||
------------------ | ||
You need to use ref in Vue attributes: | ||
----------- | ||
```js | ||
<template> | ||
<div class="whatever"> | ||
<video ref="video" class="mirax-player" src="clip.mp4"></video> | ||
</div> | ||
</template> | ||
## React | ||
<script> | ||
import { ref, onMounted } from 'vue'; | ||
import { miraxplayer } from 'mirax-player'; | ||
You need to use "useRef" in React hooks: | ||
----------- | ||
export default { | ||
name: 'ExampleComponent', | ||
setup() { | ||
const video = ref(null); | ||
For one video only: | ||
onMounted(() => { | ||
if (video.value) { | ||
miraxplayer(video.value); | ||
} | ||
}); | ||
return { | ||
video | ||
}; | ||
} | ||
}; | ||
</script> | ||
``` | ||
Typescript: Vue | ||
------------- | ||
```js | ||
<template> | ||
<div class="whatever"> | ||
<video ref="video" class="mirax-player" src="clip.mp4"></video> | ||
</div> | ||
</template> | ||
<script lang="ts"> | ||
import { ref, onMounted } from 'vue'; | ||
import { miraxplayer } from 'mirax-player'; | ||
export default { | ||
name: 'ExampleComponent', | ||
setup() { | ||
const video = ref<HTMLVideoElement | null>(null); | ||
onMounted(() => { | ||
if (video.value) { | ||
miraxplayer(video.value); | ||
} | ||
}); | ||
return { | ||
video | ||
}; | ||
} | ||
}; | ||
</script> | ||
``` | ||
## Angular | ||
------------------ | ||
You need to use ElementRef native DOM element: | ||
--------- | ||
example.component.ts | ||
----------- | ||
```js | ||
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'; | ||
import { miraxplayer } from 'mirax-player'; | ||
import React, { useEffect, useRef } from "react"; | ||
import { miraxplayer, miraxErrorHandler } 'mirax-player'; | ||
@Component({ | ||
selector: 'app-example', | ||
templateUrl: './example.component.html', | ||
styleUrls: ['./example.component.css'] | ||
}) | ||
const ExampleComponent = () => { | ||
const videoRef = useRef(null); | ||
const playerTheme = "rgba(250, 149, 35, 0.9)"; | ||
const progressTheme = "blue"; | ||
export class ExampleComponent implements OnInit { | ||
@ViewChild('video', { static: true }) video!: ElementRef<HTMLVideoElement>; | ||
ngOnInit(): void { | ||
this.initializeMiraxplayer(); | ||
} | ||
initializeMiraxplayer() { | ||
if (this.video.nativeElement) { | ||
miraxplayer(this.video.nativeElement); | ||
useEffect(() => { | ||
if (videoRef.current) { | ||
miraxplayer(videoRef.current, playerTheme, progressTheme); | ||
miraxErrorHandler(videoRef.current); // Pass the DOM element to the function | ||
} | ||
} | ||
}, []); | ||
} | ||
return ( | ||
<div className="whatever"> | ||
<video ref={videoRef} className="mirax-player" src="clip.mp4"></video> | ||
</div> | ||
); | ||
}; | ||
export default ExampleComponent; | ||
``` | ||
-------------------------------------- | ||
example.component.html | ||
------------- | ||
```html | ||
------------ | ||
For multiple videos: | ||
<div> | ||
<div class="whatever"> | ||
<video #video class="mirax-player" src="assets/clip.mp4"></video> | ||
</div> | ||
</div> | ||
``` | ||
## Svelte | ||
You need to use bind:this in svelte: | ||
----------- | ||
```js | ||
<script> | ||
import { onMount } from 'svelte'; | ||
import { miraxplayer } from 'mirax-player'; | ||
// "Reminder: This is an alpha test." | ||
let video; | ||
onMount(() => { | ||
if (video) { | ||
const miraxPlayer = miraxplayer(video); | ||
} | ||
}); | ||
</script> | ||
<div> | ||
<div class='whatever'> | ||
<video bind:this={video} class="mirax-player" src="clip3.mp4"> | ||
<track kind="captions" src="" label="English" default> | ||
</video> | ||
</div> | ||
</div> | ||
``` | ||
Typescipt: Svelte | ||
-------- | ||
```js | ||
<script lang="ts"> | ||
import { onMount } from 'svelte'; | ||
import { miraxplayer } from 'mirax-player'; | ||
let video: HTMLVideoElement | undefined; | ||
onMount(() => { | ||
if (video) { | ||
const miraxPlayer = miraxplayer(video); | ||
} | ||
}); | ||
</script> | ||
<div> | ||
<div class='whatever'> | ||
<video bind:this={video} class="mirax-player" src="clip.mp4"> | ||
<track kind="captions" src="" label="English" default> | ||
</video> | ||
</div> | ||
</div> | ||
``` | ||
-------------------------------------- | ||
@@ -362,120 +196,8 @@ | ||
- note: .whatever, you can rename it, just make sure the classname in your component also replace it. | ||
--------- | ||
```js | ||
// in React | ||
<div className='whatever'> | ||
<video ref={video} className="mirax-player" src="clip.mp4"></video> | ||
</div> | ||
// in Vue | ||
<div class="whatever"> | ||
<video ref="video" class="mirax-player" src="clip.mp4"></video> | ||
</div> | ||
// in Angular | ||
<div class="whatever"> | ||
<video #video class="mirax-player" src="assets/clip.mp4"></video> | ||
</div> | ||
// in Svelte | ||
<div class='whatever'> | ||
<video bind:this={video} class="mirax-player" src="clip.mp4"> | ||
<track kind="captions" src="" label="English" default> | ||
</video> | ||
</div> | ||
``` | ||
---------------- | ||
Left Alignment: ( 3 progress syntax should be remain ) | ||
-------------- | ||
```css | ||
.whatever { | ||
margin: 0 auto; | ||
position: relative; | ||
width: 100%; | ||
text-align: left; | ||
} | ||
.mirax-theme { | ||
float: left!important; | ||
background-color: rgba(36, 22, 223, 0.5)!important; | ||
} | ||
progress::-webkit-progress-value { | ||
background-color: rgb(65, 7, 224, 0.9)!important; | ||
} | ||
progress[value]::-moz-progress-bar { | ||
background-color: rgb(65, 7, 224, 0.9)!important; | ||
} | ||
progress::-ms-fill { | ||
background-color: rgb(65, 7, 224, 0.9)!important; | ||
} | ||
``` | ||
---------- | ||
Center Alignment: ( 3 progress syntax should be remain ) | ||
-------------- | ||
```css | ||
## Style | ||
.whatever { | ||
margin: 0 auto; | ||
position: relative; | ||
width: 100%; | ||
text-align: center; | ||
} | ||
.mirax-theme { | ||
margin: 0 auto!important; | ||
background-color: rgba(36, 22, 223, 0.5)!important; | ||
} | ||
progress::-webkit-progress-value { | ||
background-color: rgb(65, 7, 224, 0.9)!important; | ||
} | ||
progress[value]::-moz-progress-bar { | ||
background-color: rgb(65, 7, 224, 0.9)!important; | ||
} | ||
progress::-ms-fill { | ||
background-color: rgb(65, 7, 224, 0.9)!important; | ||
} | ||
You can assign your own class name to encapsulate the video player. | ||
``` | ||
-------- | ||
Right Alignment: ( 3 progress syntax should be remain ) | ||
--------- | ||
```css | ||
.whatever { | ||
margin: 0 auto; | ||
position: relative; | ||
width: 100%; | ||
text-align: right; | ||
} | ||
.mirax-theme { | ||
float: right!important; | ||
background-color: rgba(36, 22, 223, 0.5)!important; | ||
} | ||
progress::-webkit-progress-value { | ||
background-color: rgb(65, 7, 224, 0.9)!important; | ||
} | ||
progress[value]::-moz-progress-bar { | ||
background-color: rgb(65, 7, 224, 0.9)!important; | ||
} | ||
progress::-ms-fill { | ||
background-color: rgb(65, 7, 224, 0.9)!important; | ||
} | ||
``` | ||
---------- | ||
## Style | ||
You can set your own class name to wrap the video player | ||
---------------------------- | ||
@@ -494,3 +216,3 @@ | ||
You have freedom to set a theme color for free. | ||
You have the freedom to freely set a theme color. | ||
@@ -501,159 +223,40 @@ | ||
---------- | --------- | ---------------- | -------------------- | --------------- | ||
`RGBA` | rgba() | rgba(255,0,0, 0.5) | `0.1 to 0.9` or `0 to 1` | Red half transparency | ||
`RGBA` | rgba() | rgba(255,0,0, 0.5) | `0.1 to 0.9` or `0 and 1` | Red half transparency | ||
`RGB` |rgb() | rgb(255, 0, 0) | `none` | Red | ||
`HEXA` | # | #ff0000| `none` | Red | ||
`HEXA` | #6digits | #ff0000| `none` | Red | ||
`COLORNAME` | colorname | red | `none` | Red | ||
------------- | ||
To change color and theme, just add to your css file | ||
---------- | ||
To change color and theme, simply add the necessary code to your component app. | ||
Reminder for progress bar: 3 progress syntax must declared | ||
------------------- | ||
```css | ||
progress::-webkit-progress-value { | ||
//change color here | ||
} | ||
progress[value]::-moz-progress-bar { | ||
//change color here | ||
} | ||
progress::-ms-fill { | ||
//change color here | ||
} | ||
``` | ||
----------- | ||
if you want pure transparent: | ||
--------- | ||
```bash | ||
- note always put !important at the end of statement. | ||
``` | ||
```css | ||
.mirax-theme { | ||
background-color: rgba(4, 88, 25, 0.2)!important; | ||
} | ||
progress::-webkit-progress-value { | ||
background-color: rgb(252, 227, 7)!important; | ||
} | ||
progress[value]::-moz-progress-bar { | ||
background-color: rgb(252, 227, 7)!important; | ||
} | ||
progress::-ms-fill { | ||
background-color: rgb(252, 227, 7)!important; | ||
} | ||
``` | ||
--------------------------- | ||
if you want pure transparent, mirax-theme only: | ||
--------- | ||
change into: | ||
--------- | ||
```css | ||
```js | ||
.mirax-theme { | ||
background: none !important; | ||
} | ||
const playerTheme = "none"; | ||
``` | ||
--------------- | ||
Sample themes: | ||
------------- | ||
```css | ||
---------------------- | ||
.mirax-theme { | ||
background-color: purple!important; | ||
} | ||
progress::-webkit-progress-value { | ||
background-color: lime!important; | ||
} | ||
progress[value]::-moz-progress-bar { | ||
background-color: lime!important; | ||
} | ||
progress::-ms-fill { | ||
background-color: lime!important; | ||
} | ||
## Features | ||
- Play and Pause | ||
- Can play multiple videos | ||
- Responsiveness | ||
- Automatically hides the player bar | ||
- Capable of playing videos (Portrait or Landscape) | ||
- Supports 9:16 dimensions (Mobile video) | ||
- Fullscreen functionality | ||
- Adjustable volume (low or high) | ||
- Customizable color themes | ||
- Allows you to point and drag the timestamp anywhere within the video's duration | ||
- Supports PIP (Picture-in-Picture), allowing the clip to continue playing even if you switch to a new app while leaving the tab open. | ||
``` | ||
------------------- | ||
```css | ||
.mirax-theme { | ||
background-color: rgba(250, 149, 35, 0.9)!important; | ||
} | ||
progress::-webkit-progress-value { | ||
background-color: rgb(17, 117, 59)!important; | ||
} | ||
progress[value]::-moz-progress-bar { | ||
background-color: rgb(17, 117, 59)!important; | ||
} | ||
progress::-ms-fill { | ||
background-color: rgb(17, 117, 59)!important; | ||
} | ||
``` | ||
----------- | ||
```css | ||
.mirax-theme { | ||
background: none !important; | ||
} | ||
progress::-webkit-progress-value { | ||
background-color: rgba(253, 75, 90, 0.897)!important; | ||
} | ||
progress[value]::-moz-progress-bar { | ||
background-color: rgba(253, 75, 90, 0.897)!important; | ||
} | ||
progress::-ms-fill { | ||
background-color: rgba(253, 75, 90, 0.897)!important; | ||
} | ||
``` | ||
--------------- | ||
```css | ||
.mirax-theme { | ||
background: none !important; | ||
} | ||
progress::-webkit-progress-value { | ||
background-color: rgba(250, 234, 5, 0.7)!important; | ||
} | ||
progress[value]::-moz-progress-bar { | ||
background-color: rgba(250, 234, 5, 0.7)!important; | ||
} | ||
progress::-ms-fill { | ||
background-color: rgba(250, 234, 5, 0.7)!important; | ||
} | ||
``` | ||
---------------------- | ||
## Features | ||
- Play and Pause | ||
- Responsive | ||
- Auto hide the player bar | ||
- Can play videos (Portrait or Landscape) | ||
- 9:16 dimension supported (Mobile video) | ||
- Fullscreen | ||
- Adjust the volume (low or high) | ||
- Can change color themes | ||
- You can point and drag the timestamp in video time duration anywhere | ||
- PIP supported (picture in picture) will play the clip even if you leave the tab open for new app | ||
---------------------------------------------------- | ||
@@ -660,0 +263,0 @@ ## License |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
10
732
37270
2
266
1