整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          協作繪圖應用程序:在畫布上繪制形狀

          本文中,我們添加了在 HTML5 畫布上選擇顏色和繪制線條、圓形和正方形的功能!


          繪圖過程如何工作

          為了在畫布上繪圖,我們需要知道

          • 我們用什么顏色畫畫
          • 我們在畫什么形狀
          • 無論我們是繪制形狀的第一個點還是第二個點
          • 起點和終點在哪里

          將這些屬性添加到 Canvas 類的構造函數中:

          this.activeColor = '#000000';
          this.startPoint = null;
          this.endPoint = null;
          this.pointMode = 'start';
          this.mode = 'Line';

          所以我們默認畫一條黑線。 現在我們添加一個函數,讓我們改變我們繪制的顏色,作為 Canvas 類的一個方法:

          setColor(color) {
              this.activeColor = color;
              this.ctx.strokeStyle = color;
              this.ctx.fillStyle = color;
          }


          使調色板工作

          現在我們有了 setColor 方法,我們可以完成 Palette.draw() 方法。 我們將畫布對象添加為參數,并將 onclick 事件處理程序附加到每個調色板方塊:

          draw(canvas) {
              const row1 = document.querySelectorAll('#row-1 .palette');
              const row2 = document.querySelectorAll('#row-2 .palette');
              row1.forEach((div, idx) => {
                  div.style.backgroundColor = this.colors[0][idx];
                  div.onclick = e => canvas.setColor(this.colors[0][idx]);
              });
              row2.forEach((div, idx) => {
                  div.style.backgroundColor = this.colors[1][idx];
                  div.onclick = e => canvas.setColor(this.colors[1][idx]);
              });
          }

          由于我們在這里添加了它作為參數,所以我們需要在 index.html 文件中進行設置:

          palette.draw(canvas);


          選擇要繪制的形狀

          該項目允許繪制 5 種形狀:線條、空心圓、實心圓、空心矩形和實心矩形。 我們默認為一行。 為了改變形狀(代碼中稱為模式),首先將此方法添加到 Canvas :

          setMode(mode) {
              this.mode = mode;
          }

          然后在 HTML 中,在調色板下方,添加一行按鈕,讓我們選擇要繪制的形狀:

          <div id="draw-methods">
              <button onclick="canvas.setMode('Line')">Line</button>
              <button onclick="canvas.setMode('Hollow Rectangle')">Hollow Rectangle</button>
              <button onclick="canvas.setMode('Filled Rectangle')">Filled Rectangle</button>
              <button onclick="canvas.setMode('Hollow Circle')">Hollow Circle</button>
              <button onclick="canvas.setMode('Filled Circle')">Filled Circle</button>
          </div>


          處理要繪制的畫布上的點擊

          這是 Canvas 的 handleDraw 方法。 我會給你代碼然后解釋它在做什么,因為它比我們目前看到的更復雜。

          handleDraw(e) {
              const rect = this.canvas.getBoundingClientRect();
              const x = e.clientX - rect.left;
              const y = e.clientY - rect.top;    if (this.pointMode == 'start') {
                  this.startPoint = [x, y];
                  this.pointMode = 'end';
              } else if (this.pointMode == 'end') {
                  this.pointMode = 'start';
                  this.endPoint = [x, y];
                  // do the drawing
                  if (this.mode == 'Line') {
                      this.drawLine(this.startPoint, this.endPoint);
                  } else if (this.mode == 'Hollow Rectangle') {
                      this.drawHollowRectangle(this.startPoint, this.endPoint);
                  } else if (this.mode == 'Filled Rectangle') {
                      this.drawFilledRectangle(this.startPoint, this.endPoint);
                  } else if (this.mode == 'Hollow Circle') {
                      this.drawHollowCircle(this.startPoint, this.endPoint);
                  } else if (this.mode == 'Filled Circle') {
                      this.drawFilledCircle(this.startPoint, this.endPoint);
                  }
                  this.startPoint = null;
                  this.endPoint = null;
              }
          }

          前三行是關于確定用戶點擊的位置。您可能會認為,當您單擊畫布時,鼠標單擊事件只會包含您在畫布中單擊的位置的坐標。但這并不那么容易。你必須自己計算。

          getBoundingRectClient 返回值,例如畫布從左上角到左下角的距離。頁面的左上角是 (0, 0),越往右越往下,數值越大。 e是傳遞給函數的參數,代表鼠標點擊事件。 clientX 和 clientY 代表您在頁面上單擊的位置。減去畫布元素的偏移量可以得到鼠標在畫布元素中的位置。

          一旦我們有了點擊的位置,我們就需要知道這是第一次(“開始”)還是第二次(“結束”)點擊。每個形狀都是通過兩次點擊繪制的。對于一條線,只需選擇起點和終點。對于圓,選擇中心和邊緣。對于矩形,選擇兩個對角。如果是第一次單擊,則存儲單擊的位置,但不執行任何操作。如果是第二次單擊,則存儲其位置,繪制形狀,然后忘記位置。

          繪制形狀的方法可能看起來比實際復雜。對于 drawLine ,它很簡單:

          drawLine(startPoint, endPoint) {
              this.ctx.beginPath();
              this.ctx.moveTo(startPoint[0], startPoint[1]);
              this.ctx.lineTo(endPoint[0], endPoint[1]);
              this.ctx.stroke();
          }

          繪制空心和填充的矩形只需要計算兩個未點擊的點:

          drawHollowRectangle(startPoint, endPoint) {
              this.ctx.beginPath();
              this.ctx.strokeRect(
                  startPoint[0],
                  startPoint[1],
                  endPoint[0] - startPoint[0],
                  endPoint[1] - startPoint[1]
              );
          }drawFilledRectangle(startPoint, endPoint) {
              this.ctx.beginPath();
              this.ctx.fillRect(
                  startPoint[0],
                  startPoint[1],
                  endPoint[0] - startPoint[0],
                  endPoint[1] - startPoint[1]
              );
          }

          繪制圓的方法需要使用距離公式計算半徑,然后繪制 360 度圓弧。

          drawHollowCircle(startPoint, endPoint) {
              const x = startPoint[0] - endPoint[0];
              const y = startPoint[1] - endPoint[1];
              const radius = Math.sqrt(x * x + y * y);
              this.ctx.beginPath();
              this.ctx.arc(startPoint[0], startPoint[1], radius, 0, 2 * Math.PI, false);
              this.ctx.stroke();
          }drawFilledCircle(startPoint, endPoint) {
              const x = startPoint[0] - endPoint[0];
              const y = startPoint[1] - endPoint[1];
              const radius = Math.sqrt(x * x + y * y);
              this.ctx.beginPath();
              this.ctx.arc(startPoint[0], startPoint[1], radius, 0, 2 * Math.PI, false);
              this.ctx.fill();
          }


          附加 Canvas 事件偵聽器

          讓畫布真正響應被點擊需要將這兩行添加到構造函數中:

          this.handleDraw = this.handleDraw.bind(this);
          this.canvas.addEventListener('click', this.handleDraw);

          那些使用過 React 的人可能會認識到這種模式。 但為什么需要它? 它與事件偵聽器的工作方式有關。 如果沒有綁定,handleDraw 中的 this 上下文變量將指向被點擊的 HTML 元素。 在這種情況下,畫布元素。 但這意味著我們無法訪問具有我們需要的方法的 Canvas 對象。 通過使用 bind,我們強制 this 引用對象。


          把它們放在一起

          在此步驟中更改的文件此時應如下所示:

          <html>
          <head>
              <title>Collaborative Drawing App</title>
              <style type="text/css">
                  canvas {
                      border: 1px solid black;
                  }
                  .palette {
                      border: 1px solid black;
                      display: inline-block;
                      margin: 2px;
                      height: 25px;
                      width: 25px;
                  }
              </style>
          </head>
          <body>
              <h1>Collaborative Drawing App</h1>
              <div>
                  <canvas id="canvas" height="500px" width="500px"></canvas><br />
              </div>
              <div id="palette">
                  <div id="row-1">
                      <div class="palette"></div>
                      <div class="palette"></div>
                      <div class="palette"></div>
                      <div class="palette"></div>
                      <div class="palette"></div>
                      <div class="palette"></div>
                      <div class="palette"></div>
                      <div class="palette"></div>
                      <div class="palette"></div>
                      <div class="palette"></div>
                  </div>
                  <div id="row-2">
                      <div class="palette"></div>
                      <div class="palette"></div>
                      <div class="palette"></div>
                      <div class="palette"></div>
                      <div class="palette"></div>
                      <div class="palette"></div>
                      <div class="palette"></div>
                      <div class="palette"></div>
                      <div class="palette"></div>
                      <div class="palette"></div>
                  </div>
              </div> 
              <div id="draw-methods">
                  <button onclick="canvas.setMode('Line')">Line</button>
                  <button onclick="canvas.setMode('Hollow Rectangle')">Hollow Rectangle</button>
                  <button onclick="canvas.setMode('Filled Rectangle')">Filled Rectangle</button>
                  <button onclick="canvas.setMode('Hollow Circle')">Hollow Circle</button>
                  <button onclick="canvas.setMode('Filled Circle')">Filled Circle</button>
              </div>
              <script type="text/javascript" src="./script.js"></script>
              <script type="text/javascript">
                  const canvas = new Canvas();
                  const palette = new Palette();
                  palette.draw(canvas);
              </script>      
          </body>
          </html>


          class Canvas {
              constructor() {
                  this.canvas = document.querySelector('#canvas');
                  this.ctx = this.canvas.getContext('2d');
                  this.activeColor = '#000000';
                  this.startPoint = null;
                  this.endPoint = null;
                  this.pointMode = 'start';
                  this.mode = 'Line';  
                  this.handleDraw = this.handleDraw.bind(this);
                  this.canvas.addEventListener('click', this.handleDraw);              
              }
          
              setColor(color) {
                  this.activeColor = color;
                  this.ctx.strokeStyle = color;
                  this.ctx.fillStyle = color;
              }
          
              setMode(mode) {
                  this.mode = mode;
              }
          
              handleDraw(e) {
                  const rect = this.canvas.getBoundingClientRect();
                  const x = e.clientX - rect.left;
                  const y = e.clientY - rect.top;
                  if (this.pointMode == 'start') {
                      this.startPoint = [x, y];
                      this.pointMode = 'end';
                  } else if (this.pointMode == 'end') {
                      this.pointMode = 'start';
                      this.endPoint = [x, y];
                      // do the drawing
                      if (this.mode == 'Line') {
                          this.drawLine(this.startPoint, this.endPoint);
                      } else if (this.mode == 'Hollow Rectangle') {
                          this.drawHollowRectangle(this.startPoint, this.endPoint);
                      } else if (this.mode == 'Filled Rectangle') {
                          this.drawFilledRectangle(this.startPoint, this.endPoint);
                      } else if (this.mode == 'Hollow Circle') {
                          this.drawHollowCircle(this.startPoint, this.endPoint);
                      } else if (this.mode == 'Filled Circle') {
                          this.drawFilledCircle(this.startPoint, this.endPoint);
                      }
                      this.startPoint = null;
                      this.endPoint = null;
                  }
              }
              
              drawLine(startPoint, endPoint) {
                  this.ctx.beginPath();
                  this.ctx.moveTo(startPoint[0], startPoint[1]);
                  this.ctx.lineTo(endPoint[0], endPoint[1]);
                  this.ctx.stroke();
              }
          
              drawHollowRectangle(startPoint, endPoint) {
                  this.ctx.beginPath();
                  this.ctx.strokeRect(
                      startPoint[0],
                      startPoint[1],
                      endPoint[0] - startPoint[0],
                      endPoint[1] - startPoint[1]
                  );
              }
          
              drawFilledRectangle(startPoint, endPoint) {
                  this.ctx.beginPath();
                  this.ctx.fillRect(
                      startPoint[0],
                      startPoint[1],
                      endPoint[0] - startPoint[0],
                      endPoint[1] - startPoint[1]
                  );
              }
          
              drawHollowCircle(startPoint, endPoint) {
                  const x = startPoint[0] - endPoint[0];
                  const y = startPoint[1] - endPoint[1];
                  const radius = Math.sqrt(x * x + y * y);
                  this.ctx.beginPath();
                  this.ctx.arc(startPoint[0], startPoint[1], radius, 0, 2 * Math.PI, false);
                  this.ctx.stroke();
              }
          
              drawFilledCircle(startPoint, endPoint) {
                  const x = startPoint[0] - endPoint[0];
                  const y = startPoint[1] - endPoint[1];
                  const radius = Math.sqrt(x * x + y * y);
                  this.ctx.beginPath();
                  this.ctx.arc(startPoint[0], startPoint[1], radius, 0, 2 * Math.PI, false);
                  this.ctx.fill();
              }    
          }
          
          class Palette {
              constructor() {
                  this.colors = [
                      ['#000000', '#FFFFFF', '#7F7F7F', '#C3C3C3', '#880015', '#B97A57', '#ED1C24', '#FFAEC9', '#FF7F27', '#FFC90E'],
                      ['#FFF200', '#EFE4B0', '#22B14C', '#B5E61D', '#00A2E8', '#99D9EA', '#3F48CC', '#7092BE', '#A349A4', '#C8BFE7']
                  ];
              }
          
              draw(canvas) {
                  const row1 = document.querySelectorAll('#row-1 .palette');
                  const row2 = document.querySelectorAll('#row-2 .palette');
                  row1.forEach((div, idx) => {
                      div.style.backgroundColor = this.colors[0][idx];
                      div.onclick = e => canvas.setColor(this.colors[0][idx]);
                  });
                  row2.forEach((div, idx) => {
                      div.style.backgroundColor = this.colors[1][idx];
                      div.onclick = e => canvas.setColor(this.colors[1][idx]);
                  });
              }
          }

          重新啟動節點服務器后,嘗試更改顏色,設置要繪制的形狀,然后開始單擊畫布。 這是我為確保它有效而進行的一些測試:

          在下一篇文章中,我們將添加一些方便的函數來顯示選擇的形狀,以及應用程序期望用戶下一步做什么的簡短說明。

          tml5經歷了前期html快速的更新換代,以其獨有特性的優勢迅速占據了網頁開發市場鰲頭。介于目前學習和想要從事html5網頁開發的人越來越多。千鋒老師給大家整理了一下基本的html5學習計劃路線圖,適應于一些零基礎學習html5的同學借鑒。

          HTML5學習路線規劃:

          一、HTML5基礎

          HTML 快速入門、文本、圖像、鏈接、表格、列表、表單、框架;

          二、CSS3基礎

          CSS基礎語法、各種選擇器(通用選擇器、元素選擇器、id和class選擇器、后代選擇器、偽類選擇器等)、框模型與背景、文本格式化、表格、顯示與定位、瀏覽器調試

          三、HTML5高級

          HTML5 增強表單元素、HTML5驗證、HTML5新事件和新屬性、Canvas繪圖、HTML5 SVG、音頻和視頻處理、離線Web存儲與應用、HTML5 拖放、Web Socket API、Geolocation API、Web Worker API

          四、實戰技能目標

          掌握JQuery核心API,HTML5 中的繪圖、音頻視頻處理、表單新特性,輕量級WEBAPP開發。

          專業的html5開發工程師需要掌握的專業技術有:

          第一階段:前端頁面重構:PC端網站布局、HTML5+CSS3基礎項目、WebAPP頁面布局;

          第二階段:JavaScript高級程序設計:原生JavaScript交互功能開發、面向對象開發與ES5/ES6、JavaScript工具庫自主研發;

          第三階段:PC端全棧項目開發:jQuery經典特效交互開發、HTTP協議,Ajxa進階與后端開發、前端工程化與模塊化應用、PC端網站開發、PC端管理信息系統前端開發;

          第四階段:移動端webAPP開發:Touch端項目、微信場景項目、應用Vue.js開發WebApp項目、應用Ionic開發WebApp項目、應用React.js開發WebApp;

          第五階段:混合(Hybrid)開發:各類混合應用開發;

          第六階段:NodeJS全棧開發:WebApp后端系統開發;

          第七階段:大數據可視化:數據可視化入門、D3.jS詳解及項目實戰。

          HTML5開發從根本上改變了開發者開發web和應用的方式,從桌面瀏覽器到移動應用,HTML5都已經成為前端開發必不可少的語言。特別是移動互聯網的爆發和微信這個超級應用對HTML5的支持,掌握HTML5語言的程序員已然成為各個互聯網公司的標配,薪資也是一路走高。

          適的動畫不僅更能吸引人們的眼球,也能讓你的應用體驗更為流暢,而將動畫的效果做到極致,才能讓用戶感到使用你的應用是一種享受,而不是覺得生硬和枯燥。那么Web前端人員是否了解各種前端動畫效果實現方式的異同,具體應用中又是如何實現的呢?下面就讓我們一起來看一看吧~



          一、JavaScript 動畫

          因為沒有其它可用的實現方式,最初的前端動畫都是JS來實現,實現上就是通過一個定時器setInterval 每隔一定時間來改變元素的樣式,動畫結束時clearInterval即可。早期的類庫包括 jquery、prototype、mootools 等等都是這種方式。

          盡管這種方式動畫的可控性很強,但是問題也很明顯:

          · 性能不佳,因為需要不斷獲取和修改Dom的布局,所以導致了大量頁面重排(repaint)

          · 缺乏標準,不同的庫使用了不同的API,導致即使是簡單的動畫也有各不相同的實現方式,調整起來比較耗時

          · 帶寬消耗,相對豐富的動畫庫代碼量都很大,結果就是增加了http請求的大小,降低了頁面的載入時間

          二、CSS3 動畫

          css3 加了兩種動畫的實現方式,一種是 transition, 一種是 animation。

          transition 包含4種屬性:transition-delay transition-duration transition-property transition-timing-function,對應動畫的4種屬性: 延遲、持續時間、對應css屬性和緩動函數,

          transform 包含7種屬性:animation-name animation-duration animation-timing-function animation-delay animation-direction animation-iteration-count animation-fill-mode animation-play-state,它們可以定義動畫名稱,持續時間,緩動函數,動畫延遲,動畫方向,重復次數,填充模式。

          總的來書,css 動畫相比與JS更輕量,性能更好,更易于實現,同時也不必擔心缺乏標準和增加帶寬消耗的問題。animation 相比 transtion 使用起來更為復雜,但也提供了更多的控制,其中最重要的就是 frame 的支持,不過通過一些簡單的JS庫,例如 TJ 的 move.js, 我們也能在JS中通過 transition 來實現更復雜的控制。

          三、Html5 動畫

          Html5 定義了三種繪圖的方式,canvas svg Webgl,其中svg做為一種可縮放矢量圖形的實現是基于xml標簽定義的,它有專門的 animate 標簽來定義動畫。而為 canvas 或者 Webgl 實現動畫則需要通過 requestAnimationFrame (簡稱 raf) 來定期刷新畫布。盡管說 raf 的方式會讓代碼變得復雜,但是因為不需要那么多的文檔對象(通常瀏覽器只需要管理一個畫布),它的性能也好很多,尤其是在內存吃緊的移動端上面。

          通過新的 raf 接口以及一些改進手段我們也可以用JS來實現高性能的動畫。主要手段如下:

          1. 減少 Dom 樣式屬性查詢,Dom 樣式屬性的查詢會導致頁面重排,從而消耗性能,通過將屬性保存在JS變量中就可以避免在動畫時去查詢,從而減少卡頓。

          2. 使用性能更好的 css transform 替代改變絕對定位元素的定位屬性

          3. 在移動設備上使用 3d 硬件加速,最簡單辦法就是添加 -Webkit-transform: translateZ(0),原因是移動端的顯卡有很強的圖形渲染能力,而每個應用的 WebvieW 內存卻是極其有限的。

          使用JS的動畫可控性更好,比如說通過事件捕捉可以很容易的設定不同參數。這方面做的最全面的有 Velocity.js,它可做為jquery 插件使用,對于初學者很友好。加入465042726,關于前端方面的更多問題我們可以一起交流!


          主站蜘蛛池模板: 中文字幕人妻无码一区二区三区| 亚洲一区二区三区丝袜| 中文字幕日韩一区二区不卡| 精品国产免费观看一区| 免费无码毛片一区二区APP| 国产一区视频在线免费观看| 亚洲一区中文字幕在线电影网| 日韩一区二区三区在线观看| 海角国精产品一区一区三区糖心| 国产精品无圣光一区二区| 鲁大师成人一区二区三区| 欧美激情国产精品视频一区二区| 91在线视频一区| 久久久精品人妻一区二区三区 | 麻豆AV一区二区三区久久| 国产美女口爆吞精一区二区| 一区二区三区免费电影| 青娱乐国产官网极品一区| 精品日韩一区二区三区视频| 亚洲色精品三区二区一区| 无码国产精品一区二区免费式影视| 国产美女精品一区二区三区| 一区二区三区AV高清免费波多| 美女视频免费看一区二区| 国产一区二区在线观看麻豆| 日本免费精品一区二区三区| 日韩一区二区精品观看| 亚洲成av人片一区二区三区| 国产乱码精品一区二区三| 一区二区国产在线观看| 国产伦一区二区三区高清| 国精产品一区二区三区糖心| 国产乱码精品一区二区三区中文| 亚洲国产一区二区视频网站| 丝袜无码一区二区三区| 91精品一区二区三区久久久久| 日本一道高清一区二区三区| 国产精品电影一区二区三区 | 亚洲熟女乱综合一区二区| 久久精品国产一区二区电影| 亚洲av午夜福利精品一区人妖|