Canvas 使用 clearRect 和 AudioContext 清除路径
Canvas clear path with clearRect and AudioContext
我有这个可视化工具,一切正常。唯一的问题是,当您使用 clean 功能清除 canvas,然后单击 changeSrc 时,您总是可以看到上一首歌曲的可视化效果。我可以摆脱这个吗?
您可能需要 运行 在 js fiddle 上 fiddle。
https://jsfiddle.net/t87wyzgd/6/
var renderVizualitationID,
canvas, ctx, center_x, center_y, radius, bars,
x_end, y_end, bar_height, bar_width,
frequency_array,
wrap, source;
wrap = $('.w')
canvas = document.getElementById("renderer");
ctx = canvas.getContext("2d");
bars = 200;
bar_width = 2;
multiplier = 0.7;
audio = new Audio();
audio.crossOrigin = "anonymous";
context = new(window.AudioContext || window.webkitAudioContext)();
analyser = context.createAnalyser();
audio.src = "https://api.soundcloud.com/tracks/42328219/stream?client_id=b1495e39071bd7081a74093816f77ddb"; // the source path
audio.loop = true;
source = context.createMediaElementSource(audio);
source.connect(analyser);
analyser.connect(context.destination);
frequency_array = new Uint8Array(analyser.frequencyBinCount);
audio.play();
animationLooper();
function animationLooper() {
// set to the size of device
canvas.width = wrap.width();
canvas.height = wrap.height();
// find the center of the window
center_x = canvas.width / 2;
center_y = canvas.height / 2;
radius = canvas.height / 6;
//draw a circle
ctx.beginPath();
ctx.arc(center_x, center_y, radius, 0, 2 * Math.PI);
ctx.stroke();
analyser.getByteFrequencyData(frequency_array);
var i;
for (i = 0; i < bars; i++) {
//divide a circle into equal parts
rads = Math.PI * 2 / bars;
bar_height = frequency_array[i] * multiplier;
// set coordinates
x = center_x + Math.cos(rads * i) * (radius);
y = center_y + Math.sin(rads * i) * (radius);
x_end = center_x + Math.cos(rads * i) * (radius + bar_height);
y_end = center_y + Math.sin(rads * i) * (radius + bar_height);
//draw a bar
var lineColor = "rgb(" + frequency_array[i] + ", " + frequency_array[i] + ", " + 205 + ")";
ctx.strokeStyle = lineColor;
ctx.lineWidth = bar_width;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x_end, y_end);
ctx.stroke();
}
renderVizualitationID = requestAnimationFrame(animationLooper);
}
$('#clean').on('click',function() {
if (renderVizualitationID) cancelAnimationFrame(renderVizualitationID);
audio.pause();
audio.src = '';
ctx.clearRect(0, 0, canvas.width, canvas.height);
});
$('#changeSrc').on('click',function() {
audio.src = "https://api.soundcloud.com/tracks/693365626/stream?client_id=r4wruADPCq7iqJomagvYpdehvILa2bgE"; // the source path
audio.play();
animationLooper();
});
.w {
position: relative;
top: 0;
left: 0;
width: 400px;
height: 400px;
background: #ccc;
}
#renderer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #111;
background: #1D4350;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="w">
<canvas id="renderer"></canvas>
</div>
<a id="clean" href="#" >clean</a>
<a id="changeSrc" href="#" >changeSrc</a>
发生这种情况是因为您的 AudioAnalyser 通过缓冲数据来工作,它只是随着时间的推移取消移动新数据。所以当你暂停你的音频时,它仍然会包含一些数据。
为避免这种情况,您只需在 clean
函数
中创建一个新的 AudioAnalyser
var renderVizualitationID,
canvas, ctx, center_x, center_y, radius, bars,
x_end, y_end, bar_height, bar_width,
frequency_array,
wrap, source;
wrap = $('.w')
canvas = document.getElementById("renderer");
ctx = canvas.getContext("2d");
bars = 200;
bar_width = 2;
multiplier = 0.7;
audio = new Audio();
audio.crossOrigin = "anonymous";
context = new(window.AudioContext || window.webkitAudioContext)();
analyser = context.createAnalyser();
audio.src = "https://api.soundcloud.com/tracks/42328219/stream?client_id=b1495e39071bd7081a74093816f77ddb"; // the source path
audio.loop = true;
source = context.createMediaElementSource(audio);
source.connect(analyser);
analyser.connect(context.destination);
frequency_array = new Uint8Array(analyser.frequencyBinCount);
audio.play();
animationLooper();
// do not change the size of your canvas when you are drawing on it
// that will reset the whole canvas and require anew pixel buffer
// so do it only when really required
window.onresize = function() {
// set to the size of device
canvas.width = wrap.width();
canvas.height = wrap.height();
};
window.onresize();
function animationLooper() {
ctx.clearRect( 0, 0, canvas.width, canvas.height )
// find the center of the window
center_x = canvas.width / 2;
center_y = canvas.height / 2;
radius = canvas.height / 6;
//draw a circle
ctx.beginPath();
ctx.arc(center_x, center_y, radius, 0, 2 * Math.PI);
ctx.stroke();
analyser.getByteFrequencyData(frequency_array);
var i;
for (i = 0; i < bars; i++) {
//divide a circle into equal parts
rads = Math.PI * 2 / bars;
bar_height = frequency_array[i] * multiplier;
// set coordinates
x = center_x + Math.cos(rads * i) * (radius);
y = center_y + Math.sin(rads * i) * (radius);
x_end = center_x + Math.cos(rads * i) * (radius + bar_height);
y_end = center_y + Math.sin(rads * i) * (radius + bar_height);
//draw a bar
var lineColor = "rgb(" + frequency_array[i] + ", " + frequency_array[i] + ", " + 205 + ")";
ctx.strokeStyle = lineColor;
ctx.lineWidth = bar_width;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x_end, y_end);
ctx.stroke();
}
renderVizualitationID = requestAnimationFrame(animationLooper);
}
$('#clean').on('click',function() {
if (renderVizualitationID) cancelAnimationFrame(renderVizualitationID);
audio.pause();
audio.src = '';
frequency_array.fill( 0 );
ctx.clearRect(0, 0, canvas.width, canvas.height);
// kill the previous one
analyser.disconnect();
// create a new analyser
analyser = context.createAnalyser();
source.connect( analyser );
analyser.connect(context.destination);
});
$('#changeSrc').on('click',function() {
audio.src = "https://api.soundcloud.com/tracks/693365626/stream?client_id=r4wruADPCq7iqJomagvYpdehvILa2bgE"; // the source path
audio.play();
animationLooper();
});
.w {
position: relative;
top: 0;
left: 0;
width: 400px;
height: 400px;
background: #ccc;
}
#renderer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #111;
background: #1D4350;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="w">
<canvas id="renderer"></canvas>
</div>
<a id="clean" href="#" >clean</a>
<a id="changeSrc" href="#" >changeSrc</a>
我有这个可视化工具,一切正常。唯一的问题是,当您使用 clean 功能清除 canvas,然后单击 changeSrc 时,您总是可以看到上一首歌曲的可视化效果。我可以摆脱这个吗?
您可能需要 运行 在 js fiddle 上 fiddle。
https://jsfiddle.net/t87wyzgd/6/
var renderVizualitationID,
canvas, ctx, center_x, center_y, radius, bars,
x_end, y_end, bar_height, bar_width,
frequency_array,
wrap, source;
wrap = $('.w')
canvas = document.getElementById("renderer");
ctx = canvas.getContext("2d");
bars = 200;
bar_width = 2;
multiplier = 0.7;
audio = new Audio();
audio.crossOrigin = "anonymous";
context = new(window.AudioContext || window.webkitAudioContext)();
analyser = context.createAnalyser();
audio.src = "https://api.soundcloud.com/tracks/42328219/stream?client_id=b1495e39071bd7081a74093816f77ddb"; // the source path
audio.loop = true;
source = context.createMediaElementSource(audio);
source.connect(analyser);
analyser.connect(context.destination);
frequency_array = new Uint8Array(analyser.frequencyBinCount);
audio.play();
animationLooper();
function animationLooper() {
// set to the size of device
canvas.width = wrap.width();
canvas.height = wrap.height();
// find the center of the window
center_x = canvas.width / 2;
center_y = canvas.height / 2;
radius = canvas.height / 6;
//draw a circle
ctx.beginPath();
ctx.arc(center_x, center_y, radius, 0, 2 * Math.PI);
ctx.stroke();
analyser.getByteFrequencyData(frequency_array);
var i;
for (i = 0; i < bars; i++) {
//divide a circle into equal parts
rads = Math.PI * 2 / bars;
bar_height = frequency_array[i] * multiplier;
// set coordinates
x = center_x + Math.cos(rads * i) * (radius);
y = center_y + Math.sin(rads * i) * (radius);
x_end = center_x + Math.cos(rads * i) * (radius + bar_height);
y_end = center_y + Math.sin(rads * i) * (radius + bar_height);
//draw a bar
var lineColor = "rgb(" + frequency_array[i] + ", " + frequency_array[i] + ", " + 205 + ")";
ctx.strokeStyle = lineColor;
ctx.lineWidth = bar_width;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x_end, y_end);
ctx.stroke();
}
renderVizualitationID = requestAnimationFrame(animationLooper);
}
$('#clean').on('click',function() {
if (renderVizualitationID) cancelAnimationFrame(renderVizualitationID);
audio.pause();
audio.src = '';
ctx.clearRect(0, 0, canvas.width, canvas.height);
});
$('#changeSrc').on('click',function() {
audio.src = "https://api.soundcloud.com/tracks/693365626/stream?client_id=r4wruADPCq7iqJomagvYpdehvILa2bgE"; // the source path
audio.play();
animationLooper();
});
.w {
position: relative;
top: 0;
left: 0;
width: 400px;
height: 400px;
background: #ccc;
}
#renderer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #111;
background: #1D4350;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="w">
<canvas id="renderer"></canvas>
</div>
<a id="clean" href="#" >clean</a>
<a id="changeSrc" href="#" >changeSrc</a>
发生这种情况是因为您的 AudioAnalyser 通过缓冲数据来工作,它只是随着时间的推移取消移动新数据。所以当你暂停你的音频时,它仍然会包含一些数据。
为避免这种情况,您只需在 clean
函数
var renderVizualitationID,
canvas, ctx, center_x, center_y, radius, bars,
x_end, y_end, bar_height, bar_width,
frequency_array,
wrap, source;
wrap = $('.w')
canvas = document.getElementById("renderer");
ctx = canvas.getContext("2d");
bars = 200;
bar_width = 2;
multiplier = 0.7;
audio = new Audio();
audio.crossOrigin = "anonymous";
context = new(window.AudioContext || window.webkitAudioContext)();
analyser = context.createAnalyser();
audio.src = "https://api.soundcloud.com/tracks/42328219/stream?client_id=b1495e39071bd7081a74093816f77ddb"; // the source path
audio.loop = true;
source = context.createMediaElementSource(audio);
source.connect(analyser);
analyser.connect(context.destination);
frequency_array = new Uint8Array(analyser.frequencyBinCount);
audio.play();
animationLooper();
// do not change the size of your canvas when you are drawing on it
// that will reset the whole canvas and require anew pixel buffer
// so do it only when really required
window.onresize = function() {
// set to the size of device
canvas.width = wrap.width();
canvas.height = wrap.height();
};
window.onresize();
function animationLooper() {
ctx.clearRect( 0, 0, canvas.width, canvas.height )
// find the center of the window
center_x = canvas.width / 2;
center_y = canvas.height / 2;
radius = canvas.height / 6;
//draw a circle
ctx.beginPath();
ctx.arc(center_x, center_y, radius, 0, 2 * Math.PI);
ctx.stroke();
analyser.getByteFrequencyData(frequency_array);
var i;
for (i = 0; i < bars; i++) {
//divide a circle into equal parts
rads = Math.PI * 2 / bars;
bar_height = frequency_array[i] * multiplier;
// set coordinates
x = center_x + Math.cos(rads * i) * (radius);
y = center_y + Math.sin(rads * i) * (radius);
x_end = center_x + Math.cos(rads * i) * (radius + bar_height);
y_end = center_y + Math.sin(rads * i) * (radius + bar_height);
//draw a bar
var lineColor = "rgb(" + frequency_array[i] + ", " + frequency_array[i] + ", " + 205 + ")";
ctx.strokeStyle = lineColor;
ctx.lineWidth = bar_width;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x_end, y_end);
ctx.stroke();
}
renderVizualitationID = requestAnimationFrame(animationLooper);
}
$('#clean').on('click',function() {
if (renderVizualitationID) cancelAnimationFrame(renderVizualitationID);
audio.pause();
audio.src = '';
frequency_array.fill( 0 );
ctx.clearRect(0, 0, canvas.width, canvas.height);
// kill the previous one
analyser.disconnect();
// create a new analyser
analyser = context.createAnalyser();
source.connect( analyser );
analyser.connect(context.destination);
});
$('#changeSrc').on('click',function() {
audio.src = "https://api.soundcloud.com/tracks/693365626/stream?client_id=r4wruADPCq7iqJomagvYpdehvILa2bgE"; // the source path
audio.play();
animationLooper();
});
.w {
position: relative;
top: 0;
left: 0;
width: 400px;
height: 400px;
background: #ccc;
}
#renderer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #111;
background: #1D4350;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="w">
<canvas id="renderer"></canvas>
</div>
<a id="clean" href="#" >clean</a>
<a id="changeSrc" href="#" >changeSrc</a>