HTML5 Canvas实战
6.9 创建绘图应用程序
阅读(

路径和文本

图形及组合

处理图像和视频

画布变换

动画给画布带来生机

与画布交互:为图形和区域附加事件监听器

创建一个Events类

使用画布鼠标坐标

为区域附加鼠标事件监听器

为移动设备上的区域附加触摸事件监听器

为图像附加事件监听器

拖放图形

拖放图像

创建图像放大器

创建绘图应用程序

本节,我们将创建一个漂亮的绘图应用程序,这样,用户就可以直接在浏览器上绘图。

创建绘图应用程序
图6-7 创建绘图应用程序

操作步骤

按照以下步骤,创建一个简单的绘图应用:

  1. 定义工具栏、输入框、按钮的样式:
<style>
canvas  {
  border:  1px solid black;
  font-family:  “Helvetica Neue”,  “Arial”,  “Microsoft YaHei”, sans-serif; 
  font-size:  13px;
  line-height:  1.5;
  color:  #474747;
}
#toolbar  {
  width:  590px;
  border:  1px solid black; 
  border-bottom:  0px; 
  padding:  5px;
  background-color:  #f8f8f8;
}
input[type  =  ‘text’]  {
  width:  30px;
  margin:  0px  5px  0px  5px;
}
label  {
  margin-left:  40px;
}
label:first-of-type  {
  margin-left:  0px;
}
input[type  =  ‘button’]  {
  float: right;
}
#colorSquare  {
  position: relative;
  display: inline-block; 
  width:  20px;
  height:  20px;
  background-color: blue; 
  top:  4px;
}
</style>

2. 链接到Events类:

<script src=”events.js”>
</script>

3. 定义addPoint()函数,该函数向points数组中添加点:

<script>
function addPoint(events, points){
  var context  = events.getContext();
  var drawingPos  = events.getMousePos();
  if  (drawingPos  !== null)  {
    points.push(drawingPos);
  }
}

4. 定义drawPath()函数,该函数清除画布,在开始路径之前重绘画布,然后,使用points数组中的点绘制路径:

function drawPath(canvas, points, canvasImg){
  var context  = canvas.getContext(“2d”);
  //清除画布
  context.clearRect(0,  0, canvas.width, canvas.height);
  //在路径之前重绘画布
  context.drawImage(canvasImg,  0,  0, canvas.width, canvas.height);
  //绘制路径
  context.beginPath();
  context.lineTo(points[0].x, points[0].y); 
  for  (var n  =  1; n  < points.length; n++)  {
    var point  = points[n];
    context.lineTo(point.x, point.y);
  }
  context.stroke();
}

5. 定义updateColorSquare()函数,该函数更新工具栏的颜色正方形框的颜色:

function updateColorSquare(){
  var red  = document.getElementById(“red”).value;
  var green  = document.getElementById(“green”).value;
  var blue  = document.getElementById(“blue”).value;
  var colorSquare  = document.getElementById(“colorSquare”);
  colorSquare.style.backgroundColor  =  “rgb(“  + red  +  “,”  + green  +  “,”  + blue  +  “)”;
}

6. 定义getCanvasImg()函数,该函数返回画布绘图的image对象:

function getCanvasImg(canvas){
  var img  = new Image();
  img.src  = canvas.toDataURL(); 
  return img;
}

7. 页面加载完成后,实例化一个Events对象,定义isMouseDown标志,获取画布图像,并初始化绘制颜色和尺寸:

window.onload  = function(){
  var events  = new Events(“myCanvas”);
  var canvas  = events.getCanvas();
  var context  = events.getContext();
  var isMouseDown  = false;
  var canvasImg  = getCanvasImg(canvas); 
  var points  =  [];
  //初始化绘制参数
  var red  = document.getElementById(“red”).value;
  var green  = document.getElementById(“green”).value;
  var blue  = document.getElementById(“blue”).value;
  var size  = document.getElementById(“size”).value;

8. 每当输入一个新颜色,就更新颜色方框的颜色:

  //附加事件监听器
  document.getElementById(“red”).
  addEventListener(“keyup”, function(evt){ 
    updateColorSquare(); 
  }, false);
  document.getElementById(“green”).addEventListener(“keyup”, function(evt){ 
    updateColorSquare();
  }, false);
  document.getElementById(“blue”). addEventListener(“keyup”, function(evt){ 
    updateColorSquare();
  }, false);

9. 当清除按钮被按下时,清除画布:

  document.getElementById(“clearButton”).
  addEventListener(“click”, function(evt){
    events.clear(); 
    points  =  [];
    canvasImg  = getCanvasImg(canvas);
  }, false);

10. 当Save按钮被按下时,把画布绘画转换为data URL,并在新窗口以图像的形式打开画布绘图:

  document.getElementById(“saveButton”).addEventListener(“click”, function(evt){
    // 在新窗口中打开被保存的图像,以便用户可以右击并把图像保存到他们的电脑中
    window.open(canvas.toDataURL());
  }, false);

11. 当用户在画布上按下鼠标,获取绘制位置、颜色、尺寸,设置路径样式,向points数组中添加第一个点,并把isMouseDown标志设置为true:

canvas.addEventListener(“mousedown”, function(){
  var drawingPos  = events.getMousePos();
  //更新绘制参数
  red  = document.getElementById(“red”).value;
  green  = document.getElementById(“green”).value;
  blue  = document.getElementById(“blue”).value;
  size  = document.getElementById(“size”).value;
  //开始绘制路径
  context.strokeStyle  =  “rgb(“  + red  +  “,”  +  green  +  “,”  + blue  +  “)”;
  context.lineWidth  = size;
  context.lineJoin  =  “round”;
  context.lineCap  =  “round”;
  addPoint(events, points);
  isMouseDown  = true; 
}, false);

12. 当用户在画布上松开鼠标时,把isMouseDown标志设置为false,绘制路径,并保存当前绘制的图像:

canvas.addEventListener(“mouseup”, function(){
  isMouseDown  = false;
  if  (points.length  >  0)  {
    drawPath(this, points, canvasImg); // reset points
    points  =  [];
  }
  canvasImg  = getCanvasImg(this); 
}, false);

13. 当用户鼠标离开画布,模拟mouseup事件:

canvas.addEventListener(“mouseout”, function(){
  if  (document.createEvent)  {
    var evt  = document.
    createEvent(‘MouseEvents’);
    evt.initEvent(“mouseup”, true, false);
    this.dispatchEvent(evt);
  }
  else  {
    this.fireEvent(“onmouseup”);
  }
}, false);

14. 设置stage()函数,当按下鼠标并移动时,该函数连续向当前绘制路径中添加新点:

events.setStage(function(){
  if  (isMouseDown)  {
    addPoint(this, points);
    drawPath(canvas, points, canvasImg);
  }
  });
};
</script>

