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. 库函数 Math

    int abs( int num ); double fabs( double arg ); long labs( long num ); 函数返回num的绝对值   #include <mat ...

  2. 基于zigbee与tiny4412开发板的环境监测系统

    一.开发板环境搭建 1.tiny4412   linux系统的布置 参考博客:http://www.cnblogs.com/luoxiang/p/4186391.html 二.boa服务器的搭建 下载 ...

  3. Java学习笔记--Swing用户界面组件

    很多与AWT类似. 事件处理参考:Java学习笔记--AWT事件处理 1.设计模式: 模型:存储内容视图:显示内容控制器:处理用户输入· 2. 文本输入常用组件 2.1 文本域: JLabel lab ...

  4. 【iOS开发】单例模式设计(ARC & MRC)

    适用于ARC & MRC // 帮助实现单例设计模式 // .h文件的实现 #define SingletonH(methodName) + (instancetype)shared##met ...

  5. js判断输入的是单字节还是双字节

    计算机上每一个字符.数字.汉字.字母等,都对应着unicode编码,unicode编码小于255的为单字节,大于255.小于65535的为双子节或三字节 查看一个字符对应的unicode编码 var ...

  6. RAC之RMAN恢复

    之前整理的RMAN 有关还原的文章: RMAN 系列(五) ---- RMAN 还原 与 恢复 http://blog.csdn.net/tianlesoftware/archive/2010/07/ ...

  7. HashMap和Hashtable的差别

     1. HashMap 与 Hashtable继承自不同的类 1) HashMap 继承自AbstractMap,而AbstractMap实现了Map接口 2) Hashtable 继承自Dict ...

  8. 【转】Linux系统调用列表

    一.进程控制: fork 创建一个新进程 clone 按指定条件创建子进程 execve 运行可执行文件 exit 中止进程 _exit 立即中止当前进程 getdtablesize 进程所能打开的最 ...

  9. hdu 5640 King's Cake(模拟)

    Problem Description   It is the king's birthday before the military parade . The ministers prepared ...

  10. HDU 4362 Dragon Ball 线段树

    #include <cstdio> #include <cstring> #include <cmath> #include <queue> #incl ...