English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Développement d'un programme de dessin simple avec RequireJS

前言

RequireJS的出现让前端代码模块化变得容易,当前端项目越来越大,代码越来越多的时候,模块化代码让项目结构更清晰,不仅在开发时让我们的思路更清晰,而且后期维护起来也更容易。下面是我学习RequireJS后使用RequireJS开发的一款简易绘图程序,运行在浏览器中如下图所示:

如果你对RequireJS还不是很了解,可以看我的RequireJS学习笔记:http://blog.csdn.net/yubo_725/article/details/52913853

开始

这个简易绘图程序的项目结构如下图所示:

其中index.html是项目的主页,js目录下存放所有js文件,js/app目录为我们自定义的模块文件,js/lib目录中暂时没有文件,当我们的项目里用到一些其他前端框架如jquery等时,js/lib目录就存放这些框架的js文件,js/main.js为requirejs的配置文件,主要是配置一些路径,js/require.min.js是RequireJS框架的文件。下面请跟我一步一步完成这个简易的绘图程序吧!

一、配置requirejs

本项目的配置文件代码放在js/main.js中,代码内容如下:

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

Il s'agit principalement de configurer le répertoire racine du projet en 'js/dans 'lib', puis configurez un chemin nommé 'app' avec le chemin '../dans 'app', c'est-à-dire 'js/dans le répertoire 'app'.

Deuxième partie : Écrire le code du module

Les modules principaux de ce projet sont les suivants : point.js, line.js, rect.js, arc.js, utils.js, nous les expliquons un par un :

point.js:

Le module point.js représente un point (x, y), voici le code :

/** point */
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;
    };
  };
)

Le code ci-dessus utilise define pour définir le module Point, et retourne une classe dans la fonction callback, cette classe a deux paramètres x, y, et une méthode equals pour comparer si deux points sont égaux.
Pour utiliser ce module, vous pouvez utiliser le code suivant :

require(['app/point], function(Point) {
  //Créer un objet de la classe Point
  var point = new Point(3, 5);
)

Il est important de noter que le premier paramètre de la fonction require() est un tableau. Le Point dans la fonction callback représente notre classe Point, et on crée des objets de la classe Point en utilisant new Point().

line.js:

Le module line.js représente une ligne, voici le code :

/** ligne */
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();
    }
  }
)

La définition du module Ligne est similaire à celle du module Point, elles retournent toutes deux une classe dans la fonction callback de define. Le constructeur de la classe Ligne prend deux paramètres de type Point, représentant le point de départ et l'extrémité de la ligne. La classe Ligne possède également une méthode drawMe, qui prend un objet context en paramètre pour dessiner la ligne.

rect.js:

Le module rect.js représente un rectangle, voici le code :

/** rectangle */
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是矩形左上角的点的坐标,是一个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代表圆形所在的矩形的左上角的点的坐标,radius代表圆的半径,drawMe方法是画圆的方法。
在以上几个模块中,直线类、矩形类、圆形类都包含有drawMe()方法,这里涉及到了canvas绘图的知识,如果有不太清楚的,可以查一下文档:HTML 5 Canvas 参考手册

utils.js

utils.js模块主要是用来处理各种图形绘制的工具类,包括直线、矩形、圆形的绘制,也包括记录绘制轨迹、清除绘制轨迹,代码如下:

