Canvas+Javascript 带图标的工具条制作 TToolbar

工具条是由一个TToolbar对象和两个按钮对象(TImageButton、TColorButton)组成,因为之前我大部分时间是使用d.e.l.p.h.i进行开发,所以命名方面比较偏向于d.e.l.p.h.i的风格,请处女座的同学忍耐将就一下。

图标按钮 TImageButton

TImageButton 是一个图标按钮对象,可以设置三个图标文件,分别是正常状态,鼠标移上状态,鼠标点击状态。

下面我们介绍一下TImageButton的参数:

Command是按钮对应的功能编号,比如我们定义1为直线,2为矩形.

NormalSrc, MouseOnSrc, MouseDownSrc 分别为正常状态,鼠标移上状态,鼠标点击状态 的图标地址。

x, y, width, height 按钮在工具条上的位置和尺寸。

Toolbar 为宿主工具条。

Group 是按钮所属分组。

  1. function TImageButton(Command,
  2. NormalSrc,
  3. MouseOnSrc,
  4. MouseDownSrc,
  5. x,
  6. y,
  7. width,
  8. height,
  9. Toolbar,
  10. group)
  11. {
  12. }

下面为在Canvas上绘制按钮图标的代码

当鼠标移进按钮或鼠标移出按钮时,将调用ChangeState来改变按钮的状态.为按钮设置不同的图标属性,然后通过Clear()函数将原来的图素清除,再利用RenderImage函数绘制新的按钮。

  1. function Clear() {
  2. Context.clearRect(Toolbar.x + x, Toolbar.y + y, width, height);
  3. }
  4. function LoadImage(newsrc) {
  5. image.src = newsrc;
  6. if (image.complete) {
  7. RenderImage(image);
  8. } else
  9. image.onload = function() {
  10. RenderImage(image);
  11. };
  12. }
  13. function RenderImage(image) {
  14. Context.drawImage(image, Toolbar.x + x, Toolbar.y + y, width, height);
  15. }
  16. function ChangeState(NewState) {
  17. state = NewState;
  18. Clear();
  19. if (NewState == CSN)
  20. LoadImage(NormalSrc);
  21. else if (NewState == CSO)
  22. LoadImage(MouseOnSrc);
  23. else if (NewState == CSD)
  24. LoadImage(MouseDownSrc);
  25. }

PointIn函数用于检测鼠标所在位置是否在当前按钮所覆盖区域中。

注意这里的AbsX与AbsY函数,由于鼠标的x值和y值是鼠标在页面中的坐标,而当前TImageButton对象的x,y是其在TToolbar对象中的坐标位置。因此我们在计算该TImageButton所覆盖区域时,应当加上画布在页中的坐标以及TToolbar对象在画布中的偏移量。

  1. </pre><pre class="javascript" name="code">    function PointIn (testx,testy)
  2. {
  3. if ((testx>Absx())&&(testx<(Absx()+width))
  4. &&(testy>Absy()) && (testy<(Absy()+height)))
  5. {
  6. return true;
  7. }
  8. else
  9. return false;
  10. };
  1. function Absx() {
  2. return Canvas.offsetLeft + Toolbar.x + x;
  3. };
  4. function Absy() {
  5. return Canvas.offsetTop + Toolbar.y + y;
  6. };

颜色选择按钮TColorButton

从下面TColorButton对象的建立参数我们可以看到,它与TImageButton基本类似,按照面向对象的法则,应当抽取一个基类,由两个TColorButton和TImageButton来继承。但我还没有学会如何在Javascript中实现对类的继承,所以暂时将它们分成两个完全不相干的类。

