最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
當(dāng)前位置: 首頁 - 科技 - 知識百科 - 正文

RequireJS簡易繪圖程序開發(fā)

來源:懂視網(wǎng) 責(zé)編:小采 時間:2020-11-27 20:28:43
文檔

RequireJS簡易繪圖程序開發(fā)

RequireJS簡易繪圖程序開發(fā):前言RequireJS的出現(xiàn)讓前端代碼模塊化變得容易,當(dāng)前端項目越來越大,代碼越來越多的時候,模塊化代碼讓項目結(jié)構(gòu)更清晰,不僅在開發(fā)時讓我們的思路更清晰,而且后期維護(hù)起來也更容易。下面是我學(xué)習(xí)RequireJS后使用RequireJS開發(fā)的一款簡易繪圖程序,運(yùn)行在瀏
推薦度:
導(dǎo)讀RequireJS簡易繪圖程序開發(fā):前言RequireJS的出現(xiàn)讓前端代碼模塊化變得容易,當(dāng)前端項目越來越大,代碼越來越多的時候,模塊化代碼讓項目結(jié)構(gòu)更清晰,不僅在開發(fā)時讓我們的思路更清晰,而且后期維護(hù)起來也更容易。下面是我學(xué)習(xí)RequireJS后使用RequireJS開發(fā)的一款簡易繪圖程序,運(yùn)行在瀏
前言

RequireJS的出現(xiàn)讓前端代碼模塊化變得容易,當(dāng)前端項目越來越大,代碼越來越多的時候,模塊化代碼讓項目結(jié)構(gòu)更清晰,不僅在開發(fā)時讓我們的思路更清晰,而且后期維護(hù)起來也更容易。下面是我學(xué)習(xí)RequireJS后使用RequireJS開發(fā)的一款簡易繪圖程序,運(yùn)行在瀏覽器中如下圖所示:

20161028154506320.gif

開始

這個簡易繪圖程序的項目結(jié)構(gòu)如下圖所示:

其中index.html是項目的主頁,js目錄下存放所有js文件,js/app目錄為我們自定義的模塊文件,js/lib目錄中暫時沒有文件,當(dāng)我們的項目里用到一些其他前端框架如jquery等時,js/lib目錄就存放這些框架的js文件,js/main.js為requirejs的配置文件,主要是配置一些路徑,js/require.min.js是RequireJS框架的文件。下面請跟我一步一步完成這個簡易的繪圖程序吧!

一、配置requirejs

本項目的配置文件代碼放在js/main.js中,代碼內(nèi)容如下:

require.config({
 baseUrl: 'js/lib',
 paths: {
 app: '../app'
 }
})

主要就是配置了項目根目錄為'js/lib',然后配置了一個名為'app'的路徑,路徑為'../app',即'js/app'目錄。

二、編寫模塊代碼

這個項目中的模塊主要有如下幾個:point.js, line.js, rect.js, arc.js, utils.js,下面一一說明:

point.js:

point.js這個模塊代表一個點(diǎn)(x, y),代碼如下:

/** 點(diǎn) */
define(function() {
 return function(x, y) {
 this.x = x;
 this.y = y;
 this.equals = function(point) {
 return this.x === point.x && this.y === point.y;
 };
 };
})

上面的代碼中使用define定義了點(diǎn)這個模塊,在回調(diào)函數(shù)中返回了一個類,該類有兩個參數(shù)x,y,還有一個equals方法用于比較兩個點(diǎn)是否相等。
要使用這個模塊,我們可以使用如下代碼:

require(['app/point'], function(Point) {
 //新建一個點(diǎn)類的對象
 var point = new Point(3, 5);
})

這里需要注意require()函數(shù)的第一個參數(shù)是一個數(shù)組,回調(diào)函數(shù)中的Point就代表了我們的點(diǎn)類,通過new Point()的方式創(chuàng)建點(diǎn)類的對象。

line.js:

line.js模塊代表的是一條直線,代碼如下:

/** 直線 */
define(function() {
 return function(startPoint, endPoint) {
 this.startPoint = startPoint;
 this.endPoint = endPoint;
 this.drawMe = function(context) {
 context.strokeStyle = "#000000";
 context.beginPath();
 context.moveTo(this.startPoint.x, this.startPoint.y);
 context.lineTo(this.endPoint.x, this.endPoint.y);
 context.closePath();
 context.stroke();
 }
 }
})

直線模塊的定義跟點(diǎn)模塊的定義類似,都是在define的回調(diào)函數(shù)中返回一個類,這個直線類的構(gòu)造方法中有兩個點(diǎn)類的參數(shù),代表直線的起點(diǎn)和終點(diǎn),直線類還有一個drawMe方法,通過傳入一個context對象,將自身畫出來。

rect.js:

rect.js模塊代表一個矩形,代碼如下:

/** 矩形 */
define(['app/point'], function() {
 return function(startPoint, width, height) {
 this.startPoint = startPoint;
 this.width = width;
 this.height = height;
 this.drawMe = function(context) {
 context.strokeStyle = "#000000";
 context.strokeRect(this.startPoint.x, this.startPoint.y, this.width, this.height);
 }
 }
})