15. 构造工具栏,并添加画布元素:

<body>
<div id=”toolbar”>
  <label>
  Color
  </label>
  R:  <input type=”text” id=”red” maxlength=”3” class=”short” value=”0”>
  G:  <input type=”text” id=”green” maxlength=”3” class=”short” value=”0”>
  B:  <input type=”text” id=”blue” maxlength=”3” class=”short” value=”255”>
  <div id=”colorSquare”> </div>
  <label>
  Size:
  </label>
  <input type=”text” id=”size” maxlength=”3” class=”short” value=”20”>px
  <input type=”button” id=”clearButton” value=”Clear”>
  <input type=”button” id=”saveButton” value=”Save”>
</div>
<canvas id=”myCanvas” width=”600” height=”250”> </canvas>
</body>

工作原理

绘图应用一般具有以下核心特性:

  • 一个mousedown事件开始一条绘制路径,一个mouseup事件结束一条绘制路径
  • 可以设置线条宽度
  • 可以设置绘制颜色
  • 绘图可以被清除
  • 绘图可以被保存

当然,如果你想在Web上创建一个Photoshop或Gimp-like绘图应用,你可能要添加其他许许多多的特性,但这里明确说明,我们只从基础开始。

很明显,上述列表中的最重要的是第一条——我们需要找到用户可以在屏幕上绘制线条的方法。最直截了当的方法,就是按照下面步骤去做:

  1. 当用户在画布上的某个地方按下鼠标,则设置路径样式,并把鼠标位置添加到points数组,来定义绘制路径的起点。
  2. 当用户移动鼠标,则获取鼠标位置,并把另一个点添加到points数组,然后使用这个新点重绘路径。
  3. 当用户鼠标松开,则设置标志表明它是一条路径,并保存当前绘制图像,供下一条绘制路径使用。

为了简单起见,我们让用户使用文本输入框设置线条宽度,并让用户使用三个文本输入框设置颜色(即颜色的红、绿、蓝分量)。

最后,我们可以创建一个clear按钮,调用Events对象的clear()方法来清除画布,并创建一个save按钮,调用画布上下文对象的DataURL()方法,把画布绘图转换为data URL,并在新窗口中打开该data URL,用户可以在图像上右击,来把图像保存到本地计算机。

了解更多

如果你想创建一个更复杂的绘图应用,这里是更多的一些想法:

  • 在所有主流浏览器都支持颜色选择器的输入控件之前,你应该创建一个自定义的颜色选择器的小部件,让用户以图形化的方式选择颜色,而不是填写颜色的红、绿、蓝分量
  • 你可以使用HTML的range输入控件创建一个滑动条,来设置画笔的粗细
  • 可以通过为每一层动态新建一个画布元素,来支持图层。与Photoshop和Gimp类似,你也可以提供删除图层或合并图层的能力
  • 如果你的应用支持图层,你也可以为每一层增加透明度控制
  • 你可以把绘制的图画保存到本地存储或离线数据库,来增强应用的保存特性(相关参考第3章中画布绘图转换为data URL这一节)
  • 提供预构建的图形,如线条、矩形、圆等
  • 允许图形被缩放、旋转
  • 允许用户把图像导入到它们的绘图
  • 本清单还会继续下去...

希望这一节能够激起你对画布进行更深入研究的兴趣,并帮助你想到其它可能的事情。我可以有把握的说,终有这么一天,有人会创建出一个成熟的、完全基于画布的、并且不亚于Adobe Photoshop的图像编辑的Web应用。也许,这个人就是你!

相关参考

  • 第1章 绘制螺旋线
  • 第3章 画布绘图转换为data URL
  • 第3章 画布绘图另存为图像
  • 使用画布鼠标坐标

如果本教程对您帮助很大,请随意打赏。您的支持,将鼓励我们提供更好的教程!

← 键盘方向键翻页 →
返回顶部 手机访问 关注微信 返回底部

扫码访问歪脖网

随时随地,想看就看

关注歪脖网微信

分享 web 知识、交流 web 经验