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. python安装——Windows平台

    刚刚申请博客,第一次写随笔,记录下自己最近的学习情况,希望自己能够不断的学习,不断的丰富自己~ 最近刚开始学python,记录一下,希望大家相互学习,批评指正~ 1.下载python:https:// ...

  2. MVC过滤器详解和示例

    原文  http://blog.csdn.net/ankeyuan/article/details/29624005 MVC过滤器一共分为四个:ActionFilter(方法过滤器),ResultFi ...

  3. 实现android apk反编译后代码混淆

    通常情况下我们需要对我们开发的android代码进行混淆,以免代码在反编译时暴露敏感信息及相关技术代码: 反编译测试工具:onekey-decompile-apk-1.0.1. 在高级版本的adt创建 ...

  4. css3绘制几何图形

    用css3绘制你需要的几何图形 1.圆形 示例: 思路:给任何正方形元素设置一个足够大的 border-radius ,就可以把它变成一个圆形.代码如下: html: <div class=&q ...

  5. scala学习笔记-Demo存档

    class Thermomenter{ var celsius :Float = _; //将变量设置为缺省值'_',这个符号指定了变量的初始化值 //对数值类型来说是0,布尔类型是false,引用类 ...

  6. linux sed 使用

    sed对文本的处理很强大,并且sed非常小,参数少,容易掌握,他的操作方式根awk有点像.sed按顺序逐行读取文件.然后,它执行为该行指定的所有操作,并在完成请求的修改之后的内容显示出来,也可以存放到 ...

  7. wapPush

    短信推送:wapPsuh简介

  8. 【转】android cts测试方法及步骤

    原文网址:http://blog.csdn.net/shi_xin/article/details/42262675 1.CTS下载 打开下面网址, http://source.android.com ...

  9. 深入解析spring中用到的九种设计模式

    转载请注明出处,文章首发于:http://itxxz.com/a/javashili/tuozhan/2014/0601/7.html 设计模式作为工作学习中的枕边书,却时常处于勤说不用的尴尬境地,也 ...

  10. HDU1394 Minimum Inversion Number(线段树OR归并排序)

    Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java ...