在画布上设置动画矩形

时间:2016-07-29 03:31:54

标签: javascript html5 html5-canvas drawing2d

我正在尝试为水平条形图绘制动画。它将慢慢绘制,一旦完成绘制第二个。就像chart.js一样。它不一定是先进的。我只是想学习画布绘画+动画。我正在使用ctx.fillRect,我不确定这是否可以动画。

更新:在我的第二个片段中,我在fillRect周围添加了一个超时。它激活了酒吧,但现在位置.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){
	setupCanvas(canvas); 
	setScaleRatio(chart);
	if (chart.type.localeCompare('HorizontalBar') != -1){
		drawHorizontalChart(chart);
	}
}

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

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

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

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

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

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

var publicApi = {
	init: init
}; 

return publicApi; 

})();


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

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

canvas{
	margin: 0 auto;
	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">
	<h1 class="page-title underline-text">Charts</h1> 
		<div class="charts-area">
		<h3>Progress Chart</h3>
		<canvas id="myChart" width="1000" height="400"></canvas>
	</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){
	setupCanvas(canvas); 
	setScaleRatio(chart);
	if (chart.type.localeCompare('HorizontalBar') != -1){
		drawHorizontalChart(chart);
	}
}

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

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

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

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

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

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

var publicApi = {
	init: init
}; 

return publicApi; 

})();


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

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

canvas{
	margin: 0 auto;
	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">
	<h1 class="page-title underline-text">Charts</h1> 
		<div class="charts-area">
		<h3>Progress Chart</h3>
		<canvas id="myChart" width="1000" height="400"></canvas>
	</div>
<script src="jquery-3.1.0.js"></script>
<script src="npo.js"></script>
<script src="index.js"></script>

</body>

1 个答案:

答案 0 :(得分:3)

这是一个使用setTimeout一个接一个地绘制水平条的小样本。我有一个示例时序设置,等待前一个栏完成并重新绘制每10毫秒。运行它以查看。

&#13;
&#13;
<!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>
&#13;
&#13;
&#13;

编辑:清洁,多个条的延迟总和

&#13;
&#13;
<!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>
&#13;
&#13;
&#13;