2016-06-18 5 views
0

다른 값 (data-percent 참조)과 동일한 재사용 가능한 코드 블록을 사용하여 여러 개의 canvas-es을 사용해야하지만 "애니메이션"을 사용하면 조금 까다 롭습니다. 그것을 재사용 할 수있는 방법을 모르겠다. 같은 코드를 반복해서 복사하여 붙여 넣는 것은 분명히 잘못된 행동이며, 대개 어느 비용으로도 피할 수 있습니다. .. 방법에 대한 canvas 자바 스크립트 코드재사용 가능한 캔버스 코드?

<canvas class="circle-thingy" width="120" height="120" data-percent="75"></canvas> 
<canvas class="circle-thingy" width="120" height="120" data-percent="23"></canvas> 
<canvas class="circle-thingy" width="120" height="120" data-percent="89"></canvas> 

var allCircles = document.getElementsByClassName('circle-thingy'); 

하지만 지금은 더 까다로운 부분을 제공 :


우선은, 그때 나는 모든 canvas -es를 선택할 수 id를 제거하고 대신 class를 사용하는 것이 분명하다? 아마 아주 쉬운 해결책이있다 그러나 나는 그것을 볼 수 없다! 담배를 끊을 수있는 끔찍한 시간 (항상 그렇듯이), 뇌는 폐쇄 된 것처럼 보입니다.


내가 시도하는 것 : for loop 목록 allCircles으로합니다. 문제는이 방법으로 setIntervalclearTimeout을 사용할 수 없다는 것입니다. 동적 변수 이름? 나중에 어떻게 참조 할 수 있습니까?


여기 하나 원 내 코드입니다, 그것을 시도.

// Get canvas context 
 
var ctx = document.getElementById('my-circle').getContext('2d'); 
 
// Current percent 
 
var currentPercent = 0; 
 
// Canvas north (close enough) 
 
var start = 4.72; 
 
// Dimensions 
 
var cWidth = ctx.canvas.width; 
 
var cHeight = ctx.canvas.height; 
 
// Desired percent -> comes from canvas data-* attribute 
 
var finalPercent = ctx.canvas.getAttribute('data-percent'); 
 
var diff; 
 

 
function circle() { 
 
    diff = ((currentPercent/100) * Math.PI * 2 * 10).toFixed(2); 
 
    ctx.clearRect(0, 0, cWidth, cHeight); 
 
    ctx.lineWidth = 3; 
 
    
 
    // Bottom circle (grey) 
 
    ctx.strokeStyle = '#eee'; 
 
    ctx.beginPath(); 
 
    ctx.arc(60, 60, 55, 0, 2 * Math.PI); 
 
    ctx.stroke(); 
 

 
    // Percent text 
 
    ctx.fillStyle = '#000'; 
 
    ctx.textAlign = 'center'; 
 
    ctx.font="900 10px arial"; 
 
    ctx.fillText(currentPercent + '%', cWidth * 0.5, cHeight * 0.5 + 2, cWidth); 
 

 
    // Upper circle (blue) 
 
    ctx.strokeStyle = '#0095ff'; 
 
    ctx.beginPath(); 
 
    ctx.arc(60, 60, 55, start, diff/10 + start); 
 
    ctx.stroke(); 
 

 
    // If has desired percent -> stop 
 
    if(currentPercent >= finalPercent) { 
 
    clearTimeout(myCircle); 
 
    } 
 
    currentPercent++; 
 
} 
 

 
var myCircle = setInterval(circle, 20);
<canvas id="my-circle" width="120" height="120" data-percent="75"></canvas>

는 자신의 프로젝트에이 코드를 사용하시기 바랍니다.

답변

1

bind을 사용하면 문제를 해결할 수 있습니다.

function animateCircle(canvas) { 
    var scope = { 
     ctx: canvas.getContext('2d') 
     // other properties, like currentPercent, finalPercent, etc 
    };   
    scope.interval = setInterval(circle.bind(scope), 20); 
} 
this 대신 글로벌 것들에서 변수를 참조하기 위해 circle 기능을 변경

:

주어진 canvas에 대한 애니메이션을 시작하는 도우미 함수를 만듭니다

function circle() { 
    // your old code with corresponding changes 
    // e.g. 
    var ctx = this.ctx; // references corresponding scope.ctx 
    // or 
    this.currentPercent++; // references corresponding scope.currentPercent 
} 

작업 JSFiddle을, 어떤 경우 명확하지 않다.

+0

애니메이션에 setInterval을 사용해서는 안되며, 애니메이션의 품질 저하 (전단, 지연, 일관되지 않은 프레임 속도, 예기치 않은 피할 수없는 페이지 충돌 등)가 발생할 수있는 여러 가지 문제가 있습니다. 어떤 종류의 애니메이션이라도 requestAnimationFrame을 사용하십시오. 브라우저가 디스플레이 새로 고침과 동기화되면 브라우저는 애니메이션을 수행하고 있기 때문에 가위없이 캔바스를 표시하고 해당 장치가 프레임 단위로 처리 할 수있는 것 이상의 렌더링을 시도하지 않습니다. 모든 플랫폼에 걸쳐 고품질의 애니메이션을 제공합니다. – Blindman67

관련 문제