いつものように、写真を見てください!
効果は次のとおりです。
大きなHD画像!
長年コーダーとして働いていますが、老眼で目が暗くなり、アニメーションがよく見えません。 !次に、静的なスクリーンショットを見てください。 ! !
さまざまなスコアの影響は次のとおりです。
セラーズショーを見た後は、商品の製造工程を見てみましょう!
Canvas は円を描画します 1. vue では、<template lang=pug> のコードは次のとおりです。
Canvas#baseCanvas は下部の灰色のリングです
Canvas#myCanvas は上のカラーリングです
灰色のリングの上にある色付きのリングをカバーするには、CSS スタイルを使用する必要があります。
2. CSS スタイル: 3. js-canvas スタイルの描画コードこのコードも非常にシンプルです。キャンバス API を見てください。
3-1. vue コンポーネントで、script タグの先頭に必要な変数を定義します。
3-2. vueのメソッドオブジェクトには以下の3つのメソッドが定義されています。
drawBaseCanvas: 下部の灰色のリングを描画するために使用されます。灰色の円にはアニメーション効果がないため、最初に完全な灰色の円を描画するだけです。 drawClrCanvas: 上のカラーリングを描画するために使用されます。 clearCanvas: キャンバスをクリアするために使用されます。これは、カラー リング アニメーションに必要なものです。リングのアニメーション効果の中核は、色付きのリングを時々クリアし、終了角度の値を増やして再描画し、連続的なアニメーションになるようにすることであるためです。
3 つのメソッドのコードは次のとおりです。
上記の 3 つのメソッドのコードは、ほとんどすべて Canvas API のアプリケーションです。チュートリアルを読んでください。
draoClrCanvasメソッドのみ、キャンバスの円を描画する際に、arcパラメータに開始値と終了値が設定されます。
開始値は円の描画開始位置を決定し、終了値は終了位置を決定します(ナンセンスなことを言ったようですが、考えの説明文をよく考えた後、削除したくありませんははは)
この最終値の計算は私にとって非常に面倒です。
なぜ count 変数をこのように計算する必要があるのでしょうか? どうやって計算したか忘れました。
this.grade は 100 以内の正の整数で、スコアを示します。データで定義され、デフォルトは 0 ポイントです。
つまり、開始点と終了点が両方とも 0 点であるため、色付きの円は最初は表示されません。
グレードの値を0~100まで変更すると、キャンバスのカラーリングの値も変わります。
このように、グレードの値を徐々に変更して再描画すると、色のリングが徐々に増加してアニメーション効果が得られます。
リングのアニメーション効果ここでは特別なニーズがあるため、ユーザーがキャンバスが配置されているスワイパーに向かうたびにアニメーションをトリガーする必要があります (後ほど、これはさらに面倒で、アニメーションの開始前にヒストグラムとキャンバスの部分に入口効果を持たせる必要があります)。エフェクトは上の図で最も長くなります (GIF アニメーションのように)。
したがって、それを達成するにはスワイパーを使用する必要があります。スワイパー スイッチのコールバック関数では、成績スコアが 0 から連続的に増加し、カラー リングの描画が再トリガーされてアニメーション効果が実現されます。
私がvueで使用しているスワイパーは「vue-awesome-swiper」です。彼女の使用手順は他の記事に書きました。
vue-data の swiper の設定に on オブジェクトがあります。 on オブジェクトの slideChange 関数は、スワイパーがページをめくるたびにトリガーされるコールバック関数です。
ここでは、いくつかの特別なポイントについて説明します。
(1) vm: vue スクリプトに格納した変数です。null に初期化され、マウント時に vue インスタンス オブジェクトとして割り当てられます。
データを初期化して灰色の円を描画します
このメソッドを通じて、vue インスタンスの object-data-swiper-callback 関数の Grade および GradeTarget 属性値を取得し、それらを変更します。
ps: これが愚かなアプローチかどうかはわかりませんが、これを実行したときに、swiper の on コールバックで vue インスタンスを取得する方法がわかりませんでした。つまり、国を救うには非常に曲がりくねった方法があったのです。より良い解決策があれば、新しいアイデアを提供していただければ幸いです、ありがとうございます。
(2) (this.activeIndex == 2 && vm.isStar) || (this.activeIndex == 1 && !vm.isStar)
この判断はビジネス上行われるため、無視して構いません。
これは、swiperChange 関数のスワイパー オブジェクトを指します。 this.activeIndex は、スワイパー インスタンスのプロパティであり、正式には、現在のアクティブ ブロック (アクティブ化ブロック) のインデックスを返します。彼が現在どのページを参照しているか、つまり、現在見ているスワイパー スライドの下付き文字について言及していることがわかります。
ユーザーとしての私のアイデンティティのため、現在のキャンバスが配置されているスワイパーの前のページを表示するかどうかを決定します。 表示されていない場合、前のページはまったく描画されず、現在のページの対応するスワイパー添え字は (index-1) になります。
全体として、条件が満たされ、ユーザーがキャンバスがあるスワイパー ページに移動すると、if でリング描画ロジックがトリガーされます。それ以外の場合は、else に移動してデータ ページの状態を初期化し、タイマーをクリアしてアニメーションを一時停止し、色付きのリングをクリアします。
(3)vm.aniShow
前回の記事「純粋な CSS によるヒストグラムの描画」で述べたように、ヒストグラムのアニメーションについては、キャンバスのアニメーションと併せて説明する必要があります。アニメーションの実装はスワイパーの切り替えと連携する必要があるためです。それがここのコードです:
vue - data - aniShow 属性が true になると、クラス名 ani が div.row に追加されます。
同様に、aniShow が true の場合、進行状況の高さには独自のターゲット値が割り当てられます。つまり、進行状況の実際の高さは、パーセンテージで変換された後、スタイル属性の高さに割り当てられます。
このとき、プログレストランジションは高さの変化を監視しているため、高さの増加に応じてヒストグラムが増加するアニメーションが開始されます。
ani クラスの名前の下で、進行状況の遷移遅延は、高度に時間差のある増分効果を実現します。
テキストの説明を読むだけでは混乱するかもしれませんが、効果をもう一度見てください。
(4) カラーサークル描画コード部
GradeTarget は実際のスコアであり、抽出される最終結果です。
Grade は 0 から始まり、gradeTarget のサイズまで増加します。
ここで直接 ++vm.grade を実行したわけではありません。そのとき何を考えていたかわかりません。
判定した場合、成績が目標値gradeTargetまで増加するか、目標値より大きい場合、増加を停止し、grade=gradeTargetとします。クリティカルな価値に属する判断。モーション機能では衝突検知も考慮されています。
逆に、目標に達しなかった場合は、最後に描画したキャンバスがクリアされ、段階的にグレードが変更された後、新しいカラーリングが再描画されます。
(5) これらすべてを setTimeout に入れ、円の増分効果の描画を開始する前に棒グラフとリング チャートが市場に参入するのを待つために、実行する前に 500 ミリ秒停止します。
実際、上記のコードは非常に単純な論理プロセスです。読者はコードを一度読めば理解できるはずです。
新しいアイデア:
私はずっと前にこのエフェクトを作成しましたが、今日制作方法を整理していたときに、自分のコードの最適化ソリューションを考えました。
実際、タイマーでカラー サークル描画メソッドを再度呼び出す必要はありません。直接変更したのは this.grade 属性です。この属性の変更を監視するとよいでしょう。このようにして、このプロパティがタイマーで変更されると、リング メソッドが自動的に実行されます。
これはまだアイデアであり、練習が必要です。
中間テキストの追加効果:評定は毎回増加するスコアであるため、Vue の双方向データ バインディングを使用して、評定をスコア値として対応する DOM ビューに直接バインドできます。
最後に、上のリングと棒グラフのアニメーションをアニメーションと組み合わせて、アニメーションの遅延を制御します。とてもシンプルです。
Index.vue ソースコード:
(ソース コードは少し整理され、個別に抽出されていることに注意してください。完全性を確保するため、また他のビジネス コードを保護するために、いくつかの変数名が変更されており、以前のスクリーンショットとは若干異なる場合があります)
<template lang='pug'> .indexs#Indexs.app-bgtransition(name=fade) swiper#swiperBox(:options=swiperOption ref=mySwiper) swiper-slide.swiper-slide1 .container .up swiper-slide.swiper -slide2(v-if=isShow) .my-shark .up swiper-slide.swiper-slide3 .container .data-cont .data.data01 .data01-charts .row(v-for='item,index in Data' :key=index :class='aniShow ? ani:') 。 data-txt {{item.grade > 0 ? item.grade : 'データなし'}} .progress(:class='item.grade == 0 ? nodata : ' :style='height: ' + (aniShow ? (item.grade >= 100 ? (100 * 1.5) / 100 : item.grade == 0 ? 0.04 : item.grade * 1.5 / 100 ):0)+'rem')span.pg-data .week {{item.week}} .data.data02 .data02-charts .canvas-box //-baseCanvas Canvas#baseCanvas.my-canvas(ref=baseCanvas width=174 height=174) //- キャンバス Canvas#myCanvas.my-canvas.clr-canvas(ref=myCanvas width =174 高さ=174) .canvas-data #[span.num {{grade}}]points</template><script>var vm = null, timer1 = null, /* キャンバスの基本値*/ c = null, //document.getElementById(myCanvas); ctx = null, //canvas-2d Canvas x = 161 / 2 + 1, //円の中心座標 r = (161) - 10) / 2; //半径サイズ/* スワイパーコンポーネント*/import { swiper, swiperSlide } from vue-awesome-swiper;import { getData } from ../io/getData;export default { name: Indexs,Components: { swiper, swiperSlide }, data() { return { Grade: 0, //ドーナツ チャート スコア GradeTarget: 78.54, //実際のスコア番号, ajax 経由でデータをリクエストした後、isShow: true を変更できます。 // 2 ページ目のスワイパーを表示するかどうか aniShow: false, // 縦棒グラフのアニメーションを有効にするかどうか Data: [{ week:最初の週、グレード: 0 }、{ 週: 2 週目、グレード: 30 }、{ 週: 3 週目、グレード: 99.99 }、{ 週: 4 週目、グレード: 76.98 }、{ 週: 5 週目、グレード: 100 }], swiperOption: { //スワイパーパラメータ notNextTick: true、方向: 垂直、grabCursor: true、setWrapperSize: true, autoHeight: true、slidesPerView: 1、mousewheel: false、mousewheelControl: false、height: window.innerHeight、//高さ設定、デバイスの高さを埋める resistanceRatio: 0、observParents: true、initialSlide: 2 - 1、// 初期化設定時、スワイパーのデフォルトの表示ページ、最初から開始します: { slideChange() { if ( (this.activeIndex == 2 && vm.isShow) || (this.activeIndex == 1 && !vm.isShow) ) { console.log(this.activeIndex, vm.isShow, アニメーションを描画); setTimeout(function() { // ヒストグラムアニメーションを表示します vm.aniShow = true; // タイマーは、リングのアニメーション効果を実現するために、色付きのリングの描画を継続的にトリガーします timer1 = setInterval(function() { // 中間スコアのコピーライティングを変更します var num = vm.grade; num++; if (num >= vm.gradeTarget) { vm.grade = num; } / 60); }, 500) }; //ページをめくった後、データ ページのステータスを初期化し、タイマーをクリアしてアニメーションを一時停止し、色付きのリングをクリアします。 ; vm.clearCanvas (); } } } } ; 計算済み: {}, mount() { // データを初期化し、灰色の円を描画します。 this.$refs.myCanvas; ctx = c.getContext(2d); this.drawBaseCanvas(); メソッド: {drawBaseCanvas() { // キャンバス描画/* 基本値 */ var c = this.$refs.baseCanvas , //document.getElementById(myCanvas); // デバッガー; ctx = c.getContext(2d), o = x, randius = r; /*デフォルトの灰色の円*/ ctx.drawingStyle = #eee; ctx.beginPath(); ctx.arc(o, o, randius, 0, 2 * Math.PI); ; }, clearCanvas() { // キャンバスをクリアします ctx.clearRect(0, 0, 200, 200); drawClrCanvas() { var gradient = ctx.createLinearGradient(75, 50, 5, 90); gradient.addColorStop(1.0, #7E5CFF); // グラデーションを使用します。埋めるには ctx.lineWidth = 10; ctx.lineCap =round; ctx.shadowColor = rgba(191,142,255, 0.36); ctx.shadowBlur = 8; ctx.beginPath(); x、r、Math.PI、Math.PI * カウント、false); ctx.ストローク(); } }};</script><style lang='scss'>// 列 chart.row { 位置: 相対値: 0.61rem; - 0.08 - 0.38rem; text-align: center;}.data-txt { font-size: 0.2rem; 0.2rem; margin-bottom: 0.09rem;}.progress { height: 0rem; 遷移: height 0.5s easy-in-out;}.ani { @for $i from 1 to 6 { &:nth-of-type( #{$i}) { .progress { 遷移遅延: #{$i * 0.15}s } } } // &:nth-of-type(1) { // .progress { // 遷移遅延: .4s; // } // } // &:nth-of-type(2) { // .progress { // 遷移遅延: .8s; } // } // &:nth-of-type(3) { // .progress { // 遷移遅延: 1s; // } // } // &:nth-of-type(4) { / / 。進捗 { //遷移遅延: 1.4 秒; // } // } // &:nth-of-type(5) { // .progress { // 遷移遅延: 1.8 秒;データ { 表示: ブロック; 幅: 0.12rem; 高さ: 0 自動; 背景: 線形グラデーション (0deg, #c88eff 0%, #7e5cff 100%); box-shadow: 0 -0.04rem 0.14rem 0 rgba(129, 93, 255, 0.4); border-radius: 0.05rem 0.05rem 0 0;}//0 ポイント表示 rules.nodata { .pg-データ { ボーダー半径: 0; ボックスシャドウ: none; }}.week { font-size: 0.2rem; line-height: 0.2rem; margin-top: 0.08rem; }// リング チャート - data02 データ part.data02-charts : 0.32rem; 高さ: 1.61rem;}.canvas-box { 位置: 相対; 幅: 1.61rem; 高さ: 1.61rem; マージン左: 0.92rem;}.my-canvas { 幅: 1.61rem; 高さ: 1.61rem; } .canvas-data { 位置: 絶対; 左: 0; マージン-左: -0.1rem; フォントサイズ: 0.24rem; フォントサイズ: 0.32rem;
以上がこの記事の全内容です。皆様の学習のお役に立てれば幸いです。また、VeVb Wulin Network をご支援いただければ幸いです。