2016-09-04 2 views
2

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

Моя формула для построения этой функции является: ms = 1 pixel/(initial size/duration), по сути вычисления, сколько миллисекунд должно пройти, прежде чем вычитанием 1px из элемента height или width.

Моя математическая логика говорит, что функция должна быть заполнена в 1000ms, но для меня время, которое требуется для завершения, выглядит значительно больше, не зная, сколько.

Почему требуется дольше, чем 1s Заполнить и что может быть причиной этого?

Код:

/* ----- JavaScript ----- */ 
 
function slide(el, duration, direction) { 
 
    /* Default */ 
 
    duration = duration || 1000, direction = direction || "vertical"; 
 

 
    var 
 
    dim = (direction === "horizontal") ? "width" : "height", 
 
     
 
    /* Get how tall or wide el is in 'px' */ 
 
    size = initSize = parseFloat(
 
     getComputedStyle(el, null).getPropertyValue(dim) || el.style[dim] 
 
    ), 
 
     
 
    /* Get the previous size, so as to restore el to it */ 
 
    prevSize = el.style["prev" + dim] || 0, 
 
     
 
    /* Calculating how many ms should pass before subtracting 1px*/ 
 
    ms = 1/(initSize/duration), 
 
     
 
    interval = setInterval(function() { 
 
     /* If el is visible */ 
 
     if (initSize > prevSize && size > prevSize) el.style[dim] = --size + "px"; 
 
     
 
     /* If el is not visible */ 
 
     else if (prevSize > initSize && size <= prevSize) el.style[dim] = ++size + "px"; 
 
     
 
     /* Clear the interval when 0 is reached and cache the previous size */ 
 
     else { 
 
     console.log("oops") 
 
     el.style["prev" + dim] = initSize; 
 
     clearInterval(interval); 
 
     } 
 
    }, ms); 
 
} 
 

 
slide(document.getElementById("a"));
<!----- HTML -----> 
 
<div id = "a" style = "width: 200px;height: 300px;background-color:black;"></div>

+3

что значение 'ms'? чем меньше это, тем менее точным будет время - я бы посмотрел на 'requestAnimationFrame' и реорганизовал ваш код, чтобы вычесть определенное количество пикселей на анимационный кадр - другими словами, вычислить количество пикселей для вычитания в зависимости от сколько времени прошло с момента предыдущего кадра - заканчивается в более плавной согласованной анимации –

+1

