プロが教える店舗&オフィスのセキュリティ対策術

首記の件につきまして、
下記ソースコードがあるとします。

requestanimationframeを途中で止める方法がわからず困っています。
教えて頂きたくお願い致します。

やりたいこと:
・四角1~10が表示されるのが揃うまではrequestanimationframeで描画が表示され続ける
・最後の四角10が表示されてから5秒後に一斉に四角1~10のrequestanimationframeを止める
・止めた後にすぐ描画を消す(clearRect)


ソースコード:
//四角1
var id;
let x = 100;
let y = 70;
function drawsquare() {
//前の描画を消す
context.clearRect(40,90,270,240);

//四角を更新する
if(x < 255) {
x ++;
y ++;
}
else {
x = 100;
y = 70;
}

//四角を描画する
context.beginPath();
context.lineWidth = 4;
context.strokeStyle = 'rgb(20,238,200)';
context.strokeRect(50,100,x,y);
context.save();
window.requestAnimationFrame(drawsquare);
}
setTimeout(drawsquare,1);

//四角2
let x2 = 100;
let y2 = 70;
function drawsquare2() {
//前の描画を消す
context.clearRect(190,490,270,240);

//四角を更新する
if(x2 < 255) {
x2 ++;
y2 ++;
}
else {
x2 = 100;
y2 = 70;
}

//四角を描画する
context.restore();
context.strokeRect(200,500,x2,y2);
window.requestAnimationFrame(drawsquare2);
}
setTimeout(drawsquare2,1200); ←以下1200ずつ増えていく
以下、四角10まで続く。

A 回答 (1件)

こんにちは



>requestanimationframeを途中で止める方法がわからず困っています。
アニメーションの仕組みとして、再呼出しを繰り返す方式をとっていますので、再呼出しを止めればアニメーションは停止します。
停止用のflagを設けておいて、その値によって再呼出しを行うかどうかを判断すればよいでしょう。

また、ご質問には直接関係ありませんが、ざっと見るところ、
>context.save();
>context.restore();
の処理には意味がない上に、関数内で完結していないため(残りがどうなっているのか不明ですが)、おかしなことになる原因になりかねませんので、このような使い方はやめた方が宜しいと思います。


ご質問文には、ご提示の例が二つしかないので、四角1~四角10の関係がよくわかりませんが、勝手に想像するところ、
 ・サイズは同じ
 ・アニメーションの速度等も同じ
で、表示する位置だけ異なるものと仮定しました。
私のディスプレイでは四角10個を一度に表示できないので、以下の例では、四角のサイズを小さくし、個数も8個にしてあります。

>最後の四角10が表示されてから5秒後に一斉に四角1~10の
>requestanimationframeを止める
「表示されてから」の意味が、「書き始めたら」なのか「最大サイズで描画したら」なのかわかりませんが、最後のものを書始める時間は直接指定しているでしょうから、それから止めるまでの所要時間を計算できるので、あらかじめ、停止する関数を時間セットで動作させるのが簡単だと思います。

以下の例では、最後の四角が「3回目の最大サイズを表示したら」停止する関数を実行するようにしてあります。
(どのタイミングにするかだけの問題なので、判断基準を変えればいかようにでもなるでしょう)
また、図形表示の関数を何度も記述するのは非効率的なので、まとめてあります。

ご参考までに。
(IEは、アロー関数に対応していないため動作しません)

<!DOCTYPE HTML>
<html lang="ja">
<head><title>Sample</title>
</head>
<body>

<canvas id="canvas" width="800" height="800"></canvas>

<script>
let endFlag = false; // 停止用フラグ

const
canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
sizeMax = 100,
iPos = { x:50, y:30 };


const
endFunc = () =>{
endFlag = true;
ctx.clearRect(0, 0, canvas.clientWidth, canvas.clientHeight);
},
drawsquare = (n, f) =>{
let size = 0, count = 0;

const
Lw = widths[n % widths.length],
Lh = Math.ceil(Lw),
col = 'rgb(' + colors[n % colors.length] + ')',
p = { x:poss[n].x + Lw, y:poss[n].y + Lw },
box = { x:sizeMax + iPos.x + 2*Lh, y:sizeMax + iPos.y + 2*Lh };

const d = () => {
if(endFlag) return;
ctx.clearRect(p.x - Lh , p.y - Lh, box.x, box.y);
ctx.lineWidth = Lw;
ctx.strokeStyle = col;
ctx.beginPath();
ctx.strokeRect(p.x, p.y, iPos.x + size, iPos.y + size);
size = (size < sizeMax)? ++size: 0;
if(size == 0) count++;
if(count > 2 && f) endFunc();
requestAnimationFrame(d);
}
d();
};


const
num = 8,
colors = ['20 238 200','530 50 200','100 250 100','0 0 0'],
widths = [4, 12, 8],
poss = [
{x:0, y:0}, {x:300, y:0}, {x:80, y:170}, {x:380, y:170},
{x:160, y:340}, {x:460, y:340}, {x:240, y:510}, {x:540, y:510}
];

for(let i=0; i<num; i++){
setTimeout(drawsquare, i * 1200, i, i==(num-1));
}
</script>
</body>
</html>
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!