/** 管理绘图的工具 */
define(function() { 
  var history = []; //用来保存历史绘制记录的数组,里面存储的是直线类、矩形类或者圆形类的对象
  function drawLine(context, line) {
    line.drawMe(context);
  }
  function drawRect(context, rect) {
    rect.drawMe(context);
  }
  function drawArc(context, arc) {
    arc.drawMe(context);
  }
  /** ajouter une trajectoire de dessin */
  function addHistory(item) {
    history.push(item);
  }
  /** tracer l'historique des trajectoires */
  function drawHistory(context) {
    for(var i = 0; i < history.length; i++) {
      var obj = history[i];
      obj.drawMe(context);      
    }
  }
  /** effacer l'historique des trajectoires */
  function clearHistory() {
    history = [];
  }
  return {
    drawLine: drawLine,
    drawRect: drawRect,
    drawArc: drawArc,
    addHistory: addHistory,
    drawHistory: drawHistory,
    clearHistory: clearHistory
  };
)

Trois étapes pour écrire le code de l'interface et traiter les événements de la souris

Les modules de ce programme de dessin simple ont été tous définis ci-dessus. Lorsque vous dessinez des graphiques, vous utilisez simplement ces quelques modules. Nous allons commencer à écrire le code de l'interface principale maintenant. L'interface principale contient quatre boutons et un grand canevas pour dessiner. Voici directement le code du fichier index.html :

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Programme de dessin simple</title>
  <style type="text/css">
    canvas {
      background-color: #ECECEC;
      cursor: default; /** regléer le curseur à l'icône par défaut */
    }
    .tool-bar {
      marge-bottom: 10px;
    }
  </style>
</head>
<body>
  <div class="tool-bar">
    <button id="btn-line">dessiner une ligne</>',
    <button id="btn-rect">dessiner un rectangle</>',
    <button id="btn-oval">dessiner un cercle</>',
    <button id="btn-/>',
    <span id="hint" style="color: rouge;">Opération actuelle : dessiner une ligne</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(); //obtenir le rectangle contenant le 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, 2représentent respectivement le dessin d'une ligne, d'un rectangle et d'un cercle
      var downPoint = new Point(0, 0), 
        movePoint = new Point(0, 0), 
        upPoint = new Point(0, 0);
      var line;
      var rect;
      var arc;
      /** traiter l'événement de clic gauche de la souris */
      function handleMouseDown(event) {
        downPoint.x = event.clientX - canvasRect.left;
        if(selection === 0) { - canvasRect.top;
        line = new Line(downPoint, downPoint); 
          line.startPoint = downPoint;
          rect = new Rect(new Point(downPoint.x, downPoint.y), 0, 0);
        } 1) {
          else if(selection ===
        } 2) {
          arc = new Arc(new Point(downPoint.x, downPoint.y), 0);
        }
        mouseDown = true;
      }
      /** traiter l'événement de déplacement de la souris */
      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 &63; (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);
        }
      }
      /** traiter l'événement de relâchement de la souris */
      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);
      }
      /** 事件处理:菜单按钮点击 */
      function menuBtnClicked(event) {
        var domID = event.srcElement.id;
        if(domID === 'btn-clear') {
          clearCanvas();
          Utils.clearHistory();
        } else if(domID == 'btn-line') {
          selection = 0;
          showHint('操作当前:绘制直线');
        } else if(domID == 'btn-rect') {
          selection = 1;
          showHint('操作当前:绘制矩形');
        } else if(domID == 'btn-oval') {
          selection = 2;
          showHint('操作当前:绘制圆形');
        }
      }
      function showHint(msg) {
        document.getElementById('hint').innerHTML = msg;
      }
      /** Lie l'événement de clic à l'élément DOM correspondant par id */
      function bindClick(domID, handler) {
        document.getElementById(domID).addEventListener('click', handler);
      }
    });
  </script>
</body>
</html>

Il y a beaucoup de code dans le fichier index.html, mais le code le plus important est l'écoute et le traitement des événements de clic, de déplacement et de relâchement de la souris. De plus, pour obtenir la position de la souris dans le canvas, il faut noter que les valeurs clientX et clientY obtenues dans l'objet événement sont les coordonnées de la souris par rapport à la page, pour obtenir les coordonnées de la souris dans le canvas, il faut obtenir la zone rectangulaire de canvas, puis utiliser clientX-canvas.left, clientY-canvas.top pour obtenir la position de la souris dans le canvas.

Code source

Le code source de cet article de blog est hébergé sur github, cliquez ici pour voirCode source

Bug connu

Pour dessiner un cercle, vous devez glisser la souris de l'angle supérieur gauche à l'angle inférieur droit pour dessiner un cercle. Sinon, la position du cercle aura un problème.

Voici la totalité du contenu de cet article, j'espère qu'il vous sera utile dans vos études, et j'espère que vous soutiendrez également le tutoriel à cri.

Déclaration : le contenu de cet article est fourni par Internet, propriété des auteurs respectifs, contribué et téléversé par les utilisateurs d'Internet, le site Web ne possède pas de propriété, n'a pas été traité par l'éditeur humain et n'assume aucune responsabilité juridique. Si vous trouvez du contenu suspect de violation de copyright, veuillez envoyer un e-mail à notice#w3Pour signaler une violation, veuillez envoyer un e-mail à codebox.com (remplacez # par @), en fournissant des preuves pertinentes. Une fois vérifié, le site supprimera immédiatement le contenu suspect de violation de copyright.

Vous pourriez aussi aimer