Нужна помощь в переосмыслении моей концепции временной шкалы

Я создал небольшую страницу, на которой вы можете перетащить аудиофайл, который затем будет загружен. Затем создается форма волны и вычисляется количество ударов в минуту (ударов в минуту) звука. До сих пор: без проблем.

Затем я создаю (своего рода) горизонтальную шкалу времени, на которой отображается часть формы волны, которая будет прокручиваться, если вы воспроизводите звук. На осциллограмме нанесены «маркеры ударов». Они обозначают каждую «долю». Думаю, вы понимаете, о чем я. Затем на маркерах ударов есть «сетка», которая позволяет рисовать до четырех «нот» в каждой доле - до трех нот «одна над другой». Чтобы быть немного музыкальным: если доля равна 1/4 ноте, каждая нарисованная нота будет равна 1/16 ноте. Если вы сейчас немного запутались, просто посмотрите короткое видео ниже, и я уверен, что все ваши двусмысленности исчезнут. Такова концепция ... Вот небольшой демонстрационный видеоролик: http://www.youtube.com/watch?v=DkT4LcSAcvo

Теперь моя реализация для создания сетки:

<script type="text/javascript">
    function createBeatBoxes() {
        var duration = audio.duration;
        var measures = Math.floor((duration/(60/bpm))/beatPerMeasure); //calculate the amount of measures for the complete song - beatsPerMeasure defines time signature (eg. 4/4 or 3/4)
        var gapPixel = gap*secondWidth; //secondWidth defines how wide will be one second on the timeline (eg. "secondWidth=20" would mean the timeline of a song which is 10 seconds long would be 20*10 = 200 pixels wide)
        var measurePixel = secondWidth*(60/bpm)*beatPerMeasure; /defines the width of of one measure
        var beatPixel = measurePixel/beatPerMeasure; /defines the width of one beat
        var notePixel = beatPixel/notesPerBeat; /defines the width of one note - notesPerBeat defines the amount of notes in one beat
        for (i=1;i <= measures;i++) {

            var measureBox = document.createElement("div");
            measureBox.setAttribute('class', 'measureBox');
            if (i == 1) {
                measureBox.setAttribute('style', 'left:'+gapPixel+'px;width:'+measurePixel+'px');
            }
            else {
                measureBox.setAttribute('style', 'left:'+(((i-1)*measurePixel)+gapPixel)+'px;width:'+measurePixel+'px');
            }
            for (j=1;j <= beatPerMeasure;j++) {
                var beatBox = document.createElement("div");
                 beatBox.setAttribute('class', 'beatBox');
                beatBox.setAttribute('style', 'left:'+((j-1)*beatPixel)+'px;width:'+beatPixel+'px');
                for (k=1;k <= notesPerBeat;k++) {
                    var noteBarBox = document.createElement("div");
                    noteBarBox.setAttribute('class', 'noteBarBox');
                    noteBarBox.setAttribute('style', 'left:-'+(0.5*notePixel)+'px;width:'+notePixel+'px');
                        var noteBox = document.createElement("div");
                        noteBox.setAttribute('class', 'noteBox rednoteBox');
                        noteBox.setAttribute('onClick', 'toogleNote(this,"red")');
                        noteBarBox.appendChild(noteBox);
                        var noteBox = document.createElement("div");
                        noteBox.setAttribute('class', 'noteBox greennoteBox');
                        noteBox.setAttribute('onClick', 'toogleNote(this,"green")');
                        noteBarBox.appendChild(noteBox); 
                        var noteBox = document.createElement("div");
                        noteBox.setAttribute('class', 'noteBox bluenoteBox');
                        noteBox.setAttribute('onClick', 'toogleNote(this,"blue")');
                        noteBarBox.appendChild(noteBox); 
                    beatBox.appendChild(noteBarBox);
                }
                measureBox.appendChild(beatBox); 
            }
            document.querySelector('#timeline').appendChild(measureBox); 


        }
    }
</script>

Проблема с этой реализацией заключается в том, что сама шкала времени представляет собой очень широкий div (например, 950000px), содержащий img с нарисованной формой волны. В этом блоке есть много блоков мер, которые содержат (4) блока битов, которые снова содержат (4) блока нот с 3 различными блоками нот. Вот небольшой отрывок:

<div class="measureBox" style="left:1.746031745px;width:975.609756097561px">
    <div class="beatBox" style="left:0px;width:242.65243902439025px">
        <div class="noteBarBox" style="left:-29.964304878048782px;width:59.928609756097565px">
            <div class="noteBox rednoteBox" onclick="toogleNote(this,&quot;red&quot;)"></div>
            <div class="noteBox greennoteBox" onclick="toogleNote(this,&quot;green&quot;)"></div>
            <div class="noteBox bluenoteBox" onclick="toogleNote(this,&quot;blue&quot;)"></div>
            ...
        </div>
        ...
    </div>
    ...
</div>

Это CSS:

.measureBox {
    height:400px;
    float:left;
    border-right: 5px solid rgba(255,255,255,0.5);
    position:absolute;
    box-sizing:border-box;
    top:0;
}
.beatBox {
    height:400px;
    float:left;
    border-right: 3px solid rgba(255,255,255,0.5);
    box-sizing:border-box;
}
.noteBarBox {
    position: relative;
    height:400px;
    float:left;
    box-sizing:border-box;
}
.noteBox {
    float:left;
    height:133.33px;
    width:inherit;
    box-sizing:border-box;
    border-radius: 66.66px;
}
.redNoteBox { 
    top:0;
}
.greenNoteBox { 
    top:133.33px;
}
.blueNoteBox { 
    top:266.66px;
}

Суммируя все div, они имеют длину более 300 000 символов, которые, конечно же, больше не могут быть прокручены гладко, а процессор полностью перегружен.

Может быть, есть какой-нибудь другой способ создать эти «маркеры ударов» и возможность «рисовать» ноты на сетке через определенные промежутки / расстояния, которые не требуют такой большой нагрузки на процессор?

Я надеюсь, что вы придумаете несколько хороших идей или даже немного кода. Это было бы здорово, потому что я полностью застрял на этом.


person Loewe1000    schedule 16.08.2014    source источник


Ответы (1)


Используйте <canvas> и рисуйте только те элементы, которые должны быть видны в данный момент.

person Matt Ball    schedule 16.08.2014
comment
Спасибо вам за ваш быстрый ответ! :) Звучит вполне логично! Можете привести пример, как рисовать html-теги на холсте? Я понятия не имею ... - person Loewe1000; 17.08.2014
comment
Найдите себе документацию и / или учебник. Это большая тема. - person Matt Ball; 17.08.2014