이것들은 당신이 깊이 갈 때까지 이론적으로 좋은 아이디어입니다. 문제는 RAF를 비 동기화하지 않고 RAF를 조절할 수 없어 기존의 목적을 크게 상실한다는 것입니다. 당신은 최고 속도로 실행하고 별도의 루프에서 데이터를 업데이트 할 수 있도록 , 또는 별도의 스레드!
그렇습니다. 브라우저에서 멀티 스레드 JavaScript를 수행 할 수 있습니다 !
주스를 사용하지 않고 열을 적게 발생 시키므로 잔해없이 매우 잘 작동하는 두 가지 방법이 있습니다. 정확한 인간 규모의 타이밍과 기계 효율성이 그 결과입니다.
이것이 조금 장황하다면 사과하지만 여기 간다 ...
방법 1 : setInterval을 통해 데이터를 업데이트하고 RAF를 통해 그래픽을 업데이트합니다.
변환 및 회전 값, 물리, 충돌 등을 업데이트하려면 별도의 setInterval을 사용하십시오. 각 애니메이션 요소의 오브젝트에 해당 값을 유지하십시오. 변환 문자열을 각 setInterval 'frame'객체의 변수에 지정하십시오. 이 객체들을 배열로 유지하십시오. ms 단위로 원하는 fps 간격을 설정하십시오 : ms = (1000 / fps). 이는 RAF 속도에 관계없이 모든 장치에서 동일한 fps를 허용하는 안정적인 클럭을 유지합니다. 여기에 요소에 변환을 할당하지 마십시오!
requestAnimationFrame 루프에서 구식 for 루프를 사용하여 배열을 반복합니다. 여기에서 최신 양식을 사용하지 마십시오. 느립니다!
for(var i=0; i<sprite.length-1; i++){ rafUpdate(sprite[i]); }
rafUpdate 함수에서 배열의 js 객체 및 해당 요소 ID에서 변환 문자열을 가져옵니다. '스프라이트'요소를 변수에 첨부했거나 다른 방법을 통해 쉽게 액세스 할 수 있어야하므로 RAF에서 'get'하는 데 시간을 낭비하지 않아도됩니다. html id의 이름을 딴 객체에 보관하면 꽤 좋습니다. SI 또는 RAF에 들어가기 전에 해당 부분을 설정하십시오.
RAF를 사용하여 변환 만 업데이트하고 3D 변환 만 (2d에서도) 사용하고 CSS를 "will-change : transform;"으로 설정하십시오. 변경 될 요소에 대해 이렇게하면 변환이 가능한 한 기본 새로 고침 빈도와 동기화 된 상태를 유지하고 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에만 있지만 데이터에 대한 변경 및 변환 문자열 작성은 SI에 있으므로 '시간'이 아니라 '시간'이 원하는 프레임 속도로 흐릅니다.
흐름:
[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. SI를 웹 작업자에게 두십시오. 이것은 FAAAST이고 매끄 럽습니다!
방법 1과 동일하지만 웹 작업자에 SI를 넣습니다. 그런 다음 완전히 별도의 스레드에서 실행되어 RAF 및 UI 만 처리하도록 페이지를 남겨 둡니다. 스프라이트 배열을 '전송 가능한 객체'로 앞뒤로 전달하십시오. 이것은 부코 빠릅니다. 복제하거나 직렬화하는 데 시간이 걸리지 않지만 다른 쪽의 참조가 파괴된다는 점에서 참조로 전달하는 것은 아닙니다. 따라서 양쪽이 다른쪽으로 전달되고 존재하는 경우에만 업데이트해야합니다. 고등학교에서 여자 친구와 메모를주고받는 것 같은
한 번에 한 사람 만 읽고 쓸 수 있습니다. 오류를 피하기 위해 정의되지 않은 경우 확인하는 한 괜찮습니다. RAF는 빠르며 즉시 되돌려 보내지며 GPU 프레임을 통해 다시 전송되었는지 확인합니다. 웹 워커의 SI는 대부분 스프라이트 배열을 가지며 위치, 이동 및 물리 데이터를 업데이트하고 새 변환 문자열을 만든 다음 페이지의 RAF로 다시 전달합니다.
이것은 스크립트를 통해 요소를 애니메이션하는 가장 빠른 방법입니다. 두 함수는 두 개의 개별 스레드에서 두 개의 개별 프로그램으로 실행되며 단일 js 스크립트가하지 않는 방식으로 멀티 코어 CPU를 활용합니다. 멀티 스레드 자바 스크립트 애니메이션.
그리고 잔잔함없이 매끄럽게 진행되지만 실제로 지정된 프레임 속도로 발산이 거의 없습니다.
결과:
이 두 가지 방법 중 하나를 사용하면 PC, 휴대 전화, 태블릿 등에서 기기와 브라우저의 기능 내에서 스크립트가 동일한 속도로 실행됩니다.
requestAnimationFrame
은 (이름 종류의 제안으로) 필요할 때만 애니메이션 프레임을 요청하는 것입니다. 정적 블랙 캔버스를 표시한다고 가정하면 새 프레임이 필요하지 않으므로 0fps를 가져와야합니다. 그러나 60fps가 필요한 애니메이션을 표시하는 경우에도 해당 정보를 가져와야합니다.rAF
쓸모없는 프레임을 "건너 뛰고"CPU를 절약 할 수 있습니다.