Це все хороші ідеї в теорії, поки не заглибишся. Проблема полягає в тому, що ви не можете придушити RAF, не сканувавши синхронізацію, переможивши його ціль, що існує. Тож ви дозволяєте йому працювати на повній швидкості та оновлювати свої дані в окремому циклі , або навіть окремий потік!
Так, я це сказав. ви можете зробити багатопотоковий JavaScript у браузері!
Мені відомі два методи, які працюють надзвичайно добре без виїмки, використовуючи набагато менше соку і створюючи менше тепла. Точний хронометр та ефективність роботи машини - це чистий результат.
Вибачте, якщо це трохи слово, але тут іде ...
Спосіб 1: Оновлення даних через setInterval, а графіку через RAF.
Використовуйте окремий набір Інтервалу для оновлення значень перекладу та обертання, фізики, зіткнень тощо. Зберігайте ці значення в об'єкті для кожного анімованого елемента. Призначте рядок перетворення змінній в об'єкті кожного setInterval 'frame'. Зберігайте ці об’єкти в масиві. Встановіть свій інтервал на бажаний кадр в секунду в мс: ms = (1000 / fps). Це зберігає стійкий годинник, який дозволяє однакові fps на будь-якому пристрої, незалежно від швидкості RAF. Не призначайте сюди перетворення елементам!
У циклі requestAnimationFrame, повторіть свій масив зі старою школою для циклу-- не використовуйте тут новіші форми, вони повільні!
for(var i=0; i<sprite.length-1; i++){ rafUpdate(sprite[i]); }
У функції rafUpdate отримайте рядок перетворення з вашого js-об’єкта в масиві та ідентифікатор його елементів. Ви вже повинні мати свої «спрайти» елементи, приєднані до змінної або легко доступні за допомогою інших засобів, щоб ви не втрачали час, отримуючи їх у RAF. Тримаючи їх в об’єкті, названому на честь їх HTML-коду, працює досить добре. Встановіть цю частину, перш ніж вона навіть перейде у ваш SI або RAF.
Використовуйте RAF оновити перетворення тільки використовувати тільки 3D перетворення (навіть для 2d), а також безліч CSS «волі , зміна: перетворення;» на елементи, які будуть змінюватися. Це дозволяє максимально синхронізувати ваші перетворення з нативним коефіцієнтом оновлення, натискає на GPU і повідомляє браузеру, де найбільше зосередитись.
Тож у вас повинен бути щось подібне до цього псевдокоду ...
// refs to elements to be transformed, kept in an array
var element = [
mario: document.getElementById('mario'),
luigi: document.getElementById('luigi')
//...etc.
]
var sprite = [ // read/write this with SI. read-only from RAF
mario: { id: mario ....physics data, id, and updated transform string (from SI) here },
luigi: { id: luigi .....same }
//...and so forth
] // also kept in an array (for efficient iteration)
//update one sprite js object
//data manipulation, CPU tasks for each sprite object
//(physics, collisions, and transform-string updates here.)
//pass the object (by reference).
var SIupdate = function(object){
// get pos/rot and update with movement
object.pos.x += object.mov.pos.x; // example, motion along x axis
// and so on for y and z movement
// and xyz rotational motion, scripted scaling etc
// build transform string ie
object.transform =
'translate3d('+
object.pos.x+','+
object.pos.y+','+
object.pos.z+
') '+
// assign rotations, order depends on purpose and set-up.
'rotationZ('+object.rot.z+') '+
'rotationY('+object.rot.y+') '+
'rotationX('+object.rot.x+') '+
'scale3d('.... if desired
; //...etc. include
}
var fps = 30; //desired controlled frame-rate
// CPU TASKS - SI psuedo-frame data manipulation
setInterval(function(){
// update each objects data
for(var i=0; i<sprite.length-1; i++){ SIupdate(sprite[i]); }
},1000/fps); // note ms = 1000/fps
// GPU TASKS - RAF callback, real frame graphics updates only
var rAf = function(){
// update each objects graphics
for(var i=0; i<sprite.length-1; i++){ rAF.update(sprite[i]) }
window.requestAnimationFrame(rAF); // loop
}
// assign new transform to sprite's element, only if it's transform has changed.
rAF.update = function(object){
if(object.old_transform !== object.transform){
element[object.id].style.transform = transform;
object.old_transform = object.transform;
}
}
window.requestAnimationFrame(rAF); // begin RAF
Це зберігає ваші оновлення об’єктів даних та рядки перетворення, синхронізовані до потрібної частоти кадрів у SI, та фактичні призначення трансформації у системі RAF, синхронізованій зі швидкістю оновлення GPU. Таким чином, фактичні оновлення графіки є лише у RAF, але зміни в даних та побудова рядка перетворення є в СІ, тому жодні дженкі, а «час» протікає з потрібною швидкістю кадрів.
Потік:
[setup js sprite objects and html element object references]
[setup RAF and SI single-object update functions]
[start SI at percieved/ideal frame-rate]
[iterate through js objects, update data transform string for each]
[loop back to SI]
[start RAF loop]
[iterate through js objects, read object's transform string and assign it to it's html element]
[loop back to RAF]
Спосіб 2. Помістіть СІ у веб-працівника. Цей - ШВИДКО і гладко!
Те саме, що і метод 1, але покласти СІ у веб-працівника. Він буде запущений на абсолютно окремому потоці, залишаючи сторінку для роботи лише з RAF та інтерфейсом користувача. Передайте масив спрайт вперед і назад як "об'єкт, що передається". Це швидко буко. Клонування або серіалізація не потребує часу, але це не так, як пройти посилання, оскільки посилання з іншого боку знищено, тому вам потрібно буде перейти на іншу сторону і оновити їх лише при наявності, сортувати про те, як передавати записку туди-сюди зі своєю дівчиною у середній школі
Одночасно можна читати і писати лише один. Це добре, якщо вони перевіряють, чи не визначено це, щоб уникнути помилки. RAF - Швидкий і негайно поверне його назад, а потім пройде через купу кадрів GPU, просто перевіривши, чи він ще відправлений назад. SI у веб-робітника буде мати масив спрайтів, і він оновлюватиме дані про позиції, рух та фізику, а також створює нову рядок перетворення, а потім передасть її назад до RAF на сторінці.
Це найшвидший спосіб, яким я знаю, анімувати елементи за допомогою сценарію. Дві функції будуть виконуватись як дві окремі програми, на двох окремих потоках, використовуючи переваги багатоядерних процесорів таким чином, що один сценарій js не робить. Багатопотокова анімація javascript.
І це буде робити безперешкодно, але за фактичної заданої частоти кадрів, з дуже невеликою розбіжністю.
Результат:
Будь-який із цих двох методів забезпечить ваш сценарій працювати з однаковою швидкістю на будь-якому ПК, телефоні, планшеті тощо (звичайно, у межах можливостей пристрою та браузера).
requestAnimationFrame
це, як випливає з назви, - запитувати кадр анімації лише тоді, коли це потрібно. Скажімо, ви показуєте статичне чорне полотно, ви повинні отримати 0 кадрів в секунду, тому що не потрібен новий кадр. Але якщо ви показуєте анімацію, яка вимагає 60 кадрів в секунду, вам також слід її отримати.rAF
просто дозволяє "пропустити" непотрібні кадри, а потім зберегти процесор.