ブラウザベースの宇宙飛行シミュレータ用の電力制御ウィジェットを作成した方法

今日、私は自分用に小さなコードスニペットを作成し、そのコンテンツと作成の歴史をコミュニティと共有することにしました。



少なくとも私が必要なものに似たものを見つけるためにかなり長い時間インターネットを検索しましたが、インターネットはまだそのような問題に遭遇していないようです。 おそらく誰も必要ありません。



最初に、私が本当に欲しかったことを言います。

スライダーが必要です-進行状況バーと組み合わされたボリュームコントロールのアナログです。 この電力の同時表示と組み合わされた、何かの電力制御コンポーネントの一種。 電力が設定された制限の100%を超える場合があります。このレベルを表示し、パーセンテージを正しく計算する必要があります。 時々、電力がゼロ以下になることがあります(可能かどうかはわかりませんが、念のため、そのような機会を提供しました)。このレベルも表示する必要があります。 さらに、調整するデバイスは不活性ではなく、値を設定した速度で加速する場合があります。 飛行機のアフターバーナーボタンを押した場合、しばらくするとエンジンはアフターバーナーモードになります。 つまり、プログレスバーの値を個別に設定し、スライダースライダーの現在の値を個別に取得設定する必要があります。



たぶん私はイチジクの探求者ですが、最終的にはびっくりしました-私は自分で作ることにしました:

結果へのリンクがあり、猫の下にプロセスの説明があります



はじめに



まず、ウィジェットフレームを作成します。

