キャンバスが折り畳みパスを描くアニメーション
先日、読者からWeChatでこんな質問を受けました。
そのひとつが、次の画像のようなダッシュパスアニメーション効果です。
上記のようなパスアニメーションを実装するには、一般的にsvgのアニメーション機能を利用することができます。または、パス計算と組み合わせたキャンバス描画を使用して実現します。
キャンバスで描画する場合、困難な点として
- サブパスの計算が必要で、この部分の計算が複雑になる。(これは確かに可能です。)
- グラデーションの計算です。図からわかるように、アニメーションのサブパスにはグラデーション効果があり、グラデーションを分割して計算するのは煩雑になりそうです。
今回は、clipメソッドを使って、クリップの領域を動的に移動させ、近似値を実現するアイデアを紹介します。その方法を紹介します。
灰色のパスの描画
パスを描画するコードは比較的単純なので、ここでは詳しく説明せず、以下のコードでポリラインパスの描画をシミュレートしています。
ValueError: source code string cannot contain null bytes
その効果は次の通りです。
明るいパスの描画
明るいパスを描画するコードは、スタイルが明るい色であることを除いて、灰色のパスを描画するコードと同じです。
OSError: [WinError 123] Incorrect filename, directory name or volume label syntax. : '<frozen importlib._bootstrap>'
その効果は次の通りです。
クリップは、明るい色のパスを描画する領域を制御します。
canvas の clip メソッドは、描画領域を制御し、それによって賢明な描画パスの一部を制御することができます: 。
ctx.beginPath();
ctx.rect(offset,0,100,500); // offset is equal to 0
ctx.clip();
...
ctx.stroke();
クリップ後、明るいパスは以下のように部分的にしか描画されません。
<イグ
アニメーションの効果
明るい道が大通りを移動する効果は、以下のコードで、offsetの値を常に変化させることで実現できます。
offset += 2;
if(offset > 600){
offset = 100;
}
requestAnimationFrame(animate);
最終的にはこのようになります。
グラデーション
グラデーションは任意の経路をたどることができないことは分かっているので、線を計算するのであれば、分割して計算するのは面倒だ。実はこの場合、線分といっても全体の進行方向は常に左から右なので、左から右へのグラデーションで近似することができます。
function createGradient(ctx,x0,y0,x1,y1){
var grd = ctx.createLinearGradient(x0,y0,x1,y1);
grd.addColorStop(0,'#129ab3');
grd.addColorStop(1,"#19b5fe");
return grd;
}
ctx.strokeStyle = createGradient(ctx,offset,0,offset + 100,0);
最終的には以下のようになります。
フルコード
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>line animate</title>
<style>
canvas {
border: 1px solid #000;
}
</style>
</head>
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
var ctx = document.getElementById( 'canvas' ).getContext( '2d' );
var w = canvas.width,
h = canvas.height;
var x = w / 2,y = h / 2;
function setupCanvas(canvas) {
let width = canvas.width,
height = canvas.height,
dpr = window.devicePixelRatio || 1.0;
if (dpr ! = 1.0 ) {
canvas.style.width = width + "px";
canvas.style.height = height + "px";
canvas.height = height * dpr;
canvas.width = width * dpr;
ctx.scale(dpr, dpr);
}
}
setupCanvas(canvas);
var offset = 100;
function createGradient(ctx,x0,y0,x1,y1){
var grd = ctx.createLinearGradient(x0,y0,x1,y1);
grd.addColorStop(0,'#9a12b3');
grd.addColorStop(1,"#19b5fe");
return grd;
}
function animate(){
ctx.fillStyle = "black";
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.lineWidth = 3;
ctx.save();
ctx.beginPath();
ctx.moveTo(100,100);
ctx.lineTo(200,100);
ctx.lineTo(230,200);
ctx.lineTo(250,50);
ctx.lineTo(270,180);
ctx.lineTo(300,60);
ctx.lineTo(330,160);
ctx.lineTo(350,60);
ctx.lineTo(380,100);
ctx.lineTo(480,100);
ctx.strokeStyle = "gray";
ctx.lineJoin = "round";
ctx.stroke();
ctx.beginPath();
ctx.rect(offset,0,150,500);
ctx.clip();
ctx.beginPath();
ctx.moveTo(100,100);
ctx.lineTo(200,100);
ctx.lineTo(230,200);
ctx.lineTo(250,50);
ctx.lineTo(270,180);
ctx.lineTo(300,60);
ctx.lineTo(330,160);
ctx.lineTo(350,60);
ctx.lineTo(380,100);
ctx.lineTo(480,100);
ctx.lineWidth = 4;
ctx.strokeStyle = createGradient(ctx,offset,0,offset + 150,0);
ctx.lineCap = "round";
// ctx.globalCompositeOperation = 'lighter';
ctx.lineJoin = "round";
ctx.stroke();
ctx.restore();
offset += 2;
if(offset > 600){
offset = 100;
}
requestAnimationFrame(animate);
}
animate();
</script>
</body>
</html>
概要
全体としては、パスの長さやグラデーション効果を厳密に制御するのではなく、近似性を利用することで、上記の機能を実現しやすくしています。 人間の目は時に細部を識別できないことがあり、視覚化は時にそれを"feel"させる唯一の方法なので、目的は達成されます。
上記の解決策は、折り返し経路の全体的な方向が同じである場合にのみ有効です。全体的な方向が水平に右へ、次に垂直に下へ、あるいは逆方向である場合は、うまくいきません。
キャンバス描画フォールドパスアニメーションについてのこの記事はこれで終わりです、キャンバスフォールドパスアニメーションに関するより多くの関連するコンテンツは、スクリプトハウスの過去の記事を検索してくださいまたは、次の関連記事を閲覧を続ける、私はあなたがよりスクリプトハウスをサポートすることを願っていますよ。
関連
-
Html5 データストリームによる動画再生
-
画像のウォーターフォールレイアウトを実現するHTML+CSS+JSのサンプルコード
-
HTML5のSEO最適化のためのいくつかの提案
-
html5 on outbound embedded page 通信問題 (postMessage でクロスドメイン通信を解決)
-
divやimgの画像の高さを幅に合わせる方法
-
html5 色彩公差キーイング with canvas
-
キャンバス経由でのRGBAフォーマットへの色変換とパフォーマンス問題の解決
-
キャンバスを使用して画像サイズを圧縮する例
-
Canvasを使用したHD画面での描画がにじむ問題とその解決方法について
-
モバイル版Html5におけるBaidu地図のクリックイベント
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Html5による大画面データビジュアライゼーション開発の実装
-
モバイルHTML5入力に関するFAQ(要約)
-
ラチェット式モーダルボックスの実装
-
Html5は、コンテナは、画面の高さや残りの高さの適応的なレイアウトの実装を埋めることができます
-
キャンバスのマウスがアニメーションの背景に従うことを達成するために5分
-
HD画面でのキャンバスサイズリセットによる不具合の解消について
-
円形のプログレスバーを生成する html svg
-
Html5 Canvasアニメーションの基本的な衝突検出の実装
-
HTML5 動画再生プラグイン video.js のご紹介
-
html5 canvasによる画像圧縮のサンプルコード