2016-07-29 123 views
1

我正在嘗試動畫水平條形圖繪製。它會慢慢畫出來,一旦畫完第二張。就像chart.js一樣。它不一定要那麼先進。我只是想學習畫布繪畫+動畫。我正在使用ctx.fillRect,我不確定這是否可以動畫。畫布上的動畫矩形

更新:在我的第二個片段我已經加入周圍fillRect超時。它激活了酒吧,但現在position.Y似乎並沒有在適當的時間更新。酒吧被繪製在彼此的頂部。

/** 
 
* 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>

回答

2

下面是使用setTimeout繪製一個單槓一個接一個小的樣品。我爲您準備了一個示例計時設置,等待上一個工具欄完成並每10毫秒重新繪製一次。運行它看。

<!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>

編輯:清潔,款項延遲多條

<!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

這個不錯謝謝。你能簡化setTimeout嗎?我很難理解它。還有一個原因是你綁定了ctx而不是直接使用ctx?不知道在超時設置後,會發生什麼?(i> 0?delay +(bars [i-1] .value * speed):0)+ delay + l * speed);' –

+0

我正在使用bind, 'for'循環中'i'和'l'的值被保留;如果你不這樣做,他們會在調用函數的時候假定當前的'i'和'l'的值。它與'var'的範圍有關(通過'let'語句固定在ES6中,我相信)。 在超時的第二個參數是「時機」本身 - 我將解釋在下面評論更好(跑出來的字符) –

+0

定時的工作原理如下:'I> 0'是一個三元聲明問我們」?在第二,第三,第四...欄(基本上,如果我們不在第一欄上)。如果我們不在第一個欄上,我們會根據我們的時間延遲+ bars [i-1] .value * speed',這意味着我們在延遲之後繪製上一個欄的總長度TIMES繪製的速度「 - >這有效地將前一個小節添加爲下一個小節的總延遲,但這隻適用於2個小節,因爲如果有兩個以上的小節,我們必須複合所有以前的小節。最後一部分是當前正在繪製的酒吧 –