var PowerControlWidget = function(settings){ this.container = settings.container || undefined ; this.canvas = document.createElement('CANVAS'); this.canvas.height = this.height; this.canvas.width = this.width; this.container.appendChild(this.canvas); this.ctx = this.canvas.getContext('2d'); // ---    this.set_value(0); this.redraw() }
      
      







すぐに予約します-jquery.jsおよびjqueryui.jsから最大限に独立したいので、このウィジェットをjQueryプラグインとして設計しませんでした。



イベント処理





ドラッグアンドドロップでは、すべてが一般的です。マウスダウンでは状態を保存し、マウスアップではリセットします。



 var self = this; this.canvas.addEventListener("mousedown", function(event){ self.mouse_down = true; self.value = event.offsetX; if(event.offsetX < self.padding_left_right){ self.value = self.padding_left_right; } if(event.offsetX > self._line_width - self.padding_left_right){ self.value = self._line_width - self.padding_left_right; } self._percent_value = self._get_percent(self.value); self.redraw(); self.onchange(self._percent_value, self.progress_value); }) this.canvas.addEventListener("mouseup", function(event){ self.mouse_down = false; self._percent_value = self._get_percent(self.value); self.redraw(); self.onchange(self._percent_value, self.progress_value); }) this.canvas.addEventListener("mousemove", function(event){ if (self.mouse_down){ self.value = event.offsetX; if(event.offsetX < self.padding_left_right){ self.value = self.padding_left_right; } if(event.offsetX > self._line_width - self.padding_left_right){ self.value = self._line_width - self.padding_left_right; } self._percent_value = self._get_percent(self.value); self.redraw(); self.onslide(self._percent_value, self.progress_value); } })
      
      







このキャンバスの適切な場所にのみ位置を設定する補助変数がかなりあります。 ウィジェットでは、その主要部分に加えて、正確な情報の出力(進行状況バーとスライダーの現在の値)を追加する必要もあります。 キャンバス内でこれを行うことにしましたが、ここではテキストの配置に関する非常に理解可能な問題に遭遇します。 テキスト出力-少し後で。



描画を開始





スライダーコントロール自体については、このキャンバスから領域を選択します。 制限があります:





このようなもの:



 this._draw_border = function(){ var b = this.padding_top_bottom; //     . var a = this.padding_left_right; var w = this._line_width - ( 2 * a ); var h = this.height - (2*b); this.ctx.beginPath(); this.ctx.moveTo(a,b); this.ctx.bezierCurveTo(a+(w/2), b, w-(w/2)+a, b, a+w, b ); this.ctx.bezierCurveTo(a+w+a, b, a+a+w, b+h, a+w, b+h ); this.ctx.bezierCurveTo( w/2+a, b+h, w/2+a,b+h, a, b+h); this.ctx.bezierCurveTo( 0, b+h, 0,b, a,b); this.ctx.closePath(); this.ctx.strokeStyle = this.border_color; this.ctx.stroke(); //     };
      
      





ベジェ曲線の入力パラメーターに3つのポイントが含まれていることを思い出してください。 4番目のポイントは現在のポイントです。moveToを使用してそこに移動する必要があります。

そのような曲線を描く一般的な意味:



画像



丸みを帯びた美しいフレームになります。



さあ、魔法を始めましょう:

否定的な関心のあるゾーンとアフターバーナーのゾーンを描くために、クリップを使用します。 クリップは単純です。まず、描画が行われる内部にパスを作成し、次に1つだけの違いを付けて境界線の描画を繰り返します。このパスを循環させず、内部から目的の色で塗りつぶします。 見た目はシンプルで、複雑でもないようです。



最初に、それをどこに描くかを定義し、それはすべてゼロにすることです-別の色で描きます。



  var zero = this._get_x(0); //        
      
      





描画領域を作成する



  this.ctx.beginPath(); this.ctx.rect(0,0, zero, this.height); this.ctx.clip();
      
      







そして、同じベジェを目的の色で塗りつぶします。



  this.ctx.beginPath(); this.ctx.bezierCurveTo(a+(w/2), b, w-(w/2)+a, b, a+w, b ); this.ctx.bezierCurveTo(a+w+a, b, a+a+w, b+h, a+w, b+h ); this.ctx.bezierCurveTo( w/2+a, b+h, w/2+a,b+h, a, b+h); this.ctx.bezierCurveTo( 0, b+h, 0,b, a,b); this.ctx.fillStyle = this.below_z_color; this.ctx.fill(); this.ctx.closePath(); this.ctx.restore();
      
      







類推により、100%を超える領域で行動します。



コンピューティングについて少し





ウィジェットに値を設定して取得し、マウスカーソルの座標をパーセンテージに変換したり、その逆を行う必要があります。

このために、2つの非常に単純な関数を作成しました。

  this._get_percent = function(x){ var a = this.padding_left_right; //     var w = this._line_width - (2*a); //   return ((x - a) * this._range/ w)+this.starting_percent ; //      ,        ,        . }; this._get_x = function(p){ var a = this.padding_left_right; var w = this._line_width - (2*a); return a+ (p - this.starting_percent) * w / this._range; //  };
      
      







さて、テキストの描画について少し





視覚的かつ正確にしたいですか? お願いしますが、その後はテキストデータなしではできません。

インジケーターラインの右側にテキストを描画します。 別々に、スライダーの状態、プログレスバーを別々に描画します。 場所を試してみることができると思いますが、今のところは、やってみましょう。



まず、パーセンテージを表示し、内部での実装方法ではなく、100を掛けます。

  var val = this._percent_value * 100 var int = Math.floor(val); var frac = Math.floor((val - int)*100);
      
      





つまり、彼らは全体、個別の小数部分を別々に受け取りました。 さまざまなサイズで描画しますが、最初に一般的にどのフォントが適しているかを計算します。 私は、いくつかの条件でうまく機能しない単純な依存関係を作成することにしました。

  var base_font_size = this.height - (this.padding_top_bottom*2) ; //     var add_font_size = Math.floor(base_font_size / 2); //     var base_marg = base_font_size *2; //  
      
      



さて、最後に-テキストをレンダリングするためのコード



  this.ctx.save() this.ctx.translate(this._line_width+ this.padding_top_bottom, this.height-this.padding_top_bottom); this.ctx.fillStyle = "#000"; this.ctx.font = base_font_size + "pt Arial"; this.ctx.textAlign = "end"; //     this.ctx.fillText("" + (int), base_marg, 0 ) this.ctx.textAlign = "center"; this.ctx.font = (base_font_size -2) + "pt Arial"; this.ctx.fillText(",", base_marg+1,0 ) this.ctx.font = add_font_size + "pt Arial"; this.ctx.textAlign = "start"; //     this.ctx.fillText("" + (frac), base_marg+3, 0 ) this.ctx.restore();
      
      





おわりに





準備完了インジケータを使用できます。 カラー設定は直接設定できます。 残念ながら、キャンバスを使用するという決定は、cssを使用してペイントする広い機会を私たちに残しませんでしたが、キャンバスには他の利点があります-特に、このインジケーターに追加のストロークとルーラーを掛けるために使用できます。 幸いなことに、キャンバスは非常に正確に幾何学図形を描くことができます。



掘り出したり使用したい人のために、リポジトリgithub.com/stavenko/power-control-widgetのアドレスを残します。 今日、このウィジェットは1つのブラウザ(Google Chrome)でしか動作しませんでしたが、他のブラウザでもイベントが正しく動作するかどうかは正直わかりません。 特に、イベントのoffsetX変数にマウス座標がない場合があります。 そして、それは非常に便利でした-座標を計算する必要はありません-それらはすぐにコンテナの左上を基準にして与えられます。



今日は以上です。



All Articles