2016-11-01 2 views
0

키보드를 누를 때마다 새로운 사운드/애니메이션이 생성되는 웹 페이지를 만듭니다. 지금은 첫 번째 키에만 있습니다.하지만 첫 번째 키를 누른 후에 애니메이션이 멈추는 문제가 있습니다. 애니메이션을 다시 시작하거나 어떤 키를 눌렀는지에 따라 새 애니메이션을 시작하는 대신 직사각형 (이 경우)이 깜박이기 시작합니다. 아래는 내 코드 중 일부입니다.OOP 메서드를 사용하여 캔버스 애니메이션 다시 시작

class Drawable{ 
constructor(context, x = 0, y = 0, fillStyle = "#000", strokeStyle = "transparent", lineWidth = 0){ 
this.context = context; 
if(!(this.context instanceof CanvasRenderingContext2D)){ 
    throw new Error("You must provide a valid canvas context to Drawables."); 
} 
this.x = x; 
this.y = y; 
this.fillStyle = fillStyle; 
this.strokeStyle = strokeStyle; 
this.lineWidth = lineWidth; 
this.deltas = new Map(); 

this.limits = { 
    max: new Map(), 
    min: new Map() 
}; 
} 
draw(){ 
    this.context.save(); 
    this.context.translate(this.x, this.y); 
    this.context.scale(2,1.5); 
    this.context.fillStyle = this.fillStyle; 
    this.context.strokeStyle = this.strokeStyle; 
    this.context.lineWidth = this.lineWidth; 
} 
afterDraw(){ 
    this.context.restore(); 
} 
applyAnimation(secondsElapsed){ 
    for(const[propertyName, valueChangePerSecond] of this.deltas){ 
     const changedAmount = secondsElapsed * valueChangePerSecond; 
     this[propertyName] += changedAmount; 
     if(this.limits.max.has(propertyName)){ 
      this[propertyName] =  Math.min(this[propertyName],this.limits.max.get(propertyName)); 
     } else if(this.limits.min.has(propertyName)){ 
      this[propertyName] = Math.max(this[propertyName],this.limits.min.get(propertyName)); 
     } 
    } 
    } 
} 
    class Rectangle extends Drawable{ 
constructor(context, x = 0, y = 0, fillStyle = "#000", strokeStyle = "transparent", lineWidth = 0, deltas = new Map(), width = 100, height = 100){ 
super(context, x, y, fillStyle, strokeStyle, lineWidth, deltas); 
this.width = width; 
this.height = height; 
} 

draw(){ 
super.draw(); 
this.context.fillRect(this.width/-2, this.height/-2, this.width, this.height); 
this.context.strokeRect(this.width/-2, this.height/-2, this.width, this.height); 
super.afterDraw(); 
} 
loopDraw(){ 
    super.draw(); 
    let rectSize = 30; 
    for(let i = 0; i < 3; i++){ 
     let yPos = (rectSize - 10)*i; 
     for(let j = 0; j < 6; j++){ 
       this.context.fillRect((rectSize+10)*j,yPos,this.width/-2,this.height/-2); 
      this.context.strokeRect(this.width/-2, this.height/-2, this.width, this.height); 
     } 
    } 
    super.afterDraw(); 
} 
} 
const canvas = document.getElementById("soundBoardCanvas"); 
const context = canvas.getContext("2d"); 
    const animationAObjects = new Set(); 
// Creating the rectangle and setting the animation properties of the rectangle 
let animationARect = new Rectangle(context,canvas.width/1.5,canvas.height/2, randomColour(), "transparent", 0, new Map() ,50,50); 

animationARect.deltas.set("y",100); 
animationARect.deltas.set("height",50); 
animationARect.deltas.set("width",50); 
animationARect.deltas.set("x",100); 
animationARect.limits.max.set("y", canvas.height/2); 
animationARect.limits.max.set("x", canvas.width/2.5); 
animationARect.limits.max.set("height",randomBetween(100,170)); 
animationARect.limits.max.set("width",randomBetween(100,170)); 

