Code trình phát nhạc vui vẻ cho người dùng sử dụng

Code trình phát nhạc có thể sử dụng cho bất kỳ dự án thiết kế nào của bạn. Bạn có thể sử dụng để người dùng tải nhạc lên để phát trực tiếp. Nếu bạn có ý tưởng tốt hơn có thể kết nối với các thư viện nhạc có sẵn để người dùng phát nhạc để nghe ngay lập tức.

Code trình phát nhạc có thể tuỳ chỉnh các hiệu ứng rất đẹp từ màu sắc, kích thước và nhiều thứ khác. Bạn có thể chỉnh sửa trong phần Code để thay đổi các thuộc tính theo nhu cầu của mình.

Code trình phát nhạc cho người dùng

Đầu tiên, Blog Lại Văn Đức mời bạn cùng xem demo hiển thị cho bộ code này. Bạn sẽ cần có bài hát định dạng MP3 trên máy vi tính hoặc điện thoại trước. Sau đó hãy nhấp vào Chọn Tệp để tải bài hết lên để nghe.

Bộ code này sẽ không tải file nhạc của bạn lên máy chủ lưu trữ code. Nó chỉ sử dụng để phát chính file nhạc bạn chọn.

Chia sẻ Code trình phát nhạc chi tiết

Đầu tiên, bạn cần gọi file js này về trước.

 <script src='http://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.5/dat.gui.min.js'></script>

Tiếp theo là Code HTML để làm khung cho ứng dụng phát nhạc này.

.musicControls
    input.audiofile(type='file')
    //- button.listenButton ...or listen to one of mine // Silly CORS
    button.playPauseButton ▶
i#loading Chọn một file âm thanh...

// This should match the values in the js
- var maxSideNum = 24
- var maxRectangleNum = 24

.prism
    - for (var x = 0; x < maxSideNum; x++)
        .side.hide
            - for (var y = 0; y < maxRectangleNum; y++)
                .rectangle.hide

Tất nhiên, chúng ta không thể thiếu CSS cho bộ code trình phát nhạc.

// All of the commented out things are from the static, pre-dat.gui version that are no longer necessary

//$sideNum: 12;
//$rectNum: 12;

//$width: 100px;
//$margin: 1% * 7.3;
$border: 3px solid #4DA16F; /* Default all same color */


* { box-sizing: border-box; }
html, body { height:100%; }
body { 
    background: rgb(30,30,30);
    font-family: 'Helvatica', sans-serif;
    color: #FFF;
    
    position:relative;
    perspective: 1000px;
    perspective-origin: 50% 50%;
}
.hide { display:none; }

.prism {
    position:absolute;
    //top:calc(50% - #{$width * 2});
    //left:calc(50% - #{$width * 0.5});
    //width:$width;
    //height:$width * 4;
    transform-style: preserve-3d;
    
    animation:rotate 8s linear infinite;
    
    display:none;
}

.side {
    width:100%;
    height:100%;
    border-top: $border;
    border-bottom: $border;
    border-color:currentColor;
    
    position:absolute;
}

.rectangle {    
    //height: (100% / $rectNum) - 2%;
    //width:80%;
    //margin:10px auto;
    border: $border;
    border-color:currentColor;
}

.solid .rectangle {
    background:currentColor;
}

//@for $i from 1 through $sideNum {
//    .side:nth-child(#{$i}) {
//        color: hsl(144, 55%, 20% + ($i / $sideNum) * 40%);
//       
//        transform: rotateY($i * (360 / $sideNum) + deg) translateZ($width * 1.85) rotateX(180deg); 
//    }
//    .side.rainbow:nth-child(#{$i}) {
//        color: hsl(360*($i / $sideNum), 80%, 55%);
//    }
//}

@keyframes rotate {
    from { transform:rotateY(0); }
    to { transform:rotateY(-360deg); }
}



.musicControls, i {
    position: absolute;
    border-radius: 5px;
    border: 1px solid rgba(255, 255, 255, 0.3);
    padding: 10px;
}
.musicControls { 
    top: 20px;
    left: 20px;
}

