3

我正在尝试为水平条形图绘制动画。它会慢慢绘制,一旦完成绘制第二个。就像 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){
	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>

4

1 回答 1

4

这是一个小样本,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>

于 2016-07-29T04:04:45.467 回答