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. 获取本机CPU,硬盘等使用情况

    早上的时候接到主管的一个任务,要获取服务器上的cpu,硬盘, 数据库等 的使用情况,并以邮件的方式发给boss, = =没办法,公司的服务器真是不敢恭维,顺便吐槽一下公司的网速,卡的时候30k左右徘徊 ...

  2. 关于 addEventListener 和 handleEvent 方法

    使用 addEventListener 可以绑定事件,并传入回调函数. Mozilla 0.9.1 和 Netscape 6.1 之后的版本不但支持传递函数引用,也都允许直接把拥有 handleEve ...

  3. CSS选择器4是下一代CSS选择器规范

    那么,这一版本的新东西有哪些呢? 选择器配置文件 CSS选择器分为两类:快速选择器和完整选择器.快速选择器适用于动态CSS引擎.完整选择器适用于速度不占关键因素的情况,例如document.query ...

  4. jsp 、js和css

    css的一些样式 1.自动换行 .AutoNewline { Word-break: break-all;/*必须*/ width :50px;/*这里是设置多宽就进行换行 */ }

  5. ecshop中404错误页面设置

    在ecshop系统当中,比如你随意将商品详细页面的地址中的ID修改为一个不存在的商品ID,ecshop会自动跳转到首页.ecshop在这方面做得非常的差,甚至导致了很多的站不被搜索引擎收录.最模板提供 ...

  6. LAMP 环境搭建之源码包编译安装

    mysql用的二进制包安装. Apache php 用的源码包 mysql版本5.5.46    Apache版本2.4.7  PHP版本:5.5 mysql安装部分参考了阿铭linux的内容. 这是 ...

  7. mysql设置连接等待时间(wait_timeout)

    Linux下mysql修改连接超时   1,首先进入mysql,查看 wait_timeout.interactive_timeout这个值是否为默认的8小时(即 28800)  [root@serv ...

  8. C语言日期时间标准库

    用思维导图整理: 代码: #include <stdio.h> #include <time.h> #include <string.h> int main() { ...

  9. stm32的FSMC

    之前用的stm32f103rbt6,它是100引脚以内的,不带FSMC.驱动液晶屏或者SRAM要自己写时序方面的程序,比较麻烦.后来换成stm32f103zet6,带有FSMC.不过在学习FSMC的时 ...

  10. Keil "RECURSIVE CALL TO SEGMENT"彻底解决

    我们在做菜单程序或通过函数指针调用函数时,如果被调用的函数中有包含了常量字符串,那么经常会出现这样的的错误提示:"RECURSIVE CALL TO SEGMENT"意思是&quo ...