其中startPoint是矩形左上角的點(diǎn)的坐標(biāo),是一個point類,width和height分別代表矩形的寬高,同時還有一個drawMe方法將矩形自身畫出來。

arc.js:

arc.js模塊代表一個圓形,代碼如下:

/** 圓形 */
define(function() {
 return function(startPoint, radius) {
 this.startPoint = startPoint;
 this.radius = radius;
 this.drawMe = function(context) {
 context.beginPath();
 context.arc(this.startPoint.x, this.startPoint.y, this.radius, 0, 2 * Math.PI);
 context.closePath();
 context.stroke();
 }
 }
})

其中startPoint代表圓形所在的矩形的左上角的點(diǎn)的坐標(biāo),radius代表圓的半徑,drawMe方法是畫圓的方法。
在以上幾個模塊中,直線類、矩形類、圓形類都包含有drawMe()方法,這里涉及到了canvas繪圖的知識,如果有不太清楚的,可以查一下文檔:HTML 5 Canvas 參考手冊

utils.js

utils.js模塊主要是用來處理各種圖形繪制的工具類,包括直線、矩形、圓形的繪制,也包括記錄繪制軌跡、清除繪制軌跡,代碼如下:

/** 管理繪圖的工具 */
define(function() {
 var history = []; //用來保存歷史繪制記錄的數(shù)組,里面存儲的是直線類、矩形類或者圓形類的對象
 
 function drawLine(context, line) {
 line.drawMe(context);
 }
 
 function drawRect(context, rect) {
 rect.drawMe(context);
 }
 
 function drawArc(context, arc) {
 arc.drawMe(context);
 }
 
 /** 添加一條繪制軌跡 */
 function addHistory(item) {
 history.push(item);
 }
 
 /** 畫出歷史軌跡 */
 function drawHistory(context) {
 for(var i = 0; i < history.length; i++) {
 var obj = history[i];
 obj.drawMe(context); 
 }
 }
 
 /** 清除歷史軌跡 */
 function clearHistory() {
 history = [];
 }
 
 return {
 drawLine: drawLine,
 drawRect: drawRect,
 drawArc: drawArc,
 addHistory: addHistory,
 drawHistory: drawHistory,
 clearHistory: clearHistory
 };
})

三、編寫界面代碼,處理鼠標(biāo)事件

上面已經(jīng)將本次簡易繪圖程序的模塊都定義完了,在繪制圖形時用到的也就是上面幾個模塊,下面要開始編寫主界面的代碼了,主界面里包含四個按鈕,還有一塊大的畫布用于繪圖,下面直接上index.html文件的代碼:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>簡易繪圖程序</title>
 <style type="text/css">
 canvas {
 background-color: #ECECEC;
 cursor: default; /** 鼠標(biāo)設(shè)置成默認(rèn)的指針 */
 }
 .tool-bar {
 margin-bottom: 10px;
 }
 </style>