Ваша функция не * * завершена: она никогда не попадает в 'clearInterval()'. Проверьте консоль вашего браузера ...Кроме того, в отношении вашего комментария о том, что «время, которое требуется для завершения, выглядит значительно больше, не зная, сколько», почему бы вам не измерить его с помощью 'console.log (Date.now())' перед запуском и на укажите, что вы вызываете 'clearInterval()', или смотрите на использование ['console.time()'] (https://developer.mozilla.org/en-US/docs/Web/API/Console/time) ... – nnnnnn

+0

@JaromandaX, если у нас есть элемент с ** 'height: 300px' ** и установленная продолжительность **' 300ms' **, ** 'ms' ** будет равна **' 1' ** * (1/(300px/300ms)) * –

ответ

1

После некоторых мыслей, читая комментарии Jaromanda X заставили меня есть, я, наконец, в конечном итоге, используя window.requestAnimationFrame(), так как это более эффективно, чем setInterval(), и это также не заставит браузер перерисовки.

Это, в свою очередь, заставило меня изменить свою формулу от времени ориентированной (ms = 1/(initial size/duration)) на пиксель-ориентированный (px = frame * (initial size/duration)).

скольжения является более гладким сейчас и очень близко к 1000ms, только 5-7ms различие, которое я считаю, происходит, потому что я установил переменную в frame к 1000/60 не принимая во внимание частоту кадров падает, что может возникнуть.

Код:

/* ----- JavaScript ----- */ 
 
function slide(el, duration, direction) { 
 
    /* Set Defaults and record starting date */ 
 
    var a = Date.now(); 
 
    duration = duration || 1000, direction = direction || "vertical"; 
 

 
    var 
 
    dim = (direction === "horizontal") ? "width" : "height", 
 

 
    /* Get how tall or wide el is in 'px' */ 
 
    size = initSize = parseFloat(
 
     getComputedStyle(el, null).getPropertyValue(dim) || el.style[dim] 
 
    ), 
 

 
    /* Get the previous size, so as to restore el to it */ 
 
    prevSize = el.style["prev" + dim] || 0, 
 

 
    /* Calculating how many px should be added/subtracted each frame */ 
 
    frame = 1000/60, 
 
    px = frame * (initSize/duration), 
 
    step = (initSize > prevSize) ? -px : px; 
 

 
    window.requestAnimationFrame(function transform() { 
 
    el.style[dim] = (size > 0) ? (size += step) + "px" : (size = 0); 
 
    if (size === 0) { 
 
     el.style["prev" + dim] = initSize; 
 
     //element.style.prevDisplay = initDisplay; 
 
     console.log(Date.now() - a) 
 
    } else window.requestAnimationFrame(transform); 
 
    }, frame); 
 
} 
 

 
slide(document.getElementById("a"), 1000);
<!----- HTML -----> 
 
<div id="a" style="width: 200px;height: 300px;background-color:black;"></div>

+0

Я получаю время с 1984 по 2000 год - что является ошибкой одного кадра анимации по какой-то причине –

+0

@JaromandaX 1984 до 2000? Как? Я только что получил 999 и 1003. –

+0

извините, проверил ваш код с 2000;) ... с 1000 я получаю 984 до 1000 –

1

вам нужно настроить свой шаг крупности т.е. пикселя, которые будут добавлены/удалены на одну итерацию и настроить время задержки. следующая - улучшенная версия, которая занимает около 1,1 сек.

function slide(el, duration, direction) { 
    /* Default */ 
    duration = duration || 1000, direction = direction || "vertical"; 

    var dim = (direction === "horizontal") ? "width" : "height", 

    /* Get how tall or wide el is in 'px' */ 
    size = initSize = parseFloat(
     getComputedStyle(el, null).getPropertyValue(dim) || el.style[dim] 
    ), 

    /* Get the previous size, so as to restore el to it */ 
    prevSize = el.style["prev" + dim] || 0; 

    /* Calculating how many ms should pass before subtracting 1px*/ 
    var step = 1; 
    var ms = 1/(initSize/duration) 
    if(ms<10){ 
     ms=10; 
     step = 10*(initSize/duration); 
     console.log(ms,step) 
    } 
     var now=new Date(); 
     var interval;var i=0; 
    var animate = function() { 
    i++; 
     interval=setTimeout(animate,ms); 
     /* If el is visible */ 
     if (initSize > prevSize && size > prevSize) el.style[dim] = (size=size-step) + "px"; 

     /* If el is not visible */ 
     else if (prevSize > initSize && size <= prevSize) el.style[dim] = (size=size+step) + "px"; 

     /* Clear the interval when 0 is reached and cache the previous size */ 
     else { 
     console.log("oops", new Date()-now,size,step,i) 
     el.style["prev" + dim] = initSize; 
     clearInterval(interval); 
     } 
    }; 
    //var interval = setInterval(animate, ms); 
    animate(); 
} 
slide(document.getElementById("a")); 
+0

Привет, спасибо за ваш ответ. Это действительно уменьшает время скольжения до 1100 мс, что лучше, чем тот, который у меня был, поэтому я поддержал :) После некоторого исследования я в конечном итоге изменил свой код на тот, который указан в [этом ответе] (http://stackoverflow.com/ a/39314177/6313073), уменьшая его еще больше до среднего значения 1005 мс. –

+1

приятно слышать, что у вас есть лучшее решение. удачи! –