2017-11-04 2 views
6

x 및 y 좌표를 저장하는 Firebase 데이터베이스에서 정보를 읽음으로써 캔버스에 원이 그려지는 응용 프로그램을 만들려고합니다. 동그라미. 그러나 아래 코드를 실행하면 drawCricles 함수가 비동기 적으로 실행되므로 서클이 그려지기 전에 background(40) 명령이 모두 지워지기 때문에 서클의 부호없이 아무 것도 생성하지 않습니다.Firebase Javascript + P5.js : 비동기 함수가 캔버스를 다시 그리는 중입니다

function setup() { 
    createCanvas(windowWidth, windowHeight); 
    background(40); 
    stroke(80); 
    smooth(); 
    frameRate(60); 
} 

function drawCircles() { 
    firebase.database().ref("circles").once("value", function(snapshot) { 
     var snapshotVal = snapshot.val(); 
     var circleCount = snapshotVal.numCircles; 

     for (var j = 0; j < circleCount; j++) { 
      firebase.database().ref("circles" + j).once("value", function(snapshot) { 
       var snapshotValue = snapshot.val(); 
       fill(143, 2, 2); 
       ellipse(snapshotValue.xPos, 50, 50); 
      }); 
     } 
    }); 
} 

function draw() { 
    stroke(80); 
    background(40); 

    stroke(0); 
    drawCircles(); 
} 
+0

