アプレットキャンバス実際のパフォーマンスの最適化

以下の記事はトトロ「アプレットキャンバスパフォーマンス最適化の戦闘から転載されました!"

作者:totoro

リンク:https://blog.totoroxiao.com/canvas-perf-mini/

出典:https://blog.totoroxiao.com/

著作権は著者が保有しました。著者は認可商業転載してください接触、非商用の転載は、ソースを明記してください。

テンセントロケーションベースのサービスのアプレットプラグインで簡単に開発者を支援し、迅速小さなプログラムを構築することができる小型のプラグインのシリーズを作成するために、(周り)の地図機能に焦点を当て、マイクロチャネルを提供する機能、ベストパートナーを達成するために、あなたのマップ機能です。現時点では、小さなマイクロチャンネルのプラグインが提供ルート計画、地下鉄マップ、地図、用地選定やその他のサービスを!

ケースの背景

要件:

線、円、画像、テキストなどの要素を描き、地下鉄マップ地下鉄、サイトのアイコン、サイト名とテキストの行を含むアプレットキャンバスコンポーネントに地下鉄マップを描画します。
支持体は、パンとズームピンチしてドラッグします。

問題:

特に相互作用絶えず再描画トリガーの過程で小さなプログラムの限定キャンバス性能は、深刻なカトンを引き起こす可能性があります。

基本的に

最適化を考慮せずに、私たちが描くと相互作用する方法について話しましょう。

データフォーマット

スタイルの要素の座標を含むデータで最初に見て、各要素が独立してデータサービス戻り、

// 线路数据
lineData = { path: [x0, y0, x1, y1, ...], strokeColor, strokeWidth }

// 站点数据:分为普通站点和换乘站点
// 普通站点绘制简单圆形
stationData = { x, y, r, fillColor, strokeColor, strokeWidth }
// 换乘站点绘制换乘图标(png图片)
stationData_transfer = { x, y, width, height }

// 线路名称
lineNameData = { text, x, y, fillColor }

// 站点名称
stationNameData = { text, x, y }

描画API

描画要素を描画する際の描画と充填、コンテキスト要素タイプ設定のスタイルに応じて、アレイを横断します。インタフェースリファレンス:https://developers.weixin.qq.com/miniprogram/dev/api/canvas/CanvasContext.html

•設定スタイル:setStrokeStyle、setFillStyle、setLineWidth、setFontSize

•ルートを描く:moveToは、のlineTo、ストローク

•サイトを描く:moveToは、アーク、ストローク、塗りつぶし

•絵描く:drawImageメソッドを

•ドローテキスト:fillText

インタラクティブ達成

次のように相互作用の主要な手順は次のとおりです。

•bindtouchstart、bindtouchmove、bindtouchendユーザーのドラッグによって達成し、リスナーをズームピンチ、ドラッグ変位ベクトル、スケーリング、トリガ再描画を取得します。

規模別および座標が描く•ときの処理データを使用せずにズームやパンを実装翻訳

亀高速移動、非常に大きな画像遅れ:結果は、最終的に以下の通りである、長さ42.82ms、実機(IOS)平均レンダリング検証を得ました。

最適化

:完全に気づいていないキャンバスの最適化の学生が見てとることができキャンバスの最適化を

キャンバスの状態が不要避けるために変更し
、参照(機能紙)キャンバスのベストプラクティスを、描画コンテキストは、ステートマシンで、状態オーバーヘッドの一定の変化があります。キャンバスの状態は、主にここで変更する変更strokeStyle、のfillStyleや他のスタイルを指します。

それのこの部分のコストを削減するには?私たちは一緒に1回の描画で同じスタイル要素を作ってみることができます。データを見るには、スタイルの多くの要素が同じサイトで、あなたがデータ集計、データパターンに同じデータの組み合わせを描画する前に、最初に行うことができますことを示唆しています。

function mergeStationData(mapStation) {
  let mergedData = {}

  mapStation.forEach(station => {
    let coord = `${station.x},${station.y},${station.r}`
    let stationStyle = `${station.fillColor}|${station.strokeColor}|${station.strokeWidth}`

    if (mergedData[stationStyle]) {
      mergedData[stationStyle].push(coord)
    } else {
      mergedData[stationStyle] = [coord]
    }
  })

  return mergedData
}

