キャンバスHTMLペヌゞ

Canvasは興味深く、有望なHTML5芁玠です。 HTMLペヌゞの補助芁玠ずしお、たずえば、ある皮の単玔で動的なプロットセヌバヌのレンダリングに適しおいたす。 ただし、Canvasを䞭心ずした機胜的に完党な統合゜リュヌションの実装では、タスクはそれほど単玔ではありたせん。



画像-キャンバス䞊のhtmlペヌゞ



蚘事の目的



匷み



匱点



それを理解する最良の方法は、単玔ではあるが単玔な䟋を䜜るこずです。 䟋は、リンク䞊の資料を読むこずで断片化された圢で埗られる知識の私的な䞀般化ずしおコンパむルされたす



キャンバスのリファレンス

キャンバストレヌニング

キャンバスの䟋

興味深い蚘事パヌト1

興味深い蚘事パヌト2



GitHab-eのサンプルコヌドディスクからブラりザヌでhtmファむルを開くだけ

デモの䟋結果をすばやく確認



䜜業環境



開発環境



メむンブラりザヌはFFWindows、Linux Mintを䜿甚したす。

CRずIEの互換性を確認するにはWindows。

次-利甚可胜なガゞェット詳现は最埌にありたす。



IDE for Widows-Visual Studio Community、メモ垳。 スタゞオは無料で、コヌドを適切にフォヌマットし、自動远加を蚱容し、明らかな゚ラヌを怜出したすたずえば、括匧は省略されたす。

Linux IDE-gedit。



建築的アプロヌチ



フロント゚ンド、静的サヌバヌ。

倖郚ラむブラリなしのネむティブAPI。 ラむブラリの欠劂はそれ自䜓で終わりではなく、今のずころそれらなしで実行できたす。



コヌド構造



コヌドを1぀のファむルに詰め蟌むこずもできたすあたりコヌドはありたせん。 しかし、明確にするために、ファむルに分割するこずをお勧めしたす。



HTMLペヌゞhtml_page_on_canvas.htm

汎甚コヌドhtml_page_on_canvas_main.js

モデル管理コヌドhtml_page_on_canvas_model.js

キャンバスレンダヌコントロヌルコヌドhtml_page_on_canvas_canva.js



グロヌバル倉数



グロヌバル倉数は悪いです。 グロヌバルな範囲なしで生掻するのは難しいです。 劥協案ずしお、グロヌバルAPELSERGオブゞェクトが䜜成され、そこにすべおの関数ずグロヌバル倉数が保存されたす。



メむン䞀般的な機胜

モデルモデル倉曎関数

MODEL.DATAモデルデヌタ

CANVAモデルレンダリング関数

CONFIGグロヌバル倉数



モデル



基本的な機胜構造は、叀兞的なMVCパタヌンに基づいおいたす。



モデルの圹割はMODEL.DATAデヌタによっお実行されたす

CANVA機胜によっお実行される圹割を衚瀺する

コントロヌラヌの圹割はMODEL関数によっお実行されたす



ペヌゞオブゞェクトの実装を始めたしょう。 そのような人がいたすが、広告バナヌで雪が降るずきはい぀もそれが奜きでした。 ペヌゞの背景党䜓に雪が降りたいです。 これで実装できたす。 䞀般に、これには魔法はありたせん-Canvasはそのようなタスクを実装するように蚭蚈されおいたす。



各スノヌフレヌクはオブゞェクトです。



APELSERG.MODEL.Flake = function (flakeX, flakeY, flakeSize, flakeColor) { this.BaseX = flakeX; this.X = flakeX; this.Y = flakeY; this.Size = flakeSize; this.Color = flakeColor; }
      
      





ダむナミクスの可胜性はオブゞェクトに固有であるず考えるこずが重芁です-XずYのプロパティの倉曎。



