English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
前言
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' } })
Principalmente configura o diretório raiz do projeto como 'js/diretório 'lib', configurando um caminho chamado 'app' com o valor '../diretório 'app', ou seja, 'js/diretório 'app'.
2. Escrever código de módulo
Os módulos principais deste projeto são os seguintes: point.js, line.js, rect.js, arc.js, utils.js, explicaremos um a um:
point.js:
O módulo point.js representa um ponto (x, y), o código é o seguinte:
/** ponto */ 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; }; }; })
O código acima define o módulo ponto usando define, retornando uma classe com dois parâmetros x, y e um método equals para comparar se dois pontos são iguais.
Para usar este módulo, podemos usar o seguinte código:
require(['app/point'], function(Point) { //Criar um objeto da classe ponto var point = new Point(3, 5); })
Aqui é importante notar que o primeiro parâmetro da função require() é um array, o Point dentro da função de callback representa nossa classe de ponto, e os objetos da classe de ponto são criados de maneira new Point().
line.js:
O módulo line.js representa uma linha, o código é o seguinte:
/** linha */ define(function() { return function(startPoint, endPoint) { this.startPoint = startPoint; this.endPoint = endPoint; this.drawMe = function(contexto) { contexto.strokeStyle = "#000000"; contexto.beginPath(); context.moveTo(this.startPoint.x, this.startPoint.y); context.lineTo(this.endPoint.x, this.endPoint.y); contexto.closePath(); contexto.stroke(); } } })
A definição do módulo de linha é semelhante à do módulo de ponto, ambas retornam uma classe dentro da função de callback do define, a construtora da classe de linha possui dois parâmetros do tipo ponto, representando o ponto de início e o ponto final da linha, a classe de linha também possui um método drawMe, que recebe um objeto context para desenhar a linha.
rect.js:
O módulo rect.js representa um retângulo, o código é o seguinte:
/** retângulo */ define(['app/point'], function() { return function(startPoint, width, height) {}} this.startPoint = startPoint; this.width = width; this.height = height; this.drawMe = function(contexto) { contexto.strokeStyle = "#000000"; contexto.strokeRect(this.startPoint.x, this.startPoint.y, this.width, this.height); } } })
onde startPoint é as coordenadas do canto superior esquerdo do retângulo, é uma classe point, width e height representam a largura e altura do retângulo, além disso, há um método drawMe que desenha o retângulo próprio.
arc.js:
O módulo arc.js representa um círculo, o código é o seguinte:
/** círculo */ define(function() { return function(startPoint, radius) { this.startPoint = startPoint; this.radius = radius; this.drawMe = function(contexto) { contexto.beginPath(); contexto.arc(this.startPoint.x, this.startPoint.y, this.radius, 0, 2 * Math.PI); contexto.closePath(); contexto.stroke(); } } })
onde startPoint representa as coordenadas do canto superior esquerdo do retângulo onde está o círculo, radius representa o raio do círculo, o método drawMe é o método para desenhar o círculo.
Nos módulos acima, as classes de linha, retângulo e círculo contêm o método drawMe(), aqui envolve conhecimento de desenho no canvas, se houver alguma dúvida, consulte o documento: HTML 5 Manual de Referência do Canvas
utils.js
O módulo utils.js é usado principalmente para lidar com classes de ferramentas de desenho de gráficos variados, incluindo o desenho de linhas, retângulos e círculos, bem como o registro de traçados de desenho e a limpeza de traçados, o código é o seguinte:
/** ferramentas de gestão de desenho */ define(function() { var historia = []; //vetor de histórico para salvar registros de desenhos, contendo objetos do tipo linha, retângulo ou círculo function desenharLinha(contexto, linha) { linha.desenhar(contexto); } function desenharRetangulo(contexto, retangulo) { rect.desenharMe(context); } function drawArc(context, arc) { arc.desenharMe(context); } /** adicionar um traçado de desenho */ function addHistory(item) { histórico.push(item); } /** desenhar o traçado histórico */ function drawHistory(context) { for(var i = 0; i < histórico.length; i++) { var obj = histórico[i]; obj.desenharMe(context); } } /** limpar o traçado histórico */ function clearHistory() { histórico = []; } return { drawLine: drawLine, drawRect: drawRect, drawArc: drawArc, addHistory: addHistory, drawHistory: drawHistory, clearHistory: clearHistory }; })
III. Escrever código da interface, lidar com eventos do mouse
Acima, todos os módulos do programa de desenho simples foram definidos. Durante o desenho dos gráficos, são usados apenas os módulos acima. Agora, vamos começar a escrever o código da interface principal. A interface principal contém quatro botões e um grande canvas para desenhar. Abaixo está o código do arquivo index.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Programa de Desenho Simples</title> <style type="text/css"> canvas { fundo-cor: #ECECEC; cursor: padrão; /** configurar o cursor do mouse para o padrão */ } .tool-bar { margem-bottom: 10px; } </style> </head> <body> <div class="tool-bar"> <button id="btn-line">desenhar linha</>botão> <button id="btn-rect">desenhar retângulo</>botão> <button id="btn-oval">desenhar círculo</>botão> <button id="btn-clear">limpar o canvas</>botão> <span id="hint" style="color: vermelho;">Operação atual: desenhar linha</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; /** 处理鼠标按下的事件 */ 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; } /** Tratar o evento de mover o mouse */ 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); } } /** Tratar o evento de levantar o mouse */ 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); } } /** Limpar o quadro */ 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; } /** Ligar o evento de clique ao elemento DOM correspondente pelo id */ function bindClick(domID, handler) { document.getElementById(domID).addEventListener('click', handler); } }); </script> </body> </html>
O arquivo index.html contém muito código, mas o código mais importante é o monitoramento e o processamento dos eventos de clique, movimento e soltura do mouse, além disso, ao obter a posição do mouse no canvas, é necessário prestar atenção: pois os valores clientX e clientY obtidos no objeto event são as coordenadas do mouse em relação à página, para obter as coordenadas do mouse no canvas, é necessário obter o retângulo de área do canvas, e usar clientX-canvas.left, clientY-canvas.top, para obter a posição do mouse no canvas.
Código-fonte
O código-fonte deste blog foi hospedado no github, clique aqui para visualizarCódigo-fonte
Bug conhecido
Ao desenhar um círculo, é necessário arrastar o mouse do canto superior esquerdo para o canto inferior direito para desenhar o círculo. Caso contrário, a posição do círculo estará errada.
Isso é tudo sobre o conteúdo deste artigo, esperamos que ajude no seu aprendizado e que você apoie mais o tutorial de clamor.
Declaração: o conteúdo deste artigo é extraído da Internet, pertence ao respectivo proprietário, foi contribuído e carregado voluntariamente pelos usuários da Internet, o site não possui direitos de propriedade, não foi editado manualmente e não assume responsabilidades legais relacionadas. Se você encontrar conteúdo suspeito de violação de direitos autorais, por favor, envie e-mail para: notice#oldtoolbag.com (ao enviar e-mail, troque # por @ para denunciar e forneça provas relevantes. Caso seja confirmado, o site deletará imediatamente o conteúdo suspeito de violação de direitos autorais.)