2016-07-29 161 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个小节,因为如果有两个以上的小节,我们必须复合所有以前的小节。最后一部分是当前正在绘制的酒吧 –