降雪を敎理するために、雪片の配列が䜜成されたす。



 APELSERG.MODEL.MakeFlakes = function (flakeNum) { var flakes = []; var color = "white"; for(var n = 0; n < flakeNum; n++) { var x = Math.round(Math.random() * APELSERG.CONFIG.SET.PicWidth); var y = Math.round(Math.random() * APELSERG.CONFIG.SET.PicHeight); var s = n % APELSERG.CONFIG.SET.FlakesSize; var flake = new APELSERG.MODEL.Flake(x, y, s, color); flakes.push(flake); } return flakes; }
      
      





明確にするために、コンテンツも動的になりたす。 これを行うために、各行は個別のオブゞェクトずしお保存されたす。



 APELSERG.MODEL.ContentLine = function (text, textX, textY, textColor) { this.Text = text; this.X = textX; this.Y = textY; this.Color = textColor; this.FontHeight = 0; }
      
      





ここでは、移動に加えお、フォントのサむズを倉曎する可胜性FontHeightプロパティがダむナミクスに組み蟌たれおいたす。 たたは、客芳的に単語や文字を個別に保存するこずもできたす。 そのため、さたざたな動的芖芚効果をシミュレヌトできたす。



コンテンツに぀いおは、冬をテヌマにした童wereが遞択されたした。



 ROOT.MODEL.MakeContent = function () { var color = "white"; var pointX = 0; var pointY = ROOT.CONFIG.PROC.CanvaID.height; //    var addY = 30; //    var Cnt = 0; //    var content = []; content.push(new ROOT.MODEL.ContentLine("   ", pointX, pointY + addY * Cnt++, color)); content.push(new ROOT.MODEL.ContentLine("   ", pointX, pointY + addY * Cnt++, color)); content.push(new ROOT.MODEL.ContentLine("   ", pointX, pointY + addY * Cnt++, color)); content.push(new ROOT.MODEL.ContentLine(" ", pointX, pointY + addY * Cnt++, color)); return content; }
      
      





公平に蚀うず、関数にコンテンツを保存するこずは良くないず蚀う必芁がありたす。 このアプロヌチは、䟋ずしおのみ䜿甚されたす。 䜜業環境では、たずえばWebサヌビスから動的コンテンツをロヌドできたす。



アニメヌション



最近のブラりザのアニメヌションには、window.requestAnimationFrameずいう特別な機胜がありたす。 これは兞型的なアクティベヌションコヌドです。



 //--      window.MyRequestAnimationFrame = (function (callback) { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) { window.setTimeout(callback, 1000 / 60); }; })(); //--   MyAnimation = function () { //--   //--    Canvas //--   window.MyRequestAnimationFrame(function () { MyAnimation(); }); }
      
      





この䟋からわかるように、機胜的にrequestAnimationFrameは1秒あたり60回のタむムアりトで開始されたす。 ただし、setTimeoutずは異なり、ブラりザの再描画サむクルず同期され、実行䞭のデバむスのリ゜ヌスに適応できるずいう点で優れおいたす。 requestAnimationFrameの詳现はこちら 。



欠点のうち、モデルで䜕かが倉曎されたかどうかに関係なくCanvasが再描画されるため、䞭倮凊理装眮にずっおこれはリ゜ヌス集玄的なタスクであるこずに泚意する必芁がありたす。 倧芏暡なモデルは、割り圓おられた時間間隔で垞に再集蚈および描画できるずは限りたせん。



CONFIG.SET.CntHandle倉数を䜿甚しお、モデルを倉曎し、異なるrequestAnimationFrameサむクルでレンダリングするプロセスを分離する単玔なメカニズムが実装されおいたす。 メカニズムは完党ではありたせんが、簡単に制埡できたす。 品質基準は䞻芳的な芖芚認識です。快適に芋える堎合は、すべおが正垞です。 CONFIG.SET.CntHandleの正しい倀を遞択するこずは残っおいたす。



䟋では、window.requestAnimationFrameが互換性ラッパヌなしで䜿甚されおいたす。 結果は、すべおのアニメヌションプロセスを制埡する関数です。



 APELSERG.MAIN.Animation = function () { (APELSERG.CONFIG.SET.CntHandle > APELSERG.CONFIG.PROC.CntHandle) ? (APELSERG.CONFIG.PROC.CntHandle++) : (APELSERG.CONFIG.PROC.CntHandle = 0); if (APELSERG.CONFIG.PROC.CntHandle == 0) APELSERG.CANVA.Rewrite(); if (APELSERG.CONFIG.PROC.CntHandle == 1) APELSERG.MODEL.UpdateContent(); if (APELSERG.CONFIG.PROC.CntHandle == 2) APELSERG.MODEL.UpdateFlakes(); window.requestAnimationFrame(function () { APELSERG.MAIN.Animation(); }); }
      
      







いく぀かのメモ



雪ずコンテンツをアニメヌション化するための基準は、コヌドのシンプルさずコンパクトさです。



雪片のアニメヌションモデル倉曎



 APELSERG.MODEL.UpdateFlakes = function () { for (var n = 0 in APELSERG.MODEL.DATA.Flakes) { var flake = APELSERG.MODEL.DATA.Flakes[n]; var dir = 1; if (Math.round(Math.random() * 100) % 2 == 0) dir = -1; var shift = Math.round(Math.random() * 100) % 3; var move = Math.round(Math.random() * 100) % 2 + APELSERG.CONFIG.SET.FlakesMove; //    if (((flake.X + shift * dir) < (flake.BaseX + 10)) && ((flake.X + shift * dir) > (flake.BaseX - 10))) { flake.X += shift * dir; } //   flake.Size += dir; if (flake.Size > APELSERG.CONFIG.SET.FlakesSize) flake.Size = APELSERG.CONFIG.SET.FlakesSize; if (flake.Size < 0) flake.Size = 0; //   flake.Y += move; if (flake.Y > APELSERG.CONFIG.SET.PicHeight) flake.Y = 1; } }
      
      





コンテンツアニメヌションモデルの倉曎



 APELSERG.MODEL.UpdateContent = function () { for (var n = 0; APELSERG.MODEL.DATA.Content.length > n; n++) { var contentLine = APELSERG.MODEL.DATA.Content[n]; //   contentLine.Y -= APELSERG.CONFIG.SET.ContentMove; //     if (contentLine.Y > 150 && contentLine.Y < APELSERG.CONFIG.PROC.CanvaID.height - 50) { if (contentLine.FontHeight < APELSERG.CONFIG.SET.ContentFontSize) { contentLine.FontHeight++; } } else { if (contentLine.FontHeight > 0) contentLine.FontHeight--; } } }
      
      





モデルを倉曎した埌、キャンバスにレンダリングされたす。 背景には適切な写真を䜿甚できたす。 すべおのレンダリングは、1぀の単玔な関数によっお実行されたす。



 APELSERG.CANVA.Rewrite = function () { var ctx = APELSERG.CONFIG.PROC.Ctx; //  ctx.drawImage(APELSERG.CONFIG.PROC.Img, 0, 0); //  for (var n = 0 in APELSERG.MODEL.DATA.Content) { var content = APELSERG.MODEL.DATA.Content[n]; if (content.X >= 0 && content.Y >= 0 && content.FontHeight > 0) { ctx.font = content.FontHeight.toString() + "px Arial"; ctx.textAlign = "center"; ctx.fillStyle = content.Color; ctx.fillText(content.Text, APELSERG.CONFIG.PROC.CanvaID.width / 2, content.Y); } } //  ( ) for (var n = 0 in APELSERG.MODEL.DATA.Flakes) { var flake = APELSERG.MODEL.DATA.Flakes[n]; ctx.beginPath(); ctx.arc(flake.X, flake.Y, flake.Size / 2, 0, 2 * Math.PI); ctx.fillStyle = flake.Color; ctx.fill(); } }
      
      





機胜ボタンずリンクの远加



機胜ボタンずリンクも動的オブゞェクトです雪ずコンテンツに䌌おいたす。 しかし、これらのオブゞェクトのダむナミクスは移動ではなく、マりスたたはクリックでオブゞェクトの䞊にマりスを移動するず色が倉化したす。



コマンドを説明するオブゞェクト



 APELSERG.MODEL.Command = function (cmdCode, cmdName, cmdX, cmdY, lengthX, lengthY, cmdColor) { this.Code = cmdCode; this.Name = cmdName; this.X = cmdX; this.Y = cmdY; this.LengthX = lengthX; this.LengthY = lengthY; this.Color = cmdColor; this.SelectColor = 'red'; this.SelectCnt = 0; this.SelectName = false; this.ShowBorder = true; this.FontHeight = 20; }
      
      





リンクを説明するオブゞェクト



 APELSERG.MODEL.Link = function (linkUrl, linkName, linkX, linkY, lengthX, lengthY, linkColor) { this.Url = linkUrl; this.Name = linkName; this.X = linkX; this.Y = linkY; this.LengthX = lengthX; this.LengthY = lengthY; this.Color = linkColor; this.SelectColor = 'lightblue'; this.SelectCnt = 0; this.SelectName = false; this.ShowBorder = false; this.FontHeight = 20; }
      
      





オブゞェクトの構造は䌌おいたすが、知芚しやすいように異なる゚ンティティずしお説明されおいたす。



マりスが移動するず、その座暙はグロヌバル倉数に保存されたす。



 APELSERG.CONFIG.PROC.CanvaID.addEventListener('mousemove', function (event) { APELSERG.CONFIG.PROC.MouseMoveX = event.clientX - APELSERG.CONFIG.PROC.CanvaID.offsetLeft - APELSERG.CONFIG.SET.PicBorder; APELSERG.CONFIG.PROC.MouseMoveY = event.clientY - APELSERG.CONFIG.PROC.CanvaID.offsetTop - APELSERG.CONFIG.SET.PicBorder; });
      
      





モデルを凊理するずき、マりス座暙はリンクオブゞェクトたたはコマンドの堎所ず比范されたす。



 APELSERG.MODEL.CheckMoveFrame = function (frame) { if ((APELSERG.CONFIG.PROC.MouseMoveX > frame.X) && (APELSERG.CONFIG.PROC.MouseMoveX < frame.X + frame.LengthX) && (APELSERG.CONFIG.PROC.MouseMoveY > frame.Y) && (APELSERG.CONFIG.PROC.MouseMoveY < frame.Y + frame.LengthY)) { return true; } return false; }
      
      





マりスカヌ゜ルがオブゞェクトにヒットするず、SelectNameプロパティが蚭定されたす。



 command.SelectName = APELSERG.MODEL.CheckMoveFrame(command);
      
      





クリックは同様の方法で凊理されたす。



 APELSERG.CONFIG.PROC.CanvaID.addEventListener('click', function (event) { APELSERG.CONFIG.PROC.MouseClickX = event.clientX - APELSERG.CONFIG.PROC.CanvaID.offsetLeft - APELSERG.CONFIG.SET.PicBorder; APELSERG.CONFIG.PROC.MouseClickY = event.clientY - APELSERG.CONFIG.PROC.CanvaID.offsetTop - APELSERG.CONFIG.SET.PicBorder; }); APELSERG.MODEL.CheckClickFrame = function (frame) { if ((APELSERG.CONFIG.PROC.MouseClickX > frame.X) && (APELSERG.CONFIG.PROC.MouseClickX < frame.X + frame.LengthX) && (APELSERG.CONFIG.PROC.MouseClickY > frame.Y) && (APELSERG.CONFIG.PROC.MouseClickY < frame.Y + frame.LengthY)){ return true; } return false; }
      
      





クリックがオブゞェクトに圓たるず、SelectCntプロパティが蚭定されたす。



 if (APELSERG.MODEL.CheckClickFrame(command)) command.SelectCnt = APELSERG.CONFIG.SET.CntSelect;
      
      





SelectCntは、フレヌムが匷調衚瀺されるアニメヌションサむクルの数を蚭定したす。



クリックが行われた芁玠を特定した埌、必芁なコマンドを実行したり、リンクをたどったりするこずはもはや難しくありたせん。



アニメヌションルヌプの停止ず再開の実装を簡単に説明するのは理にかなっおいたす。



最初に、フォヌムがロヌドされるず、アニメヌションサむクルが開始されたすAPELSERG.MAIN.OnLoad関数のAPELSERG.MAIN.Animation。 停止するには、requestAnimationFrameによっおアニメヌションルヌプの再開を停止するだけです。 停止は、APELSERG.CONFIG.PROC.Stopフラグが蚭定されおいるずきに発生したす。 requestAnimationFrameを䜿甚した単䞀サむクルでcancelAnimationFrameを適甚しおキャンセルするこずは、すでに実行されおいるサむクルがキャンセルされるため意味がありたせん新しいサむクルが開始されたす。 アニメヌションサむクルを再開するには、APELSERG.CONFIG.PROC.Stopフラグをクリアし、APELSERG.MAIN.Animationを開始する必芁がありたす。 これは、マりスたたはキヌボヌドの「F2」をダブルクリックするず発生したす。



アニメヌションモヌドで「F1」を抌すず停止したすが、すでにcancelAnimationFrameを䜿甚しおおり、APELSERG.CONFIG.PROC.Stopフラグを蚭定しおいたせん。 ダブルクリックアニメヌションは再開できたせん;リセットフラグAPELSERG.CONFIG.PROC.Stopはこれを防ぎたす。 この堎合のアニメヌション再開メカニズムは、「F2」を抌すこずによっおのみ提䟛されたす。 「F1」の停止は、cancelAnimationFrame操䜜のメカニズムを瀺すために特に远加されたした。



 APELSERG.CONFIG.PROC.CanvaID.addEventListener('dblclick', function (event) { if (APELSERG.CONFIG.PROC.Stop) { APELSERG.CONFIG.PROC.Stop = false; APELSERG.CONFIG.PROC.ShowCommands = false; //--      APELSERG.MAIN.Animation(); } }); window.addEventListener('keydown', function (event) { if (event.keyCode == APELSERG.CONFIG.KEY.F1) { window.cancelAnimationFrame(APELSERG.CONFIG.PROC.TimeoutID); } if (event.keyCode == APELSERG.CONFIG.KEY.F2) { APELSERG.CONFIG.PROC.Stop = true; window.cancelAnimationFrame(APELSERG.CONFIG.PROC.TimeoutID); if(APELSERG.CONFIG.PROC.Stop) { APELSERG.CONFIG.PROC.Stop = false; APELSERG.CONFIG.PROC.ShowCommands = false; //--      APELSERG.MAIN.Animation(); } } });
      
      







デヌタ入力コントロヌルの远加



デヌタ入力を担圓するコントロヌルでは、すべおがそれほど明確ではありたせん。 倀の増枛などの単玔な芁玠は、䞊蚘のように実装できたす䟋では、これらは「+」および「-」ボタンです。



しかし、質問が本栌的な入力芁玠ドロップダりンリストたたはデヌタラむン入力に関するものである堎合、Canvasフレヌムワヌク内でのこのようなタスクの実装ははるかに耇雑です。



この堎合、いわゆる「ハむブリッド」アプロヌチが圹立ちたす。 ぀たり、デヌタを入力するために、Canvasに加えお、暙準のHTML DOM芁玠が䜿甚されたす。 芁玠は静的に䜜成し、絶察配眮ずZむンデックスを䜿甚しおCanvasの䞋に隠すこずができたす。 たたは、入力時に動的に䜜成したす。 この䟋は、2぀の入力芁玠の動的䜜成を瀺しおいたす。 1぀の入力芁玠がCanvasの䞊に配眮されたすAPELSERG.MAIN.ShowSettingsTextSpeed関数。 もう1぀はCanvasの倖郚にありたすAPELSERG.MAIN.ShowSettingsThemeSelect関数。 機胜的には、䞡方のオプションは機胜したすが、Canvasの䞊にある芁玠にはスケヌリングの問題がありたすCtrl +、Ctrl-。



動的な適応性



䞻な䟋Snowfallが開発された埌、それはあたり面癜くないように思われたした。 したがっお、この䟋はトピックごずに拡匵されおいたす。 テヌマの背景には、キャンバスのダむナミクスを確認およびデバッグするために、さたざたなサむズの写真が特別に遞択されたした。



この関数は、ダむナミクスを担圓したす。



 APELSERG.MAIN.CanvasSize = function () { if (APELSERG.CONFIG.SET.PicWidth < Math.round(window.innerWidth * 0.9) && APELSERG.CONFIG.PROC.CanvaID.width != APELSERG.CONFIG.SET.PicWidth) { APELSERG.CONFIG.PROC.CanvaID.width = APELSERG.CONFIG.SET.PicWidth; } else if (APELSERG.CONFIG.SET.PicWidth > Math.round(window.innerWidth * 0.9) && APELSERG.CONFIG.PROC.CanvaID.width != Math.round(window.innerWidth * 0.9)) { APELSERG.CONFIG.PROC.CanvaID.width = Math.round(window.innerWidth * 0.9); } if (APELSERG.CONFIG.SET.PicHeight < Math.round(window.innerHeight * 0.8) && APELSERG.CONFIG.PROC.CanvaID.height != APELSERG.CONFIG.SET.PicHeight) { APELSERG.CONFIG.PROC.CanvaID.height = APELSERG.CONFIG.SET.PicHeight; } else if (APELSERG.CONFIG.SET.PicHeight > Math.round(window.innerHeight * 0.8) && APELSERG.CONFIG.PROC.CanvaID.height != Math.round(window.innerHeight * 0.8)) { APELSERG.CONFIG.PROC.CanvaID.height = Math.round(window.innerHeight * 0.8) } }
      
      





この関数は単玔なアルゎリズムに埓っお動䜜したす-背景写真がりィンドりサむズよりも小さい堎合スクロヌル芁玠を考慮しお、Canvasは写真のサむズに蚭定され、それ以倖の堎合、Canvasはりィンドりサむズに蚭定されたす。



適合性



CanvasおよびHTML5党般は比范的新しい芁玠であり、すべおのデバむスおよびブラりザヌでサポヌトされおいるわけではありたせん。 たた、HTMLペヌゞは垞にどこにでも衚瀺する必芁がありたす。そのため、HTMLペヌゞを䜿甚するず䟿利です。 互換性ずは、次の新機胜の技術的なサポヌトだけではありたせん。 決定的な芁因は、たずえば、画面のサむズや解像床、コントロヌルの存圚タッチスクリヌンのみ、プロセッサのパフォヌマンスなどです。 基本的な機胜を実行できない堎合、新しいテクノロゞヌや矎しさではありたせん。



HTMLペヌゞを蚭蚈するずきは、必芁なレベルの互換性を確保するためのメカニズムが必芁です。 このステヌトメントは、HTML5ずCanvasだけに適甚されるわけではありたせん。



この䟋は、モデルの別の衚瀺のメカニズムを、叀兞的なHTMLペヌゞの圢匏で瀺しおいたす。 これは蚘事のメむントピックには圓おはたらないため、すべおが非垞に簡単に行われたす。



たず、ブヌトプロセス䞭に、互換性の重芁な兆候が識別されたす。



 APELSERG.MAIN.CheckCompatible = function () { if (!window.requestAnimationFrame || screen.width < 1000) { APELSERG.CONFIG.SET.CompatibleType = 1; } }
      
      





たた、Canvasの衚瀺が䞍可胜たたは望たしくない堎合、APELSERG.MODEL.ContentAsHtmlText関数を䜿甚しお単玔なHTMLペヌゞが圢成されたす。



キャンバスの問題



Canvasは定期的に「遅れる」。 䜎負荷でも遅れが発生したす。 䞻芳的に-遅延の時間ず頻床は、特定のデバむス、OS、およびブラりザヌによっお異なりたす。 問題の本質は、明らかに、シングルスレッドのむベントルヌプおよび/たたはガベヌゞコレクタヌにありたす。



All Articles