</head>
<body>
 <div class="tool-bar">
 <button id="btn-line">畫直線</button>
 <button id="btn-rect">畫矩形</button>
 <button id="btn-oval">畫圓形</button>
 <button id="btn-clear">清空畫布</button>
 <span id="hint" style="color: red;">當(dāng)前操作:畫直線</span>
 </div>
 <canvas id="canvas" width="800" height="600"></canvas>
 <script type="text/javascript" src="js/require.min.js" data-main="js/main"></script>
 <script type="text/javascript">
 require(['app/point', 'app/line', 'app/rect', 'app/arc', 'app/utils'],
 function(Point, Line, Rect, Arc, Utils) {
 
 var canvas = document.getElementById("canvas");
 var context = canvas.getContext('2d');
 var canvasRect = canvas.getBoundingClientRect(); //得到canvas所在的矩形
 canvas.addEventListener('mousedown', handleMouseDown);
 canvas.addEventListener('mousemove', handleMouseMove);
 canvas.addEventListener('mouseup', handleMouseUp);
 bindClick('btn-clear', menuBtnClicked);
 bindClick('btn-line', menuBtnClicked);
 bindClick('btn-rect', menuBtnClicked);
 bindClick('btn-oval', menuBtnClicked);
 
 var mouseDown = false;
 var selection = 1; // 0, 1, 2分別代表畫直線、畫矩形、畫圓
 
 var downPoint = new Point(0, 0),
 movePoint = new Point(0, 0),
 upPoint = new Point(0, 0);
 var line;
 var rect;
 var arc;
 
 /** 處理鼠標(biāo)按下的事件 */
 function handleMouseDown(event) {
 downPoint.x = event.clientX - canvasRect.left;
 downPoint.y = event.clientY - canvasRect.top;
 if(selection === 0) {
  line = new Line(downPoint, downPoint);
  line.startPoint = downPoint;
 } else if(selection === 1) {
  rect = new Rect(new Point(downPoint.x, downPoint.y), 0, 0);
 } else if(selection === 2) {
  arc = new Arc(new Point(downPoint.x, downPoint.y), 0);
 }
 mouseDown = true;
 }
 
 /** 處理鼠標(biāo)移動的事件 */
 function handleMouseMove(event) {
 movePoint.x = event.clientX - canvasRect.left;
 movePoint.y = event.clientY - canvasRect.top;
 if(movePoint.x == downPoint.x && movePoint.y == downPoint.y) {
  return ;
 }
 if(movePoint.x == upPoint.x && movePoint.y == upPoint.y) {
  return ;
 }
 if(mouseDown) {
  clearCanvas();
  if(selection == 0) {
  line.endPoint = movePoint;
  Utils.drawLine(context, line);
  } else if(selection == 1) {
  rect.width = movePoint.x - downPoint.x;
  rect.height = movePoint.y - downPoint.y;
  Utils.drawRect(context, rect);
  } else if(selection == 2) {
  var x = movePoint.x - downPoint.x;
  var y = movePoint.y - downPoint.y;
  arc.radius = x > y ? (y / 2) : (x / 2);
  if(arc.radius < 0) {
  arc.radius = -arc.radius;
  }
  arc.startPoint.x = downPoint.x + arc.radius;
  arc.startPoint.y = downPoint.y + arc.radius;
  Utils.drawArc(context, arc);
  }
  Utils.drawHistory(context);
 }
 }
 
 /** 處理鼠標(biāo)抬起的事件 */
 function handleMouseUp(event) {
 upPoint.x = event.clientX - canvasRect.left;
 upPoint.y = event.clientY - canvasRect.top;
 
 if(mouseDown) {
  mouseDown = false;
  if(selection == 0) {
  line.endPoint = upPoint; 
  if(!downPoint.equals(upPoint)) {
  Utils.addHistory(new Line(new Point(downPoint.x, downPoint.y),
  new Point(upPoint.x, upPoint.y)));
  } 
  } else if(selection == 1) {
  rect.width = upPoint.x - downPoint.x;
  rect.height = upPoint.y - downPoint.y;
  Utils.addHistory(new Rect(new Point(downPoint.x, downPoint.y), rect.width, rect.height));
  } else if(selection == 2) {
  Utils.addHistory(new Arc(new Point(arc.startPoint.x, arc.startPoint.y), arc.radius));
  }
  clearCanvas();
  Utils.drawHistory(context);
 }
 }
 
 /** 清空畫布 */
 function clearCanvas() {
 context.clearRect(0, 0, canvas.width, canvas.height);
 }
 
 /** 菜單按鈕的點(diǎn)擊事件處理 */
 function menuBtnClicked(event) {
 var domID = event.srcElement.id;
 if(domID === 'btn-clear') {
  clearCanvas();
  Utils.clearHistory();
 } else if(domID == 'btn-line') {
  selection = 0;
  showHint('當(dāng)前操作:畫直線');
 } else if(domID == 'btn-rect') {
  selection = 1;
  showHint('當(dāng)前操作:畫矩形');
 } else if(domID == 'btn-oval') {
  selection = 2;
  showHint('當(dāng)前操作:畫圓形');
 }
 }
 
 function showHint(msg) {
 document.getElementById('hint').innerHTML = msg;
 }
 
 /** 給對應(yīng)id的dom元素綁定點(diǎn)擊事件 */
 function bindClick(domID, handler) {
 document.getElementById(domID).addEventListener('click', handler);
 }
 });
 </script>
</body>
</html>

index.html文件中的代碼比較多,但最主要的代碼還是對鼠標(biāo)按下、移動、抬起三種事件的監(jiān)聽和處理,另外,獲取鼠標(biāo)在canvas中的坐標(biāo)位置需要注意一點(diǎn):由于event對象中獲取的clientX和clientY是鼠標(biāo)相對于頁面的坐標(biāo),為了獲取鼠標(biāo)在canvas中的坐標(biāo),需要獲得canvas所在的矩形區(qū)域,然后用clientX-canvas.left,clientY-canvas.top,來獲取鼠標(biāo)在canvas中的位置。

已知bug

在畫圓形時需要鼠標(biāo)從左上角拖到右下角畫圓,如果不是這樣,圓的位置會有問題。

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

RequireJS簡易繪圖程序開發(fā)

RequireJS簡易繪圖程序開發(fā):前言RequireJS的出現(xiàn)讓前端代碼模塊化變得容易,當(dāng)前端項目越來越大,代碼越來越多的時候,模塊化代碼讓項目結(jié)構(gòu)更清晰,不僅在開發(fā)時讓我們的思路更清晰,而且后期維護(hù)起來也更容易。下面是我學(xué)習(xí)RequireJS后使用RequireJS開發(fā)的一款簡易繪圖程序,運(yùn)行在瀏
推薦度:
標(biāo)簽: 軟件 開發(fā) js
  • 熱門焦點(diǎn)

最新推薦

猜你喜歡

熱門推薦

專題
Top