i {
  left: 50%;
  top: 50%;
  transform: translateY(-50%) translateX(-50%);
}


body.loaded {
    #loading {
      display: none;
    }
    
    .prism {
        display:block;
    }
}

Cuối cùng là linh hồn của bộ ứng dụng phát nhạc với JavaScript.

var maxSideNum = 24,
    maxRectangleNum = 24;

// Dat.gui setup
var Options = function() {
    this.height = 400;
    this.radius = 185;
    this.sideCount = 12;
    
    this.rectangleCount = 12;
    this.rectangleWidth = 80;
    this.vertMargin = 10;
    this.borderWidth = 3;
    
    this.color = 200;
    this.solidBG = false;
    this.rainbowMode = false;
    this.animateThroughSpectrum = false;
};


window.onload = function() {
    // dat.gui setup
    var myOptions = new Options(),
        gui = new dat.GUI(),
        f1 = gui.addFolder('Prism Controls'),
        f2 = gui.addFolder('Rectangle Controls'),
        f3 = gui.addFolder('Color Controls'),
        
        mySideCount = f1.add(myOptions, 'sideCount', 3, maxSideNum).step(1),
        myRadius = f1.add(myOptions, 'radius', 30, 600).step(15),
        myHeight = f1.add(myOptions, 'height', 50, 750).step(50),
        
        myRectangleCount = f2.add(myOptions, 'rectangleCount', 3, maxRectangleNum).step(1),
        myRectangleWidth = f2.add(myOptions, 'rectangleWidth', 1, 100).step(5),
        myVertMargin = f2.add(myOptions, 'vertMargin', 0, 15).step(1),
        myBorderWidth = f2.add(myOptions, 'borderWidth', 0, 15).step(1),
        
        myColor = f3.add(myOptions, 'color', 0, 360).step(1),
        mySolidBG = f3.add(myOptions, 'solidBG'),
        myRainbow = f3.add(myOptions, 'rainbowMode'),
        myAnimateThroughSpectrum = f3.add(myOptions, 'animateThroughSpectrum');
    
    f2.open();
    
    var audio,
        analyser,
        audioctx,
        sourceNode,
        stream;

    var audioInput = document.querySelector('.audiofile'),
        listenButton = document.querySelector(".listenButton"),
        playPauseButton = document.querySelector(".playPauseButton");

    var c = 0, // Used to change color over time
        paused = true;
  
    /*var myMusic = [
        "https://laivanduc.vn/wp-content/uploads/2021/12/Chieu-Cuoi-Tuan-Le-Quyen.mp3",
        "https://laivanduc.vn/wp-content/uploads/2021/12/Chieu-Cuoi-Tuan-Le-Quyen.mp3",
        "https://laivanduc.vn/wp-content/uploads/2021/12/Chieu-Cuoi-Tuan-Le-Quyen.mp3",
        "https://laivanduc.vn/wp-content/uploads/2021/12/Chieu-Cuoi-Tuan-Le-Quyen.mp3"
    ];*/
    
    var prism = document.querySelector(".prism"),
        sides = document.querySelectorAll(".side"),
        rectangleArray = [maxSideNum],
        lastTime = Date.now(),
        timeGap = 50;
    
    function rectangleSetup() {
        for(var i = 0; i < maxSideNum; i++) {
            rectangleArray[i] = sides[i].querySelectorAll(".rectangle");
        }
    }
    rectangleSetup();
    
    
    
    // dat.gui listeners
    
    // f1 listeners
    function sideCountChange(newCount) {
        [].forEach.call(sides, function(elem, i) {
            if(i < myOptions.sideCount) {
                // The circle is inscribed inside of the prism, so we can use this formula to calculate the side length
                var sideLength = 2 * (myOptions.radius) * Math.tan(Math.PI / newCount);
                prism.style.width = sideLength + "px";
                prism.style.left = "calc(50% - " + sideLength / 2 + "px)";
                
                sides[i].style.transform = "rotateY(" + i * (360 / newCount) + "deg) translateZ(" + myOptions.radius + "px) rotateX(180deg)";
                sides[i].classList.remove("hide");
            } else {
                sides[i].classList.add("hide");
            }
        });
    }
    mySideCount.onFinishChange(sideCountChange);
    sideCountChange(myOptions.sideCount);
    
    function radiusChange(newRadius) {
        sideCountChange(myOptions.sideCount);
    }
    myRadius.onFinishChange(radiusChange);
    radiusChange(myOptions.radius);
    
    function heightChange(newHeight) {
        prism.style.height = newHeight + "px";
        prism.style.top = "calc(50% - " + newHeight / 2 + "px)"
        rectangleCountChange(myOptions.rectangleCount);
    }
    myHeight.onFinishChange(heightChange);
    heightChange(myOptions.height);
    
    // f2 listeners 
    function rectangleCountChange(newCount) {
        [].forEach.call(rectangleArray, function(side, i) {
            [].forEach.call(side, function(rect, i) {
                if(i < myOptions.rectangleCount) {
                    rect.style.height = (myOptions.height - myOptions.vertMargin) / newCount - myOptions.vertMargin + "px";
                    rect.classList.remove("hide");
                } else {
                    rect.classList.add("hide");
                }
            });
        });
    }
    myRectangleCount.onFinishChange(rectangleCountChange);
    rectangleCountChange(myOptions.rectangleCount);
    
    function rectangleWidthChange(newWidth) {
        [].forEach.call(rectangleArray, function(side, i) {
            [].forEach.call(side, function(rect, i) {
                rect.style.width = newWidth + "%";
            });
        });
    }
    myRectangleWidth.onFinishChange(rectangleWidthChange);
    rectangleWidthChange(myOptions.rectangleWidth);
    
    function vertMarginChange(newMargin) {
        [].forEach.call(rectangleArray, function(side, i) {
            [].forEach.call(side, function(rect, i) {
                rect.style.margin = newMargin + "px auto";
            });
        });
        rectangleCountChange(myOptions.rectangleCount);
    }
    myVertMargin.onFinishChange(vertMarginChange);
    vertMarginChange(myOptions.vertMargin);
    
    function borderWidthChange(newWidth) {
        [].forEach.call(rectangleArray, function(side, i) {
            [].forEach.call(side, function(rect, i) {
                rect.style.borderWidth = newWidth + "px";
            });
        });
    }
    myBorderWidth.onFinishChange(borderWidthChange);
    borderWidthChange(myOptions.borderWidthChange);
    
    // f3 listeners
    function colorChange(value) {
        if(!myOptions.rainbowMode)
            [].forEach.call(sides, function(elem, i) {
                sides[i].style.color = "hsl(" + value + ", 55%, " + (20 + (i / myOptions.sideCount) * 40) + "%)";
            });
    }
    myColor.onFinishChange(colorChange);
    colorChange(myOptions.color);
    
    mySolidBG.onFinishChange(function(value) {
        if(value === true)
            prism.classList.add("solid");
        else
            prism.classList.remove("solid");
    });
    
    function goRainbowMode(value) {
        [].forEach.call(sides, function(elem, i) {
            if(value === true)
                sides[i].style.color = "hsl(" + 360 * (i / myOptions.sideCount) + ", 80%, 55%)";
            else
                colorChange(myOptions.color);
        });
    }
    myRainbow.onFinishChange(goRainbowMode);
    
    function checkAnimateThroughSpectrum() {
        if(myOptions.animateThroughSpectrum)
            [].forEach.call(sides, function(elem, i) {
                sides[i].style.color = "hsl(" + c + ", 80%, " + (20 + (i / myOptions.sideCount) * 40) + "%)";
            });
        else if(myOptions.rainbowMode)
            goRainbowMode(true);
        else
            colorChange(myOptions.color);
    }
    
    
    
    // The music player listeners
    audioInput.addEventListener('change', function(event) {
        if(event.target.files[0]) {
            // No error checking of file here, could be added
            stream = URL.createObjectURL(event.target.files[0]);
            
            loadSong(stream);
        }
    }, false);
    
    if(listenButton)
        listenButton.addEventListener('click', chooseOneOfMine, false);
    
    playPauseButton.addEventListener('click', togglePlayPause, false);
    
    
    // The music functions
    function setup() {
        // Stop the previous song if there is one
        if(audio)
            togglePlayPause();
        
        audio = new Audio();
        audioctx = new AudioContext();
        analyser = audioctx.createAnalyser();
        analyser.smoothingTimeConstant = 0.75;
        analyser.fftSize = 512;
        
        audio.addEventListener('ended', songEnded, false);
        
        sourceNode = audioctx.createMediaElementSource(audio);
        sourceNode.connect(analyser);
        sourceNode.connect(audioctx.destination);
    }
    
    function loadSong(stream) {
        setup();

        audio.src = stream;

        togglePlayPause();
        document.body.classList.add('loaded');
        update();
    }
    
    function songEnded() {
        document.body.classList.remove('loaded');
        togglePlayPause();
    }
    
    function togglePlayPause() {
        if(paused) {
            document.body.classList.add('loaded');
            audio.play();
            playPauseButton.innerText = "▮▮";
        } else if(!audio.paused && !audio.ended) {
            audio.pause();
            playPauseButton.innerText = "▶";
        }
        
        paused = !paused;
    }
    
    function chooseOneOfMine() {
        var num = Math.round(Math.random() * (myMusic.length - 1)) + 1;
        loadSong(myMusic[num]);
    }

    
    
    // The drawing functions 
    function drawSide(freqSequence, freqPercent) {   
        // Get the number of rectangles based on the freqValue
        drawRectangles(freqSequence, Math.floor(freqPercent * myOptions.rectangleCount / 100))
    }
    
    function drawRectangles(sideNum, numRectanglesShowing) {
        for(var i = 0; i < myOptions.rectangleCount; i++) {
            if(i <= numRectanglesShowing) {
                rectangleArray[sideNum][i].classList.remove("hide");
            } else {
                rectangleArray[sideNum][i].classList.add("hide");
            }
        }
    }

    var sectionsAveraged = [maxSideNum],
        countSinceLast = [maxSideNum];
    
    function update() {
        var currTime = Date.now();
        
        var freqArray = new Uint8Array(analyser.frequencyBinCount);
        analyser.getByteTimeDomainData(freqArray);

        // Find the average of the values near to each other (grouping)
        var average = 0,
            count = 0,
            numPerSection = 256 / (myOptions.sideCount + 1),
            nextSection = numPerSection;

        for (var i = 0; i < freqArray.length; i++) {
            var v = freqArray[i];
            average += Math.abs(128 - v); // 128 is essentially 0
            count++;
            
            if(i > nextSection) {
                var currentSection = Math.floor(i / numPerSection - 1);
                
                sectionsAveraged[currentSection] += average / count;
                countSinceLast[currentSection]++;
                
                average = 0;
                count = 0;
                nextSection += numPerSection;
            }
        }
        
        // Find the average of the values since the last time checked per section (smoothing)
        if(currTime - lastTime > timeGap) {  
            for (var i = 0; i < myOptions.sideCount; i++) {
                drawSide(i, (sectionsAveraged[i] / countSinceLast[i]), c);
                sectionsAveraged[i] = 0;
                countSinceLast[i] = 0;
            }
            
            lastTime = currTime;
        } 
        
        checkAnimateThroughSpectrum();
            
        c += 0.5;
        requestAnimationFrame(update);
    }
};

Download Code trình phát nhạc

Để mọi chuyện đơn giản hơn, bạn có thể download toàn bộ code trình phát nhạc này về và sử dụng ngay lập tức trên trình duyệt. Link download ngay bên dưới.

Sau khi tải về, bạn hãy giải nén và mở thư mục dist và chạy file index.html trên trình duyệt là được.

Thế Thôi

Bài viết chia sẻ code trình phát nhạc cho người dùng giúp bạn dễ dàng sử dụng và chỉnh sửa. Bạn có thể copy code để dùng hoặc tải toàn bộ code này để chạy ngay lập tức.

Chúc các bạn vui vẻ và thành công.

0 0 đánh giá
Đánh giá bài viết
guest
0 Bình luận
Phản hồi nội tuyến
Xem tất cả bình luận