注意一下这个建立函数与TImageButton的唯一区别是它的Command参数不再是保存命令的编号,而是保存颜色的值。

  1. function TColorButton(Command,
  2. x,
  3. y,
  4. width,
  5. height,
  6. Toolbar,
  7. group)
  8. {

TColorButton同样有 mousemoveon,mouseleave,click三种状态。当鼠标在按钮上时在颜色选择小框外画一个淡黄色的小框。

  1. function Clear()
  2. {
  3. Context.clearRect(Toolbar.x+ x,Toolbar.y+ y,width,height);
  4. }
  5. function RenderButton()
  6. {
  7. Context.fillStyle=command;
  8. Context.fillRect(Toolbar.x+ x, Toolbar.y+ y,width,height);
  9. if (state==CSO)
  10. {
  11. Context.strokeStyle="#FFCC33";
  12. Context.lineWidth=2;
  13. Context.strokeRect(Toolbar.x+ x+2, Toolbar.y+ y+2,width-4,height-4);
  14. }
  15. }
  16. function ChangeState(NewState)
  17. {
  18. state=NewState;
  19. Clear();
  20. RenderButton();
  21. }

主工具条TToolbar

  1. function TToolbar(Canvas, x, y, width, height) {
  2. var Context = Canvas.getContext('2d');
  3. this.Canvas = Canvas;
  4. this.x = x;
  5. this.y = y;
  6. this.width = width;
  7. this.height = height;
  8. var CurrentShapeProperty;
  9. var BorderColor;
  10. btnList = new Array();
  11. btnCounter = 0;
  12. Create();
  13. }

首先我们来看一下TToolbar的建立参数和成员变量

Canvas是工具条的图象载体,与用户交互的UI元素. x,y 为工具条在画布(Canvas) 上的偏移量,width,height分别为工具条的宽度和高度.

定义画布的上下文

var Context = Canvas.getContext('2d');

CurrentShapeProperty 用于记录选择的一些图形属性 如画笔的宽度,颜色等.

TToolbar负责做两件重要的工作

1.判断鼠标移动到了哪个按钮或者鼠标点击了哪个按钮.

利用 InstallEvents 绑定工具条的画布Canvas鼠标事件.

mousemove函数逐个判断当前工具条所管理的按钮是否获得了鼠标焦点. 如果当前鼠标移到了该按钮上,将该按钮的图标设为相应图标(在testHit函数中).其余图标设置为普通状态.

mousedown 函数逐个判断当前工具条所管理的按钮是否获得了鼠标点击.如果是颜色按钮则将当前选中的颜色值拷贝到大颜色按钮.

  1. mousemove = function(event) {
  2. var Current = null;
  3. for (var i = 0; i < btnList.length; i++) {
  4. if (btnList[i].testHit(event.clientX, event.clientY) == true)
  5. Current = btnList[i];
  6. }
  7. if (Current != null) {
  8. for (var i = 0; i < btnList.length; i++) {
  9. if ((btnList[i] != Current) && (btnList[i].getisChecked() == false))
  10. btnList[i].setNormal();
  11. }
  12. }
  13. };
  14. mousedown = function(evnet) {
  15. var Current = null;
  16. for (var i = 0; i < btnList.length; i++) {
  17. if (btnList[i].testMouseDown(event.clientX, event.clientY) == true)
  18. Current = btnList[i];
  19. }
  20. if (Current != null) {
  21. for (var i = 0; i < btnList.length; i++) {
  22. if (Current.getGroup() == btnList[i].getGroup()) {
  23. if (btnList[i] != Current)
  24. btnList[i].setNormal();
  25. }
  26. }
  27. if (Current.getGroup()==3)
  28. {
  29. var Color=Current.Command();
  30. ColorSelected(Color);
  31. }
  32. }
  33. };
  34. //安装鼠标移动、点击等方法
  35. this.InstallEvents = function() {
  36. Canvas.onmousemove = function(event) {
  37. mousemove(event);
  38. };
  39. Canvas.onmousedown = function(event) {
  40. mousedown(event);
  41. };
  42. };

另外我之前想用以下方法来绑定鼠标事件,没有成功请帮看一下问题出在哪里,谢谢

  1. function AddEvent(element, eventName, eventHandler) {
  2. window.alert( typeof element.addEventListener);
  3. if ( typeof element.addEventListener != "undefined") {
  4. window.alert(eventHandler);
  5. element.addEventListener(eventName, eventHandler, false);
  6. window.alert(element.onmousemove);
  7. } else
  8. element.attachEvent(eventName, eventHandler);
  9. }
  10. //安装鼠标移动、点击等方法
  11. this.InstallEvents = function() {
  12. AddEvent(Canvas,"onmousemove",this.mousemove);
  13. AddEvent(Canvas,"onmousedown",this.mousedown);
  14. };

2.管理画图的命令(TComand)

建立绘图命令会在后续的章节进行介绍.

  1. this.getNewCommand = function(DisplayCanvas) {
  2. for (var i = 0; i < btnList.length; i++) {
  3. if (btnList[i].getGroup() == 1) {
  4. if (btnList[i].getisChecked()) {
  5. var commandId = btnList[i].Command();
  6. var command = new TCommand(DisplayCanvas, commandId);
  7. return command;
  8. }
  9. }
  10. }
  11. return null;
  12. };

在线演示

工具条对象完整代码(TToolbar)

  1. function TToolbar(Canvas, x, y, width, height) {
  2. var Context = Canvas.getContext('2d');
  3. this.Canvas = Canvas;
  4. this.x = x;
  5. this.y = y;
  6. this.width = width;
  7. this.height = height;
  8. var CurrentShapeProperty;
  9. var BorderColor;
  10. btnList = new Array();
  11. btnCounter = 0;
  12. Create();
  13. // InstallEvents();
  14. function Create() {
  15. Context.strokeStyle = "black";
  16. Context.lineWidth = "2";
  17. Context.strokeRect(x, y, width, height);
  18. }
  19. this.AddButton = function(button) {
  20. btnList[btnCounter++] = button;
  21. };
  22. function AddEvent(element, eventName, eventHandler) {
  23. window.alert( typeof element.addEventListener);
  24. if ( typeof element.addEventListener != "undefined") {
  25. window.alert(eventHandler);
  26. element.addEventListener(eventName, eventHandler, false);
  27. window.alert(element.onmousemove);
  28. } else
  29. element.attachEvent(eventName, eventHandler);
  30. }
  31. mousemove = function(event) {
  32. var Current = null;
  33. for (var i = 0; i < btnList.length; i++) {
  34. if (btnList[i].testHit(event.clientX, event.clientY) == true)
  35. Current = btnList[i];
  36. }
  37. if (Current != null) {
  38. for (var i = 0; i < btnList.length; i++) {
  39. if ((btnList[i] != Current) && (btnList[i].getisChecked() == false))
  40. btnList[i].setNormal();
  41. }
  42. }
  43. };
  44. mousedown = function(evnet) {
  45. var Current = null;
  46. for (var i = 0; i < btnList.length; i++) {
  47. if (btnList[i].testMouseDown(event.clientX, event.clientY) == true)
  48. Current = btnList[i];
  49. }
  50. if (Current != null) {
  51. for (var i = 0; i < btnList.length; i++) {
  52. if (Current.getGroup() == btnList[i].getGroup()) {
  53. if (btnList[i] != Current)
  54. btnList[i].setNormal();
  55. }
  56. }
  57. if (Current.getGroup()==3)
  58. {
  59. var Color=Current.Command();
  60. ColorSelected(Color);
  61. }
  62. }
  63. };
  64. //安装鼠标移动、点击等方法
  65. this.InstallEvents = function() {
  66. //AddEvent(Canvas,"onmousemove",this.mousemove);
  67. //AddEvent(Canvas,"onmousedown",this.mousedown);
  68. //Canvas.onmousemove=this.mousemove;
  69. Canvas.onmousemove = function(event) {
  70. mousemove(event);
  71. };
  72. Canvas.onmousedown = function(event) {
  73. mousedown(event);
  74. };
  75. };
  76. this.setBorderColorButton=function(ColorButton)
  77. {
  78. BorderColor=ColorButton;
  79. };
  80. function ColorSelected (color) {
  81. BorderColor.setColor(color);
  82. }
  83. this.getNewCommand = function(DisplayCanvas) {
  84. for (var i = 0; i < btnList.length; i++) {
  85. if (btnList[i].getGroup() == 1) {
  86. if (btnList[i].getisChecked()) {
  87. var commandId = btnList[i].Command();
  88. var command = new TCommand(DisplayCanvas, commandId);
  89. return command;
  90. }
  91. }
  92. }
  93. return null;
  94. };
  95. this.getShapeProperty = function() {
  96. if (typeof CurrentShapeProperty=="undefined")
  97. CurrentShapeProperty = new TShapeProperty();
  98. CurrentShapeProperty.setLineColor(BorderColor.Command());
  99. for (var i = 0; i < btnList.length; i++) {
  100. if (btnList[i].getGroup() == 2) {
  101. if (btnList[i].getisChecked()) {
  102. CurrentShapeProperty.setLineWidth(btnList[i].Command());
  103. }
  104. }
  105. }
  106. return CurrentShapeProperty;
  107. };
  108. }

图片按钮完整代码(TImageButton)

  1. function TImageButton(Command, NormalSrc, MouseOnSrc, MouseDownSrc, x, y, width, height, Toolbar, group) {
  2. var command = Command;
  3. var NormalSrc = NormalSrc;
  4. var MouseOnSrc = MouseOnSrc;
  5. var MouseDownSrc = MouseDownSrc;
  6. var x = x;
  7. var y = y;
  8. var width = width;
  9. var height = height;
  10. var Canvas = Toolbar.Canvas;
  11. var Context = Canvas.getContext("2d");
  12. var CSN = "Normal";
  13. var CSO = "MouseOn";
  14. var CSD = "MouseDown";
  15. var state = CSN;
  16. var Group = group;
  17. var image = new Image();
  18. CreateButton();
  19. function CreateButton() {
  20. LoadImage(NormalSrc);
  21. }
  22. function Absx() {
  23. return Canvas.offsetLeft + Toolbar.x + x;
  24. };
  25. function Absy() {
  26. return Canvas.offsetTop + Toolbar.y + y;
  27. };
  28. function PointIn(testx, testy) {
  29. if ((testx > Absx()) && (testx < (Absx() + width)) && (testy > Absy()) && (testy < (Absy() + height))) {
  30. return true;
  31. } else
  32. return false;
  33. };
  34. function Clear() {
  35. Context.clearRect(Toolbar.x + x, Toolbar.y + y, width, height);
  36. }
  37. function LoadImage(newsrc) {
  38. image.src = newsrc;
  39. if (image.complete) {
  40. RenderImage(image);
  41. } else
  42. image.onload = function() {
  43. RenderImage(image);
  44. };
  45. }
  46. function RenderImage(image) {
  47. Context.drawImage(image, Toolbar.x + x, Toolbar.y + y, width, height);
  48. }
  49. function ChangeState(NewState) {
  50. state = NewState;
  51. Clear();
  52. if (NewState == CSN)
  53. LoadImage(NormalSrc);
  54. else if (NewState == CSO)
  55. LoadImage(MouseOnSrc);
  56. else if (NewState == CSD)
  57. LoadImage(MouseDownSrc);
  58. }
  59. this.testHit = function(dx, dy) {
  60. if (PointIn(dx, dy)) {
  61. if (state == CSN) {
  62. ChangeState(CSO);
  63. }
  64. return true;
  65. }
  66. return false;
  67. };
  68. this.OnClick = function() {
  69. };
  70. this.testMouseDown = function(dx, dy) {
  71. if (PointIn(dx, dy)) {
  72. ChangeState(CSD);
  73. this.OnClick();
  74. return true;
  75. }
  76. return false;
  77. };
  78. this.getisChecked = function() {
  79. return (state == CSD);
  80. };
  81. this.Command = function() {
  82. return command;
  83. };
  84. this.MoveOn = function() {
  85. return (state == CSO);
  86. };
  87. this.setNormal = function() {
  88. ChangeState(CSN);
  89. };
  90. this.getGroup = function() {
  91. return Group;
  92. };
  93. }

颜色选择框的完整代码(TColorButton)

  1. <span style="font-size:12px;">function TColorButton(Command,
  2. x,
  3. y,
  4. width,
  5. height,
  6. Toolbar,
  7. group)
  8. {
  9. var command=Command;
  10. var x=x;
  11. var y=y;
  12. var width=width;
  13. var height=height;
  14. var Canvas=Toolbar.Canvas;
  15. var Context=Canvas.getContext("2d");
  16. var CSN="Normal";
  17. var CSO="MouseOn";
  18. var CSD="MouseDown";
  19. var state=CSN;
  20. var Group=group;
  21. CreateButton();
  22. function CreateButton()
  23. {
  24. RenderButton();
  25. }
  26. function Absx()
  27. {
  28. return Canvas.offsetLeft+Toolbar.x+x;
  29. };
  30. function Absy()
  31. {
  32. return Canvas.offsetTop+Toolbar.y+y;
  33. };
  34. function PointIn (testx,testy)
  35. {
  36. if ((testx>Absx())&&(testx<(Absx()+width))
  37. &&(testy>Absy()) && (testy<(Absy()+height)))
  38. {
  39. return true;
  40. }
  41. else
  42. return false;
  43. };
  44. function Clear()
  45. {
  46. Context.clearRect(Toolbar.x+ x,Toolbar.y+ y,width,height);
  47. }
  48. function RenderButton()
  49. {
  50. Context.fillStyle=command;
  51. Context.fillRect(Toolbar.x+ x, Toolbar.y+ y,width,height);
  52. if (state==CSO)
  53. {
  54. Context.strokeStyle="#FFCC33";
  55. Context.lineWidth=2;
  56. Context.strokeRect(Toolbar.x+ x+2, Toolbar.y+ y+2,width-4,height-4);
  57. }
  58. }
  59. function ChangeState(NewState)
  60. {
  61. state=NewState;
  62. Clear();
  63. RenderButton();
  64. }
  65. this.testHit=function(dx,dy)
  66. {
  67. if (PointIn(dx,dy))
  68. {
  69. if (state==CSN)
  70. {
  71. ChangeState(CSO);
  72. }
  73. return true;
  74. }
  75. return false;
  76. };
  77. this.testMouseDown=function(dx,dy)
  78. {
  79. if (PointIn(dx,dy))
  80. {
  81. ChangeState(CSD);
  82. return true;
  83. }
  84. return false;
  85. };
  86. this.getisChecked=function()
  87. {
  88. return (state==CSD);
  89. };
  90. this.Command=function()
  91. {
  92. return command;
  93. };
  94. this.MoveOn=function()
  95. {
  96. return (state==CSO);
  97. };
  98. this.setNormal=function()
  99. {
  100. ChangeState(CSN);
  101. };
  102. this.getGroup=function()
  103. {
  104. return Group;
  105. };
  106. this.setColor=function(color)
  107. {
  108. command=color;
  109. Context.fillStyle=command;
  110. Context.fillRect(Toolbar.x+ x, Toolbar.y+ y,width,height);
  111. };
  112. }

HTML5 canvas 在线画笔绘图工具(二)的更多相关文章

  1. HTML5 canvas 在线画笔绘图工具(三)

    组装画板(TDrawBuilder) 在这一小节中我们要把工具条和画板组装起来,让他们可以协同进行工作. 画板通过一个命名为TDrawBuilder来进行组装.在详细讲解TDrawBuilder对象之 ...

  2. HTML5 canvas 在线画笔绘图工具(一)

    HTML5 canvas 在线画笔绘图工具(一) 功能介绍 这是我用Javascript写的第一个程序,在写的过程中走了很多弯路,所以写完之后想分享出来,给与我一样的初学者做为学习的参考,同时在编写这 ...

  3. HTML5 canvas 在线画笔绘图工具(四)

    HTML5画图命令 图形的绘制是由TDrawHandler与TCommand 协同工作完成. TDrawHandler需要完成以下工作 1.聚集类用于管理绘图的命令 TCommand 2.管理鼠标事件 ...

  4. html5 canvas在线文本第二步设置(字体边框)等我全部写完,我会写在页面底部

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. HTML5 canvas 在线涂鸦

    插件地址 http://bencentra.github.io/jq-signature/ 采用技术 jq-signature.min.js Developed using jQuery 2.1.4. ...

  6. 18个基于 HTML5 Canvas 开发的图表库

    如今,HTML5 可谓如众星捧月一般,受到许多业内巨头的青睐.很多Web开发者也尝试着用 HTML 5 来制作各种各样的富 Web 应用.HTML 5 规范引进了很多新特性,其中之一就是 Canvas ...

  7. [js高手之路] html5 canvas系列教程 - arcTo(弧度与二次,三次贝塞尔曲线以及在线工具)

    之前,我写了一个arc函数的用法:[js高手之路] html5 canvas系列教程 - arc绘制曲线图形(曲线,弧线,圆形). arcTo: cxt.arcTo( cx, cy, x2, y2, ...

  8. 基于HTML5 Canvas和jQuery 的绘图工具的实现

    简单介绍 HTML5 提供了强大的Canvas元素.使用Canvas并结合Javascript 能够实现一些很强大的功能.本文就介绍一下基于HTML5 Canvas 的绘图工具的实现.废话少说,先看成 ...

  9. Processon 一款基于HTML5的在线作图工具

    CSDN的蒋涛不久前在微博上评价说ProcessOn是web版的visio,出于好奇私下对ProcessOn进行了一番研究.最后发现无论是在用户体验上,还是在技术上,ProcessOn都比微软的Vis ...

随机推荐

  1. destoon实现底部添加你是第几位访问者的方法

    经常会看到一些网站有类似“您是第位访客”字样的计数统计,这里我们来实现把这个统计功能添加到destoon的底部,显示“你是第几问访问者”的效果.此处的计数器与网站流量统计有区别,记录的是刷新次数,并不 ...

  2. java 根据时间生成唯一id

    主要是依据当前系统毫秒数,但若用循环测试,同一毫秒依然会循环很多次, 系统毫秒数是13位, 公司的解决方法是再加5位的自增数,从00001开始, 于是登录淘宝查看,淘宝的id是13位的数字,猜测应该是 ...

  3. hdu 1255 覆盖的面积

    http://acm.hdu.edu.cn/showproblem.php?pid=1255 #include <cstdio> #include <cstring> #inc ...

  4. perl 对象 通过bless实现

    对象只是一种特殊的引用,它知道自己是和哪个类关联在一起的,而构造器知道如何创建那种关联关系. 这些构造器是通过使用bless操作符,将一个普通的引用物转换成一个对象实现的,

  5. poj 1503 大数相加(java)

    代码: import java.math.*; import java.util.Scanner; public class Main { public static void main(String ...

  6. 【HDU2795】Billboard(线段树)

    大意:给一个h*w的格子,然后给出多个1*w的板子往格子里面填,如果有空间尽量往上一行填满,输出行数,无法填补,则输出-1: 可以使用线段树转化问题,将每一排的格子数目放到每一个叶子节点上,然后每有一 ...

  7. Linux下如何选择文件系统:EXT4、Btrfs 和 XFS

    老实说,人们最不曾思考的问题之一是他们的个人电脑中使用了什么文件系统.Windows 和 Mac OS X 用户更没有理由去考虑,因为对于他们的操作系统,只有一种选择,那就是 NTFS 和 HFS+. ...

  8. poj 3662 Telephone Lines(好题!!!二分搜索+dijkstra)

    Description Farmer John wants to set up a telephone line at his farm. Unfortunately, the phone compa ...

  9. MyWidget【简单自制控件】

    #coding=gbk from PyQt4 import QtGui,QtCore import random class MyWidget(QtGui.QWidget): def __init__ ...

  10. AFNetwork 作用和使用方法具体解释

    转自:http://www.maxiaoguo.com/clothes/269.html AFNetworking是一个轻量级的iOS网络通信类库.它建立在NSURLConnection和NSOper ...