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. Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化(一)

    在数据库有外键的时候,使用 select_related() 和 prefetch_related() 可以很好的减少数据库请求的次数,从而提高性能.本文通过一个简单的例子详解这两个函数的作用.虽然Q ...

  2. JQuery基础学习总结

    JQuery基础学习总结 简单总结下JQuery: 一:事件 1.change事件 <!DOCTYPE html> <html lang="en"> < ...

  3. Linux - Reset a MySQL root password

    Use the following steps to reset a MySQL root password by using the command line interface. Stop the ...

  4. JWeb备忘录

    一.好记性不如赖笔头-- 工具类: JUnit4使用  MyEclipse快捷键 知识点: JAVA反射 JavaSe教程  Java5新特性  Java6新特性  Java7新特性  Java8新特 ...

  5. 转:完善eclipse+pdt作php开发中的代码提示能力

    在eclipse开发中 ,可能由于各种原因导致项目文件(eclipse内置)丢失或错乱, 因而, 失去一些能力.. 以下是经过被痛苦折磨后查阅总结的一点东西 设置完下面内容, 支持以下特性 PHP: ...

  6. tyvj1297 小气的小B

    描述 其实你们都不知道,小B是很小气的.一天小B带着他的弟弟小B'一起去摘果子,走着走着,他们忽然发现了一颗长满了果子的树.由于弟弟长得太矮了,弟弟只有让哥哥小B帮他摘一些果子下来.哥哥小B说:&qu ...

  7. Video.js网页视频播放插件

        插件描述:Video.js 是一个通用的在网页上嵌入视频播放器的 JS 库,Video.js 自动检测浏览器对 HTML5 的支持情况,如果不支持 HTML5 则自动使用 Flash 播放器. ...

  8. Linux 文件系统同步

    同步就是将物理内存中dirty的页写入到磁盘中,保证磁盘和物理页之间的内容一致. 触发同步操作的时机: 1.周期性内核线程,扫描脏页,根据一定的规则选择脏页,将页写回到磁盘. 2.如果内核中的脏页过多 ...

  9. Handsontable对单元格的操作

    1.自动填充单元格数据 fillHandle:true/false    //当值为true时,允许拖动单元格右下角,将其值自动填充到选中的单元格 2.合并单元格 mergeCells:[{row:起 ...

  10. IOS消息推送情况总结

      App没有启动的时候,接受到了消息通知.这个时候操作系统会按默认方式来展示一个alert,在App Icon上标记一个数字 .当程序处于关闭状态收到推送消息时,点击图标或消息栏会调用 - (BOO ...