重合した後、329合併サイトのデータ24、変更の冗長ステータスにコストの効率90%の削減。少し速くいくつかの動きが、画像はまだ高遅延である:平均は長い20.48ms、実機検証をレンダリングするためにドロップされたとき、それの後にテストを変更します。

合成されたデータは、このシナリオが別の腺、腺のサイトではありません、注意を払う必要があり、順番がある場合、その後、合併時にのみ隣接し、同じスタイルデータマージすることができます。

ドローを減らすことでした

•は、スクリーニングに加えてのビジョンを描かれた:ユーザーが画像を拡大する際、実際には、ほとんどが引き分けに消えてしまった不要なオーバーヘッドを保存することができます視界外の要素を描画を避けるために、視野外でした。最初のプロセスがない場合、それは、より複雑であり、線分はそのまた、視野に計算することができ、要素は、ポイントサイト、サイト名、ライン名が点要素として扱うことができるの視野の外にあるかを決定することは比較的容易です。ふるい17.02msの平均長をレンダリングし、それの後に描かれたテストの視界の外を取り除くために、実機検証:上記と同じで、あまり変化はありません。

•画面に加えて、オブジェクトを描画するには小さすぎる:ユーザーが縮小画像であるとき、原因サイズにテキストやサイトが小さすぎると、非常にユーザーエクスペリエンスに影響を与えずに、クリアすることはできません直接削除考えることができます。比率が30%未満、9.68msに低減22.12ms、よりレベルのレンダリングの持続時間である場合、試験によれば、最終的な決定は、テキストと表示部位を除去します。

再描画頻度を減らします

タスクをレンダリングontouchmoveたびにキュー非同期に追加されるので、平均長さが、はるかに低いレンダリング、依然として高いインタラクティブShique遅延してきたが、イベントは、周波数を行うことが可能な第2の描画当たりの回数をはるかに超えるされるトリガ、レンダリングタスクの深刻なバックログが生じ、遅れに進みます。requestAnimationFrameのは、一般的にPC側には小さなプログラムが存在しない、この問題を解決するために使用されるが、自分自身の参照達成することができますrequestAnimationFrameのを用いたマイクロ手紙アプレットを

const requestAnimationFrame = function (callback, lastTime) {
  var lastTime;
  if (typeof lastTime === 'undefined') {
    lastTime = 0
  }
  var currTime = new Date().getTime();
  var timeToCall = Math.max(0, 30 - (currTime - lastTime));
  lastTime = currTime + timeToCall;
  var id = setTimeout(function () {
    callback(lastTime);
  }, timeToCall);
  return id;
};

const cancelAnimationFrame = function (id) {
  clearTimeout(id);
};

PCの我々は、一般に、約16msの中で距離制御をレンダリングしますが、小さなプログラムで考慮に性能限界を取る側、および各モデルの携帯端末の性能はので、ここで我々は30FPSの周りにいくつかの領域、制御30msの、対応を残して、異なります。

しかし、あなたは、個別に開く最初の相互作用時にアニメーションを停止し、ontouchend ontouchstart終了することができますので、停止状態で不要なオーバーヘッドが発生しますサイクルを呼び出すされている場合:

animate(lastTime) {
  this.animateId = requestAnimationFrame((t) => {
    this.render()
    this.animate(t)
  }, lastTime)
},

stop() {
  cancelAnimationFrame(this.animateId)
}

テストに実機を変更した後:画面比較処理、若干ケイトン、それが遅れることはありません。

追加

本実施例ので、ズームとパンの状態は絶対的状態、スケールに保存され、そして保存および復元を併用することに翻訳され、のsetTransformは、マトリックスをリセットするために直接使用することができます。理論的にはこれは、お金を節約することができるはずですが、どのような効果は実際のテスト、18.12msでレンダリング平均長をしました。この問題を検討する必要があります。
setDataメソッドを使用してアプレット避けてページを再描画を避けるために、独立したデータをレンダリングするインターフェースセーブ。

最適化の結果

上記の最適化の後、およそ17msに42ダウンから長い時間をレンダリング、アンドリュースモデルの実機検証は、一般的に非常に、非常に良い経験を滑らかに、iOS搭載モデルわずかカトンを、長ケイトンが明らかになったの使用と、後者が可能で綿密な研究メモリ管理の問題があります。

おすすめ

転載: www.cnblogs.com/Yi-Xiu/p/12030352.html