2016-07-29 14 views
1

Ich versuche, horizontale Balkendiagrammzeichnung zu animieren. Es wird langsam gezeichnet und wenn es fertig ist, wird die zweite gezeichnet. Genau wie chart.js. Es muss nicht so fortgeschritten sein. Ich versuche gerade Leinwandzeichnen + Animation zu lernen. Ich benutze ctx.fillRect und ich bin mir nicht sicher, ob das animiert werden kann.Animiere Rechteck auf Leinwand

Update: In meinem zweiten Snippet habe ich ein Timeout um fillRect hinzugefügt. Es animiert die Bar aber jetzt position.Y scheint nicht zur richtigen Zeit aktualisiert zu werden. Die Balken sind übereinander gezeichnet.

/** 
 
* Javascript Carousel 
 
* Author: Yasin Yaqoobi 
 
* Project Goal: Build a really simple slider using javascript timer and css transition. 
 
* Date: 07/09/16 
 
**/ 
 

 
var Charts = (function(){ 
 

 
var ctx; 
 
var canvas; 
 
var legendsHeight = 50; 
 
var yLabelsWidth = 100; 
 
var scaleRatio; 
 

 
function init(canvas, chart){ 
 
\t setupCanvas(canvas); 
 
\t setScaleRatio(chart); 
 
\t if (chart.type.localeCompare('HorizontalBar') != -1){ 
 
\t \t drawHorizontalChart(chart); 
 
\t } 
 
} 
 

 
function drawHorizontalChart(chart){ 
 
\t var canvasHeight = $(canvas).outerHeight(); 
 
\t var canvaswidth = $(canvas).outerWidth(); 
 
\t var marginRatio = (canvasHeight - 2 * legendsHeight)/chart.data.labels.length * 0.2; 
 
\t var barHeight = ((canvasHeight - 2 * legendsHeight)/chart.data.labels.length) - marginRatio; 
 
\t \t 
 
\t ctx.beginPath(); 
 
\t ctx.moveTo(yLabelsWidth, legendsHeight); // (30, 15) 
 
\t ctx.lineTo(yLabelsWidth, canvasHeight - legendsHeight); // (30,385) 
 
\t ctx.lineTo(canvaswidth, canvasHeight - legendsHeight); // (1000,385) 
 
\t ctx.stroke(); 
 

 
\t ctx.font = "16px serif"; 
 
\t ctx.fillText(chart.data.datasets[0].label, (canvaswidth - yLabelsWidth)/2, legendsHeight/2); 
 
\t var position = {x:yLabelsWidth,y:legendsHeight}; 
 

 
\t for (var i = chart.data.labels.length-1; i >= 0; i--){ 
 
\t \t ctx.fillStyle = chart.data.datasets[0].backgroundColor[i]; 
 
\t \t ctx.fillRect(position.x,position.y, scaleRatio * chart.data.datasets[0].data[i], barHeight); 
 
\t \t position.y += marginRatio + barHeight; 
 
\t \t console.log('this is i ' + i); 
 
\t } 
 
} 
 

 
function setScaleRatio(chart){ 
 
\t scaleRatio = chart.data.datasets[0].data.reduce(function(prev,curr){ 
 
\t \t if (prev > curr){ 
 
\t \t \t return prev; 
 
\t \t } 
 
\t \t return curr; 
 
\t }); 
 

 
\t scaleRatio = $(canvas).outerWidth()/(scaleRatio + 10); 
 
} 
 

 
function setupCanvas(canv){ 
 
\t canvas = canv; 
 
\t if (canvas.getContext){ 
 
\t \t ctx = canvas.getContext('2d'); 
 
\t } 
 
\t console.log(ctx); 
 
} 
 

 
var publicApi = { 
 
\t init: init 
 
}; 
 

 
return publicApi; 
 

 
})(); 
 

 

 
$(document).ready(function(){ 
 
\t var canvas = document.getElementById("myChart"); 
 
\t Charts.init(canvas, { 
 
\t \t type: 'HorizontalBar', 
 
\t \t data: { 
 
\t \t \t labels: ['USA', 'Russia', 'China'], 
 
\t \t \t datasets: [ 
 
\t \t \t \t { 
 
\t \t \t \t \t label: 'Progress Chart', 
 
\t \t \t \t \t backgroundColor: [ 
 
\t \t \t \t \t \t 'rgba(255, 99, 132, 0.2)', 
 
\t \t     'rgba(54, 162, 235, 0.2)', 
 
\t \t     'rgba(255, 206, 86, 0.2)' 
 
\t     ], 
 
\t     borderColor: [ 
 
\t \t     'rgba(255,99,132,1)', 
 
\t \t     'rgba(54, 162, 235, 1)', 
 
\t \t     'rgba(255, 206, 86, 1)' 
 
\t     ], 
 
\t     borderWidth: 1, 
 
\t     data: [60, 30, 80] 
 
\t    } 
 
\t \t \t ] 
 
\t \t } 
 

 
\t }); 
 
});
.container{ 
 
\t width: 1200px; 
 
\t box-shadow: 5px 5px 35px 0px rgba(0,0,0,0.4); 
 
\t -webkit-box-shadow: 5px 5px 35px 0px rgba(0,0,0,0.4); 
 
\t -moz-box-shadow: 5px 5px 35px 0px rgba(0,0,0,0.4); 
 
\t overflow: hidden; 
 
\t margin: 0 auto; 
 
\t padding: 5%; 
 
} 
 

 
canvas{ 
 
\t margin: 0 auto; 
 
\t display: block; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<!DOCTYPE html> 
 
<head> 
 
<link rel="stylesheet" href="style.css"> 
 
</head> 
 
<body> 
 

 
<div class="container"> 
 
\t <h1 class="page-title underline-text">Charts</h1> 
 
\t \t <div class="charts-area"> 
 
\t \t <h3>Progress Chart</h3> 
 
\t \t <canvas id="myChart" width="1000" height="400"></canvas> 
 
\t </div> 
 
<script src="jquery-3.1.0.js"></script> 
 
<script src="npo.js"></script> 
 
<script src="index.js"></script> 
 

 
</body>

/** 
 
* Javascript Carousel 
 
* Author: Yasin Yaqoobi 
 
* Project Goal: Build a really simple slider using javascript timer and css transition. 
 
* Date: 07/09/16 
 
**/ 
 

 
var Charts = (function(){ 
 

 
var ctx; 
 
var canvas; 
 
var legendsHeight = 50; 
 
var yLabelsWidth = 100; 
 
var scaleRatio; 
 

 
function init(canvas, chart){ 
 
\t setupCanvas(canvas); 
 
\t setScaleRatio(chart); 
 
\t if (chart.type.localeCompare('HorizontalBar') != -1){ 
 
\t \t drawHorizontalChart(chart); 
 
\t } 
 
} 
 

 
function drawHorizontalChart(chart){ 
 
\t var canvasHeight = $(canvas).outerHeight(); 
 
\t var canvaswidth = $(canvas).outerWidth(); 
 
\t var marginRatio = (canvasHeight - 2 * legendsHeight)/chart.data.labels.length * 0.2; 
 
\t var barHeight = ((canvasHeight - 2 * legendsHeight)/chart.data.labels.length) - marginRatio; 
 
\t \t 
 
\t ctx.beginPath(); 
 
\t ctx.moveTo(yLabelsWidth, legendsHeight); // (30, 15) 
 
\t ctx.lineTo(yLabelsWidth, canvasHeight - legendsHeight); // (30,385) 
 
\t ctx.lineTo(canvaswidth, canvasHeight - legendsHeight); // (1000,385) 
 
\t ctx.stroke(); 
 

 
\t ctx.font = "16px serif"; 
 
\t ctx.fillText(chart.data.datasets[0].label, (canvaswidth - yLabelsWidth)/2, legendsHeight/2); 
 
\t var position = {x:yLabelsWidth,y:legendsHeight}; 
 

 
\t for (var i = chart.data.labels.length-1; i >= 0; i--){ 
 
\t \t ctx.fillStyle = chart.data.datasets[0].backgroundColor[i]; 
 
\t \t for (var n = 20; n < scaleRatio * chart.data.datasets[0].data[i]; n+=1){ 
 
\t \t (function (ratio){ 
 
\t \t \t setTimeout(function(){ 
 
\t \t \t \t console.log(ratio); 
 
\t \t \t \t ctx.fillRect(position.x,position.y, ratio, barHeight); 
 
\t \t \t }, 1000); 
 
\t \t })(n); 
 
\t } 
 
\t \t position.y += marginRatio + barHeight; 
 
\t \t console.log('this is positionY ' + position.y); 
 
\t } 
 
} 
 

 
function setScaleRatio(chart){ 
 
\t scaleRatio = chart.data.datasets[0].data.reduce(function(prev,curr){ 
 
\t \t if (prev > curr){ 
 
\t \t \t return prev; 
 
\t \t } 
 
\t \t return curr; 
 
\t }); 
 

 
\t scaleRatio = $(canvas).outerWidth()/(scaleRatio + 10); 
 
} 
 

 
function setupCanvas(canv){ 
 
\t canvas = canv; 
 
\t if (canvas.getContext){ 
 
\t \t ctx = canvas.getContext('2d'); 
 
\t } 
 
\t console.log(ctx); 
 
} 
 

 
var publicApi = { 
 
\t init: init 
 
}; 
 

 
return publicApi; 
 

 
})(); 
 

 

 
$(document).ready(function(){ 
 
\t var canvas = document.getElementById("myChart"); 
 
\t Charts.init(canvas, { 
 
\t \t type: 'HorizontalBar', 
 
\t \t data: { 
 
\t \t \t labels: ['USA', 'Russia', 'China'], 
 
\t \t \t datasets: [ 
 
\t \t \t \t { 
 
\t \t \t \t \t label: 'Progress Chart', 
 
\t \t \t \t \t backgroundColor: [ 
 
\t \t \t \t \t \t 'rgba(255, 99, 132, 0.2)', 
 
\t \t     'rgba(54, 162, 235, 0.2)', 
 
\t \t     'rgba(255, 206, 86, 0.2)' 
 
\t     ], 
 
\t     borderColor: [ 
 
\t \t     'rgba(255,99,132,1)', 
 
\t \t     'rgba(54, 162, 235, 1)', 
 
\t \t     'rgba(255, 206, 86, 1)' 
 
\t     ], 
 
\t     borderWidth: 1, 
 
\t     data: [60, 30, 80] 
 
\t    } 
 
\t \t \t ] 
 
\t \t } 
 

 
\t }); 
 
});
.container{ 
 
\t width: 1200px; 
 
\t box-shadow: 5px 5px 35px 0px rgba(0,0,0,0.4); 
 
\t -webkit-box-shadow: 5px 5px 35px 0px rgba(0,0,0,0.4); 
 
\t -moz-box-shadow: 5px 5px 35px 0px rgba(0,0,0,0.4); 
 
\t overflow: hidden; 
 
\t margin: 0 auto; 
 
\t padding: 5%; 
 
} 
 

 
canvas{ 
 
\t margin: 0 auto; 
 
\t display: block; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<!DOCTYPE html> 
 
<head> 
 
<link rel="stylesheet" href="style.css"> 
 
</head> 
 
<body> 
 

 
<div class="container"> 
 
\t <h1 class="page-title underline-text">Charts</h1> 
 
\t \t <div class="charts-area"> 
 
\t \t <h3>Progress Chart</h3> 
 
\t \t <canvas id="myChart" width="1000" height="400"></canvas> 
 
\t </div> 
 
<script src="jquery-3.1.0.js"></script> 
 
<script src="npo.js"></script> 
 
<script src="index.js"></script> 
 

 
</body>

Antwort

2

Hier ist eine kleine Probe setTimeout unter Verwendung einer horizontalen Leiste eine nach der anderen zu ziehen. Ich habe ein Sample Timing Setup für Sie, das darauf wartet, dass der vorherige Balken alle 10 Millisekunden beendet und neu gezeichnet wird. Führen Sie es aus, um zu sehen.

<!DOCTYPE html> 
 
<html> 
 

 
<body> 
 

 
<canvas id="canvas" height="300" width="600"></canvas> 
 

 
<script> 
 

 
var canvas = document.getElementById('canvas'), 
 
    ctx = canvas.getContext('2d'); 
 

 
var bars = [ 
 
    { name: 'bar1', value: 567 }, 
 
    { name: 'bar2', value: 394 } 
 
]; 
 

 
var delay = 0, 
 
    speed = 10; 
 

 
for(var i = 0; i < bars.length; ++i){ 
 
    for(var l = 0; l < bars[i].value; ++l) setTimeout(ctx.fillRect.bind(ctx,0,50 + 100 * i, l, 75),(i > 0 ? delay+(bars[i-1].value*speed) : 0) + delay+l*speed); 
 
} 
 

 
</script> 
 

 
</body> 
 

 
</html>

EDIT: Reiniger, Summen Verzögerung für mehrere Bars

<!DOCTYPE html> 
 
<html> 
 

 
<body> 
 

 
<canvas id="canvas" height="300" width="675"></canvas> 
 

 
<script> 
 

 
var canvas = document.getElementById('canvas'), 
 
    ctx = canvas.getContext('2d'); 
 

 
var bars = [ 
 
    { name: 'bar1', value: 567 }, 
 
    { name: 'bar2', value: 394 }, 
 
    { name: 'bar3', value: 217 } 
 
]; 
 

 
var delay = 0, // accrued delay 
 
    speed = 3; // drawing speed (milliseconds per render) 
 

 
for(var i = 0; i < bars.length; ++i){ 
 
    for(var l = 0; l < bars[i].value; ++l){ 
 
     setTimeout(
 
      ctx.fillRect.bind(ctx,0,50 + 100 * i, l, 75), 
 
      (i == 0 ? 0 : delay) + l*speed 
 
     ); 
 
    } 
 
    delay += bars[i].value * speed; 
 
} 
 

 
</script> 
 

 
</body> 
 

 
</html>

+0

das sieht gut danke. Kannst du bitte das setTimeout vereinfachen. Ich habe es schwer, es zu verstehen. Gibt es auch einen Grund, warum Sie den CTX binden, anstatt nur den CTX direkt zu benutzen? Habe keine Ahnung, was nach dem Comm in set timeout passiert '(i> 0? Delay + (Balken [i-1] .value * Geschwindigkeit): 0) + Verzögerung + l * Geschwindigkeit);' –

+0

Ich verwende bind, damit der der Wert von "i" und "l" in den "for" -Schleifen wird beibehalten; Wenn Sie dies nicht tun, nehmen sie den Wert des aktuellen "i" und "l" zu dem Zeitpunkt an, zu dem die Funktion aufgerufen wird. Es hat mit dem Umfang von 'var's zu tun (in ES6 über' let' Statements fixiert, glaube ich). Das zweite Argument im Timeout ist das "Timing" selbst - ich erkläre es besser im folgenden Kommentar (ohne Zeichen) –

+0

Das Timing funktioniert wie folgt: 'i> 0?' Ist eine ternäre Aussage, die fragt, ob wir ' Re auf der zweiten, dritten, vierten ... Bar (im Grunde, wenn wir nicht auf der ersten Bar sind). Wenn wir NICHT auf dem ersten Balken sind, verzögern wir + tables [i -1] .value * speed' für unser Timing, dh wir zeichnen "nach einer Verzögerung PLUS die Gesamtlänge des vorherigen Balkens ZEIT die Geschwindigkeit, die zum Zeichnen benötigt wird "-> Dies fügt effektiv den vorherigen Balken als Gesamtverzögerung für den nächsten hinzu, obwohl dies nur mit 2 Balken funktioniert, da wir alle vorherigen Balken zusammensetzen müssten, wenn es mehr als zwei wären. Der letzte Teil ist nur aktuelle Balken gezeichnet –