>  기사  >  웹 프론트엔드  >  RequireJS 간단한 그리기 프로그램 개발

RequireJS 간단한 그리기 프로그램 개발

高洛峰
高洛峰원래의
2016-12-08 14:11:311191검색

머리말

RequireJS의 등장으로 프론트엔드 프로젝트가 점점 커지고 코드가 많아질수록 모듈화 코드는 프로젝트 구조를 더 명확하게 만들어줍니다. 개발 중에만 생각이 더 명확해지고 나중에 유지 관리가 더 쉬워집니다. 다음은 RequireJS를 배운 후 RequireJS를 사용하여 개발한 간단한 그리기 프로그램입니다. 아래와 같이 브라우저에서 실행됩니다.

RequireJS 간단한 그리기 프로그램 개발

Start

이 간단한 프로젝트는 그리기 프로그램의 구조는 다음과 같습니다.

여기서 index.html은 프로젝트의 홈페이지이고 모든 js 파일은 js 디렉토리에 저장되며 js/app 디렉토리는 사용자 정의 모듈 파일이며 js/lib 디렉터리는 현재로서는 파일이 없습니다. 우리 프로젝트에서 jquery와 같은 다른 프런트엔드 프레임워크를 사용하는 경우 js/lib 디렉터리에는 이러한 프레임워크의 js 파일이 저장됩니다. 주로 일부 경로를 구성하는 requirejs의 구성 파일인 js /require.min.js는 RequireJS 프레임워크의 파일입니다. 이 간단한 그리기 프로그램을 완성하려면 저를 단계별로 따라오세요!

1. requirejs 구성

본 프로젝트의 구성 파일 코드는 js/main.js에 위치합니다.

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


가장 중요한 것은 프로젝트 루트 디렉터리를 'js/lib'로 구성한 후 'app'이라는 경로를 구성하는 것인데, 경로는 '../app'이고, 즉, 'js/app' 목차입니다.

2. 모듈 코드 작성

이 프로젝트의 모듈은 주로 point.js, line.js, ret.js, arc.js, utils.js 등을 포함합니다. 설명:

point.js:

point.js 이 모듈은 점(x, y)을 나타내며 코드는 다음과 같습니다.

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


위 코드는 정의를 사용하여 이 모듈을 정의하고 콜백 함수에서 클래스를 반환합니다. 이 클래스에는 두 개의 매개 변수 x, y 및 두 매개 변수를 비교하기 위한 equals 메서드가 있습니다. . 포인트가 동일합니까?
이 모듈을 사용하려면 다음 코드를 사용할 수 있습니다.

require(['app/point'], function(Point) {
  //新建一个点类的对象
  var point = new Point(3, 5);
})


여기서 첫 번째 매개변수에 주의해야 합니다. require() 함수 배열입니다. 콜백 함수의 Point는 포인트 클래스를 나타내며, 포인트 클래스 객체는 new Point()를 통해 생성됩니다.

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


직선 모듈의 정의는 포인트 모듈의 정의와 유사합니다. 둘 다 정의 콜백 함수에 클래스를 반환합니다. 이 직선 클래스의 생성 메서드에는 두 가지 포인트 클래스 매개변수가 있습니다. 직선의 시작점과 끝점 직선 클래스 컨텍스트 개체를 전달하여 스스로 그리는 drawMe 메서드도 있습니다.

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 모서리 점의 좌표는 각각 직사각형의 너비와 높이를 나타내는 포인트 클래스입니다. 직사각형 자체를 그리는 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() 메소드가 포함되어 있으며, 이는 캔버스 그리기에 대한 지식이 포함되어 있습니다. 확실하지 않은 경우 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);
  }
 
  /** 添加一条绘制轨迹 */
  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
  };
})

위의 모듈은 그래픽을 그릴 때 사용됩니다. 메인 인터페이스에는 4개의 버튼과 그리기를 위한 대형 캔버스가 포함되어 있습니다. index.html 파일의 코드는 아래에 직접 업로드됩니다:


index.html 파일에는 많은 코드가 있지만 가장 중요한 것은 코드가 여전히 마우스 누르기, 이동, 들어올리기의 세 가지 이벤트를 모니터링하고 처리한다는 것입니다. 캔버스에서 마우스의 좌표 위치 가져오기: 이벤트 객체에서 얻은 clientX 및 clientY는 페이지를 기준으로 한 마우스의 좌표이므로 캔버스에서 마우스의 좌표를 가져오려면 다음을 가져와야 합니다. 캔버스가 위치한 직사각형 영역을 선택한 다음 clientX-canvas.left, clientY-canvas.top을 사용하여 캔버스에서 마우스 위치를 가져옵니다.
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>简易绘图程序</title>
  <style type="text/css">
    canvas {
      background-color: #ECECEC;
      cursor: default; /** 鼠标设置成默认的指针 */
    }
    .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;">当前操作:画直线</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([&#39;app/point&#39;, &#39;app/line&#39;, &#39;app/rect&#39;, &#39;app/arc&#39;, &#39;app/utils&#39;],
      function(Point, Line, Rect, Arc, Utils) {
 
      var canvas = document.getElementById("canvas");
      var context = canvas.getContext(&#39;2d&#39;);
      var canvasRect = canvas.getBoundingClientRect(); //得到canvas所在的矩形
      canvas.addEventListener(&#39;mousedown&#39;, handleMouseDown);
      canvas.addEventListener(&#39;mousemove&#39;, handleMouseMove);
      canvas.addEventListener(&#39;mouseup&#39;, handleMouseUp);
      bindClick(&#39;btn-clear&#39;, menuBtnClicked);
      bindClick(&#39;btn-line&#39;, menuBtnClicked);
      bindClick(&#39;btn-rect&#39;, menuBtnClicked);
      bindClick(&#39;btn-oval&#39;, 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;
 
      /** 处理鼠标按下的事件 */
      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;
      }
 
      /** 处理鼠标移动的事件 */
      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);
        }
      }
 
      /** 处理鼠标抬起的事件 */
      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 === &#39;btn-clear&#39;) {
          clearCanvas();
          Utils.clearHistory();
        } else if(domID == &#39;btn-line&#39;) {
          selection = 0;
          showHint(&#39;当前操作:画直线&#39;);
        } else if(domID == &#39;btn-rect&#39;) {
          selection = 1;
          showHint(&#39;当前操作:画矩形&#39;);
        } else if(domID == &#39;btn-oval&#39;) {
          selection = 2;
          showHint(&#39;当前操作:画圆形&#39;);
        }
      }
 
      function showHint(msg) {
        document.getElementById(&#39;hint&#39;).innerHTML = msg;
      }
 
      /** 给对应id的dom元素绑定点击事件 */
      function bindClick(domID, handler) {
        document.getElementById(domID).addEventListener(&#39;click&#39;, handler);
      }
    });
  </script>
</body>
</html>

알려진 버그

원을 그릴 때 마우스를 왼쪽 상단에서 오른쪽 하단으로 드래그해야 원을 그릴 수 있습니다. 그렇지 않으면 위치에 문제가 있습니다. 원의.

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.