[작은 조각으로 문제를 해결] (http://happycoding.io/tutorials/how-to/program)하고 한 번에 하나씩 만 작업하십시오. 예를 들어 Firebase에서 데이터를 검색하는 간단한 프로그램을 작성할 수 있습니까? 계속 진행하기 전에 완벽하게 작동하도록하십시오. 이와 별도로 하드 코딩 된 포인트를 표시하는 프로그램을 만들 수 있습니까? 하나의 프로그램으로 결합하기 전에 완벽하게 작동하도록하십시오. 특정 단계에서 벗어나면 그 단계의 [mcve]를 게시하십시오. 행운을 빕니다. –

+1

@KevinWorkman drawCircles()가 비동기 적으로 실행되기 때문에 background (40)가 화면에 그려진 모든 원을 지우고 있다는 사실로 문제를 좁혔습니다. – Vaporeon

답변

0

그것은 당신의 문제가 발-경쟁 조건을 일으키는 초당 단지 60 프레임, 보인다. Firebase .once은 페칭을 완료하면 비동기를 실행하고, P5는 프레임 속도 타이밍을 고수하기 때문에 가져 오기를 기다리지 않습니다.

이 특별한 경우에는 필자가 원하는 결과에 매우 가까워 지도록 여러 가지 권장 사항이 있습니다.

1 - 재구성 코드 코드의 현재 구조를 가진 두 가지 문제가있다

.

  • 사례 1 : 현재 코드는 서클이 데이터베이스에 실시간으로 업데이트됩니다 생각하는 나를 이끌 것입니다, 당신은 최신 상태로 유지해야하는, 그래서 당신은 그들의 최신 위치를 가져 오는 유지한다. 이 경우 .once("value") 대신 .on("value")을 사용해야하며 왕복 요청 시간을 절약하기 위해 초당 60 회 요청하는 대신 firebase이 서클이 변경 될 때마다 업데이트를 보내도록해야합니다. 이 경우 : 솔루션 1 아래를 참조하십시오.

  • 사례 2 : 서클이 데이터베이스에서 실시간으로 업데이트되지 않고 전체 서클 목록 만 원할 경우 아무 이유없이 초를 60 회 가져옵니다. 설정시 .once을 사용하여 목록을 가져와 나중에 draw()에 해당 목록을 반복해야합니다. 아래 해결책 2을 참조하십시오.

2 - 재구성 데이터베이스 어느 경우

은 현재 데이터베이스 모델은 루프에서 가져 오는 유지하도록 요구합니다. 즉, circleCount과 같은 요청을 많이 내고 있음을 의미합니다. 이는 각 요청이 추가 소요 시간을 필요로하기 때문에 사용자의 사용에 좋지 않으며, 우리는 소요 시간을 줄이기 위해 노력하고 있으므로 실시간에 가깝습니다. (또는 프레임 속도와 일치) 당신이 그들을 검색 할 .ref("circles" + j)를 사용하고 있기 때문에

이 현재 서클이 보이는, 루트에 등 circles1 circles2 모두로 저장됩니다. 서클을 다음과 같이 저장하도록하십시오 : .ref("circles/" + j) 이것은 circle이 이제 circles으로 저장된다는 것을 의미합니다. like circles/circle1 circles/circle2

이제 이점은 firebase에 대한 모든 요청을 추가로 요청할 필요가 없다는 것입니다. Firebase는 forEach과 같이 믿을 수 없을만큼 편리한 것들을 가지고 있습니다. 하나의 요청으로 모든 아이들을 반복합니다.

3 - 당신의 중포 기지 콜백에 걸린 배경

현재, 당신은 프레임 속도 특정 방식으로 배경을 취소합니다. 이것은 각각의 firebase 호출이 1/60 초 (16 밀리 초)보다 오래 걸리면 배경을 지우고 계속 진행할 것임을 의미합니다. 우리가 데이터베이스를 구성한 후에도이 속도를 달성 할 확률은 매우 낮습니다. 대신 30fps를 사용하는 것이 좋습니다. 그러면 30 초 통화로 firebase에 걸릴 전화 수가 줄어 듭니다.

해결 방법 1

서클이 데이터베이스에 업데이트하는 경우 (다른 게임 플레이어 또는 다른 사람에 의해, 예를 들어 말, 당신은 당신의 코드는 항상 최신 X 좌표를 표시 할)

var latestCirclePositionsSnapshot; 

function setup() { 
    createCanvas(windowWidth, windowHeight); 
    background(40); 
    stroke(80); 
    smooth(); 
    frameRate(60); 

    firebase.database().ref("circles").on("value", function(snapshot) { 
    // got a new value from database, so let's save this in a global variable. 
    latestCirclePositionsSnapshot = snapshot; 
    // we will keep drawing this update until we get a new one from the database. 
    }); 
} 

function draw() { 
    drawCircles(); 
} 

function clearBackground() { 
    stroke(80); 
    background(40); 
} 

function drawCircles() { 
    clearBackground(); 
    stroke(0); 
    latestCirclePositionsSnapshot.forEach(function(circleSnapshot) { 
    // circleData will be the actual contents of each circle 
    var circleData = circleSnapshot.val(); 
    fill(143, 2, 2); 
    ellipse(circleData.xPos, 50, 50); 
    }); 
} 

기본적으로 이것은 우리가 새로운 것을 얻을 때까지 우리가 firebase에서 얻은 마지막 원 위치를 그려 낼 것입니다. (P5는 초당 60 프레임에서 새로 고침 계속됩니다,하지만 중포 기지 업데이트를 실행하고 중포 기지 등으로부터 가져올 수 중포 기지로 실시간으로 할 수 있도록)

해결 방법 2

당신이 실시간으로 업데이트 할 수없는 경우 데이터베이스에, 그리고 당신이 원하는 모든 번 중포 기지에서 데이터를 가져 오는으로 원을 그리는 것입니다

var circlePositions; 
var gotPositions = false; 

function setup() { 
    createCanvas(windowWidth, windowHeight); 
    background(40); 
    stroke(80); 
    smooth(); 
    frameRate(60); 

    firebase.database().ref("circles").once("value", function(snapshot) { 
    // got the circle values from the database 
    // let's store them and we'll keep drawing them forever. 
    circlePositions = snapshot; 
    gotPositions = true; 
    }); 
} 

function draw() { 
    drawCircles(); 
} 

function clearBackground() { 
    stroke(80); 
    background(40); 
} 

function drawCircles() { 
    clearBackground(); 
    stroke(0); 

    if (gotPositions) { 
    circlePositions.forEach(function(circleSnapshot) { 
     // circleData will be the actual contents of each circle 
     var circleData = circleSnapshot.val(); 
     fill(143, 2, 2); 
     ellipse(circleData.xPos, 50, 50); 
    }); 
    } else { 
    // Display some text here like "LOADING DATA FROM SERVERS..." 
    } 
} 

이 도움을 희망 : 그것은 또 다른를 참조하는 것이 좋다 (일부 데이터를 기반으로 몇 가지 점을 음모 예를 들어 말) 동료 팬 & Firebase.

0

내가 여기에 문서로보고하고 그들이 가져온 데이터를 처리하는 것이 좋습니다 방법의 example입니다 :

여기 내 코드입니다. 귀하의 경우, 별도의 인출 및 도면을 시도, 일부 글로벌 변수를 사용하여 데이터를 캐시 : 당신은 항상 관련 데이터를 표시해야하는 경우

var circles = []; 
 

 
function fetchData() { 
 
    firebase.database().ref("circles").once("value", 
 
    function(snapshot) { 
 
     var snapshotVal = snapshot.val(); 
 
     var circleCount = snapshotVal.numCircles; 
 
     
 
     circles = []; 
 

 
     for (var j = 0; j < circleCount; j++) { 
 
      firebase.database().ref("circles" + j).once("value",     function(snapshot) { 
 
       circles.push(snapshot.val()); 
 
      }); 
 
     } 
 
    }); 
 
} 
 

 
function setup() { 
 
    createCanvas(windowWidth, windowHeight); 
 
    background(40); 
 
    stroke(80); 
 
    smooth(); 
 
    frameRate(60); 
 
    fetchData(); 
 
} 
 

 
function drawCircles() { 
 
    circles.forEach(function (snapshotValue) { 
 
     var snapshotValue = snapshot.val(); 
 
     fill(143, 2, 2); 
 
     ellipse(snapshotValue.xPos, 50, 50); 
 
    }); 
 
} 
 

 
function draw() { 
 
    stroke(80); 
 
    background(40); 
 

 
    stroke(0); 
 
    drawCircles(); 
 
}

, fetchData 기능처럼, setInterval를 사용하여 전화를 시도 :

function setup() { 
 
     createCanvas(windowWidth, windowHeight); 
 
     background(40); 
 
     stroke(80); 
 
     smooth(); 
 
     frameRate(60); 
 
     setInterval(fetchData, 5000); //will call fetchData every 5000 ms 
 
    }

+0

코드를 사용해 보았지만 불행히도 서클은 여전히 ​​표시되지 않습니다. – Vaporeon

0

문제는 drawCircles()이 비동기가 아닙니다. 문제는 이 frameRate()에 있고 background()은 그리기 루프를 실행할 때 각 단편을 단색으로 지 웁니다. draw referencebackground을 참조하십시오. 라인 background(40)draw()에서 제거하면 각 프레임이 지워지지 않고 원하는 원이 그려집니다. 이것은 각 프레임의 모든 Firebase 데이터를 다시 그리는 것보다 간단합니다.

개념을 설명하는 다음과 같은 스케치는 일 때만 호출되며 draw()이 아닌 일 때만 호출되므로 화면 영역은 한 번 채색 된 다음 점진적으로 누적 된 원으로 덮어 씁니다.

function setup() { 
 
    createCanvas(400, 200); 
 
    frameRate(5) 
 
    background(40); 
 
} 
 
function drawCircles() { 
 
    fill(143, 2, 2); 
 
    ellipse(random(width), 50, 50); 
 
} 
 
function draw() { 
 
    // background(40); 
 
    drawCircles(); 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.16/p5.js"></script> 
 
<html> 
 
    <head> 
 
    </head> 
 
    <body> 
 
    </body> 
 
</html>

각 프레임을 몇 가지를 축적 다른 사람을 닦아하려면

는, 당신은 createGraphics 버퍼에 서클을 축적 할 필요가있다. 각 프레임은 원의 버퍼를 캔버스에 다시 그린 다음 위에 마우스 포인터 등의 일시적인 요소를 그립니다.

다음은 예입니다. 각 프레임의 캔버스가 background()으로 지워진 다음 pg 버퍼가 캔버스에 그려지고 마우스에 흰색 원이 그려집니다. 배경이 화면을 지우므로 흰색 원은 프레임에서 프레임으로 뒤 흔적을 남기지 않습니다. 그러나 빨간색 원은 지워지지 않은 그래픽 버퍼로 그려 지므로 그대로 유지됩니다.

var pg; 
 
function setup() { 
 
    createCanvas(400, 200); 
 
    pg = createGraphics(400, 200); 
 
    background(40); 
 
} 
 
function drawCircles() { 
 
    pg.fill(143, 2, 2); 
 
    pg.ellipse(random(pg.width), 50, 50); 
 
} 
 
function draw() { 
 
    background(40); 
 
    drawCircles(); 
 
    image(pg,0,0); 
 
    fill(255); 
 
    ellipse(mouseX,mouseY,50,50); 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.16/p5.js"></script> 
 
<html> 
 
    <head> 
 
    </head> 
 
    <body> 
 
    </body> 
 
</html>

관련 문제