私が最近実践した下の写真の効果を皆さんと共有したいと思います。
以下の曲線のアニメーションを描画したい場合
毎回短い線を引いて結ぶと、下の図は5つのセグメントに分割されます。
あと 10 段落読んでください
分割数が十分であれば、1 つずつ描画すると曲線の軌跡のように見えます。
二次ベジェ曲線/** * 二次ベジェ曲線アニメーション* @param {Array<number>} 開始開始点の座標* @param {Array<number>} 曲率点の座標 (つまり、正確な座標ではなく、おおよその方向) * @param {Array<number>} end 終点座標 * @param {number} パーセント描画パーセント (0-100) */ functiondrawCurvePath(start, point, end,percent){ ctx.beginPath(); //線の描画を開始します ctx.moveTo(start[0], start[1]) //ペンを開始点に移動します (var t = 0; t <=パーセント / 100; t) += 0.005 ) { //各時点の座標を取得 var x =quadraticBezier(start[0], point[0], end[0], t); quadraticBezier(start[1], point[1], end[1], t); ctx.lineTo(x, y); //前の時点から現在の時点まで直線を描画します。 ); //Stroke} /** * 二次ベジェ曲線方程式* @param {配列<数値>} 開始開始点* @param {配列<数値>} 曲率点* @param {配列<数値>} 終了終点 * @param {数値} 描画進行状況 (0-1) */ functionquadraticBezier(p0, p1, p2, t) { var k = 1 - t; return k * k * p0 + 2 * (1 - t) * t * p1 + t * t * p2;
ベジェ曲線の詳細については、このブログを参照してください。
完全なコードに
<!DOCTYPE html><html lang=ja><head> <meta charset=UTF-8> <meta name=viewport content=width=device-width、initial-scale=1.0> <meta http-equiv=X-UA -互換コンテンツ=ie=edge> <title>二次ベジェ曲線アニメーション</title> <style> body { background: #0f1632 } #canvas { border: 1px Solid #ccc; } #img { display: none <!--img を直接非表示にするだけです。後で直接引用されます --> } </style></head><body> <canvas id=canvas width =1500 高さ =750></canvas> <img id=img src=https://s3.imgsha.com/2019/04/22/light.png> <script> var ctx = document.getElementById('canvas').getContext('2d'); var img = document.getElementById('img'); var パーセント = 0; 開始: [400, 200], ポイント: [ 300, 100]、終了: [100, 400]、部門: 'データ 1'、値: 4321 } 関数init(){percent = 0; //毎回処理をリセットdraw(); } functiondraw(){ ctx.clearRect(0, 0, 1500, 750); //毎回キャンバスをクリアします。 # ffffff'; //線のスタイルを設定しますdrawCurvePath(data.start, data.point, data.end,percent); //プロセスが増加するにつれて、これはアニメーション速度を制御します (percent <=) 100) { //描画が完了していない場合は呼び出しを続行します。描画が完了すると進行状況はリセットされます requestAnimationFrame(draw) }else{ init() } } functiondrawCurvePath(start, point, end,percent); /... } functionquadraticBezier( p0, p1, p2, t) { //... } </script></body></html>
アニメーションが出てくる
前に述べたように、 drawCurvePath(start, point, end, percent)
関数のpoint
パラメーターは、曲率の特定の点ではなく、一般的な方向です。
point
を[200,200]
に変更した場合を見てみましょう
落ちる効果を実現したい場合は、ラインに高いところから低いところ、遠いところから近いところへのグラデーション効果を追加する必要があります。
/** * 線形グラデーションを作成します* @param {Array<number>} start 開始点* @param {Array<number>} 曲率点* @param {Array<number>} end end point* @param {number} 描画progress ( 0-1) */function createLinearGradient(start,end,startColor,endColor){ var lineGradient = ctx.createLinearGradient(...start, ...end); lineGradient.addColorStop(0, startColor); // lineGradient.addColorStop(0.3, '#fff'); lineGradient.addColorStop(1, endColor); // 描画関数には調整が必要です functiondraw(){ // ctx.ストロークスタイル = '#ffffff'; ctx.ストロークスタイル = createLinearGradient(data.start, data.end, 'rgba(255,255,255,.2)', '#fff' );
キャンバスのグラデーションの詳細については、MDN を参照してください。
頭のハロー頭のハローを追加するには、円を描画し、放射状のグラデーションを設定する必要があります。drawCurvePath 関数drawCurvePath
使用して、x、y を取得し、円の位置をリセットします。
function createHeadLight(x,y){ ctx.beginPath(); //放射状グラデーションを作成 varradialGradient = ctx.createRadialGradient(x, y, 0, x, y, 20); )); radioGradient.addColorStop(.2, rgba(255,255,255,.8)); radioGradient.addColorStop(1,parent); //円を描く ctx.arc(x, y, 20, 0, 2 *)数学.PI、false); ctx.fill();}//drawCurvePath 関数にはいくつかの調整が必要です functiondrawCurvePath(start, point, end,percent){ //... ctx.ストローク() // Stroke createHeadLight(x,y) // 描画線を描くような円の周波数}
円を描画するためのarc
詳細については、MDN を参照してください。
テキストの追加は、頭のハローの追加と非常に似ています。どちらも、 drawCurvePath
関数を使用して x、y を取得し、テキスト ブロックの位置をリセットします。
/** * テキストの作成* @param {String} 部門データ* @param {Number} データ* @param {Number} x 軸座標* @param {Number} y 軸座標*/functiondrawText(部門, 値, x, y) { ctx.fillStyle = '#fff' ctx.font = 22px Microsoft Yahei ctx.fillText(部門, x + 30, y + 20); //ハローの右下隅にテキストを作成するには、y 軸をある程度の距離だけオフセットする必要があります var width = ctx.measureText(value).width; //幅を取得します。テキストの ctx.fillStyle = createLinearGradient([x + 30, 0], //テキスト グラデーションの x 軸のレンダリング範囲は [x+30,x+30+text width], [x + 30 + width, 0]、 //テキストの高さを取得するための API がないため、ここでは y を 0 に設定します。0 を書くことも可能です。 '#fffd00', '#ff6d00' ); 50 ); } //drawCurvePath 関数にはいくつかの調整が必要です functiondrawCurvePath(start, point, end,percent,Department, value) { //... createHeadLight(x,y)drawText(部門,値,x,y) }アニメーション終了後の終了位置に文字や絵を追加します。
アニメーションの完了後にテキストや画像を追加する場合は、曲線アニメーションの完了後すぐにキャンバスをクリーンアップしてから、テキストや画像を追加する必要があることに注意してください。
/** * 画像の作成* @param {数値} x 軸座標* @param {数値} y 軸座標*/functiondrawImg(x, y) { ctx.drawImage(img, x - img.width / 2, y - img.height); }//描画関数にはいくつかの調整が必要ですdraw(){ //... if (percent <= 100) { requestAnimationFrame(draw); }else{ ctx.clearRect(0, 0, 1500, 750); //曲線アニメーションが完了したらすぐにキャンバスをクリアしますdrawText(data.Department, //テキストをレンダリングします data.value, data.end[0], data .end[1 ])drawImg(data.end[0], data.end[1]) //画像をレンダリング setTimeout(function(){ //2000ms 後に init() を再描画 },2000) } }仕上げる
この例の完全なコード
記事の最初の画像にある例の完全なコード
参考記事:キャンバスを使って曲線アニメーションを描く - ベジェ曲線を深く理解する
以上がこの記事の全内容です。皆様の学習のお役に立てれば幸いです。また、VeVb Wulin Network をご支援いただければ幸いです。