animationAObjects.add(animationARect); 


function randomBetween(min,max){ 
let range = max - min; 

let random = Math.random(); 
random = random * (range + 1); 
random = random + min; 

return random; 
} 

// Animates all of the objects in the selected set 
function animationA(){ 
    requestAnimationFrame(animationA); 
    context.clearRect(0,0,canvas.width,canvas.height); 

    const diffSeconds = (Date.now() - lastTime)/1000; 
    lastTime = Date.now(); 

    if(diffSeconds > 0){ 
     for(const animationAObject of animationAObjects){ 
      animationAObject.applyAnimation(diffSeconds); 
      animationAObject.draw(); 
     } 
    } 
} 
document.addEventListener("keydown", (e) => { 
e.preventDefault(); 
cancelAnimationFrame(requestId); 
if(e.keyCode == 65){ 
    window.requestAnimationFrame(animationA); 
} 
}); 
+1

코드가 누락되었습니다. 당신이 가진 것에서 당신이 묘사하는 문제에 대한 이유가 없습니다. BTW requestAnimationFrame은 콜백에 대한 첫 번째 인수로 1/1000,000 초 (1/1000 초)의 가장 작은 값 0.001ms를 고해상도 시간으로 전달합니다. 'function animationA (time) {' – Blindman67

+0

@ Blindman67 이제 위의 편집에 모든 코드를 추가했습니다. 잘하면 그게 더 잘 설명해야합니다. requestAnimationFrame에 대해 작성한 주석에 대해 자세히 설명해 주시겠습니까? – seanrs97

+0

브라우저가'requestAnimationFrame'에 전달하는 "콜백"함수를 호출 할 때 콜백에 전달 된 첫 번째 인수는 시간입니다. 예 :'함수 콜백 (time) {// 시간 인수는 RAF에 의해 전달''requestAnimationFrame (callback); // RAF 콜백 함수를 설정합니다. ' – Blindman67

답변

1

당신은 결코 생성하지 않았을 때 그 (적어도 엄격 모드에서) 오류가 발생한다, 그래서 requestId (또는 어디서든 선언). 그리고 나서 을 누를 때마다 새로운 애니메이션을 만들면 서로를 방해하고 깜박 거리게됩니다. (왜 그런지 정확히 알 수는 없지만).

let requestId = 0; // declare this! 
let lastTime = Date.now(); // important initialisation 

function animationA(){ 
    requestId = requestAnimationFrame(animationA); 
// ^^^^^^^^ 
    … 
} 
document.addEventListener("keydown", (e) => { 
    e.preventDefault(); 
    cancelAnimationFrame(requestId); 
    if (e.keyCode == 65) { 
     requestId = window.requestAnimationFrame(animationA); 
//  ^^^^^^^^^ 
    } 
}); 
+0

방금이 코드를 변경 했으므로 아무런 차이가 없습니다. 키 누름을 반복하면 모양이 다시 그려지지 않으며 애니메이션이 반복되지 않습니다. 그 대신에 그 모양들은 단지 거기에 고정되어 있습니다. – seanrs97

+0

@ seanrs97 오류가 있습니까? 애니메이션을 디버깅 했습니까? 'animationA'는 정기적으로 호출됩니까? 'applyAnimation'은 당신이 원하는대로 할 수 있습니까? 'loopDraw'는 아무데도 호출되지 않는 이유는 무엇입니까? 일부 로그를 추가하여 캔바스에서 일어나는 일뿐만 아니라 개체에 어떤 변화가 있는지 확인하십시오. – Bergi

+0

나는 오류가 있는지 전혀 확인하지 않았다. LoopDraw는 아직 필요하지 않은 별도의 그리기 방법입니다. 코드에 영향을 미치지 않습니다. 애니메이션 적용은 내가 아는대로하고 있습니다. 이 콘솔이 도움이되는지 몇 가지 console.logs에 기록 할 것입니다. – seanrs97

관련 문제