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 是按钮所属分组。
- function TImageButton(Command,
- NormalSrc,
- MouseOnSrc,
- MouseDownSrc,
- x,
- y,
- width,
- height,
- Toolbar,
- group)
- {
- }
下面为在Canvas上绘制按钮图标的代码
当鼠标移进按钮或鼠标移出按钮时,将调用ChangeState来改变按钮的状态.为按钮设置不同的图标属性,然后通过Clear()函数将原来的图素清除,再利用RenderImage函数绘制新的按钮。
- function Clear() {
- Context.clearRect(Toolbar.x + x, Toolbar.y + y, width, height);
- }
- function LoadImage(newsrc) {
- image.src = newsrc;
- if (image.complete) {
- RenderImage(image);
- } else
- image.onload = function() {
- RenderImage(image);
- };
- }
- function RenderImage(image) {
- Context.drawImage(image, Toolbar.x + x, Toolbar.y + y, width, height);
- }
- function ChangeState(NewState) {
- state = NewState;
- Clear();
- if (NewState == CSN)
- LoadImage(NormalSrc);
- else if (NewState == CSO)
- LoadImage(MouseOnSrc);
- else if (NewState == CSD)
- LoadImage(MouseDownSrc);
- }
PointIn函数用于检测鼠标所在位置是否在当前按钮所覆盖区域中。
注意这里的AbsX与AbsY函数,由于鼠标的x值和y值是鼠标在页面中的坐标,而当前TImageButton对象的x,y是其在TToolbar对象中的坐标位置。因此我们在计算该TImageButton所覆盖区域时,应当加上画布在页中的坐标以及TToolbar对象在画布中的偏移量。
- </pre><pre class="javascript" name="code"> function PointIn (testx,testy)
- {
- if ((testx>Absx())&&(testx<(Absx()+width))
- &&(testy>Absy()) && (testy<(Absy()+height)))
- {
- return true;
- }
- else
- return false;
- };
- function Absx() {
- return Canvas.offsetLeft + Toolbar.x + x;
- };
- function Absy() {
- return Canvas.offsetTop + Toolbar.y + y;
- };
颜色选择按钮TColorButton
从下面TColorButton对象的建立参数我们可以看到,它与TImageButton基本类似,按照面向对象的法则,应当抽取一个基类,由两个TColorButton和TImageButton来继承。但我还没有学会如何在Javascript中实现对类的继承,所以暂时将它们分成两个完全不相干的类。
注意一下这个建立函数与TImageButton的唯一区别是它的Command参数不再是保存命令的编号,而是保存颜色的值。
- function TColorButton(Command,
- x,
- y,
- width,
- height,
- Toolbar,
- group)
- {
TColorButton同样有 mousemoveon,mouseleave,click三种状态。当鼠标在按钮上时在颜色选择小框外画一个淡黄色的小框。
- function Clear()
- {
- Context.clearRect(Toolbar.x+ x,Toolbar.y+ y,width,height);
- }
- function RenderButton()
- {
- Context.fillStyle=command;
- Context.fillRect(Toolbar.x+ x, Toolbar.y+ y,width,height);
- if (state==CSO)
- {
- Context.strokeStyle="#FFCC33";
- Context.lineWidth=2;
- Context.strokeRect(Toolbar.x+ x+2, Toolbar.y+ y+2,width-4,height-4);
- }
- }
- function ChangeState(NewState)
- {
- state=NewState;
- Clear();
- RenderButton();
- }
主工具条TToolbar
- function TToolbar(Canvas, x, y, width, height) {
- var Context = Canvas.getContext('2d');
- this.Canvas = Canvas;
- this.x = x;
- this.y = y;
- this.width = width;
- this.height = height;
- var CurrentShapeProperty;
- var BorderColor;
- btnList = new Array();
- btnCounter = 0;
- Create();
- }
首先我们来看一下TToolbar的建立参数和成员变量
Canvas是工具条的图象载体,与用户交互的UI元素. x,y 为工具条在画布(Canvas) 上的偏移量,width,height分别为工具条的宽度和高度.
定义画布的上下文
var Context = Canvas.getContext('2d');
CurrentShapeProperty 用于记录选择的一些图形属性 如画笔的宽度,颜色等.
TToolbar负责做两件重要的工作
1.判断鼠标移动到了哪个按钮或者鼠标点击了哪个按钮.
利用 InstallEvents 绑定工具条的画布Canvas鼠标事件.
mousemove函数逐个判断当前工具条所管理的按钮是否获得了鼠标焦点. 如果当前鼠标移到了该按钮上,将该按钮的图标设为相应图标(在testHit函数中).其余图标设置为普通状态.
mousedown 函数逐个判断当前工具条所管理的按钮是否获得了鼠标点击.如果是颜色按钮则将当前选中的颜色值拷贝到大颜色按钮.
- mousemove = function(event) {
- var Current = null;
- for (var i = 0; i < btnList.length; i++) {
- if (btnList[i].testHit(event.clientX, event.clientY) == true)
- Current = btnList[i];
- }
- if (Current != null) {
- for (var i = 0; i < btnList.length; i++) {
- if ((btnList[i] != Current) && (btnList[i].getisChecked() == false))
- btnList[i].setNormal();
- }
- }
- };
- mousedown = function(evnet) {
- var Current = null;
- for (var i = 0; i < btnList.length; i++) {
- if (btnList[i].testMouseDown(event.clientX, event.clientY) == true)
- Current = btnList[i];
- }
- if (Current != null) {
- for (var i = 0; i < btnList.length; i++) {
- if (Current.getGroup() == btnList[i].getGroup()) {
- if (btnList[i] != Current)
- btnList[i].setNormal();
- }
- }
- if (Current.getGroup()==3)
- {
- var Color=Current.Command();
- ColorSelected(Color);
- }
- }
- };
- //安装鼠标移动、点击等方法
- this.InstallEvents = function() {
- Canvas.onmousemove = function(event) {
- mousemove(event);
- };
- Canvas.onmousedown = function(event) {
- mousedown(event);
- };
- };
另外我之前想用以下方法来绑定鼠标事件,没有成功请帮看一下问题出在哪里,谢谢
- function AddEvent(element, eventName, eventHandler) {
- window.alert( typeof element.addEventListener);
- if ( typeof element.addEventListener != "undefined") {
- window.alert(eventHandler);
- element.addEventListener(eventName, eventHandler, false);
- window.alert(element.onmousemove);
- } else
- element.attachEvent(eventName, eventHandler);
- }
- //安装鼠标移动、点击等方法
- this.InstallEvents = function() {
- AddEvent(Canvas,"onmousemove",this.mousemove);
- AddEvent(Canvas,"onmousedown",this.mousedown);
- };
2.管理画图的命令(TComand)
建立绘图命令会在后续的章节进行介绍.
- this.getNewCommand = function(DisplayCanvas) {
- for (var i = 0; i < btnList.length; i++) {
- if (btnList[i].getGroup() == 1) {
- if (btnList[i].getisChecked()) {
- var commandId = btnList[i].Command();
- var command = new TCommand(DisplayCanvas, commandId);
- return command;
- }
- }
- }
- return null;
- };
工具条对象完整代码(TToolbar)
- function TToolbar(Canvas, x, y, width, height) {
- var Context = Canvas.getContext('2d');
- this.Canvas = Canvas;
- this.x = x;
- this.y = y;
- this.width = width;
- this.height = height;
- var CurrentShapeProperty;
- var BorderColor;
- btnList = new Array();
- btnCounter = 0;
- Create();
- // InstallEvents();
- function Create() {
- Context.strokeStyle = "black";
- Context.lineWidth = "2";
- Context.strokeRect(x, y, width, height);
- }
- this.AddButton = function(button) {
- btnList[btnCounter++] = button;
- };
- function AddEvent(element, eventName, eventHandler) {
- window.alert( typeof element.addEventListener);
- if ( typeof element.addEventListener != "undefined") {
- window.alert(eventHandler);
- element.addEventListener(eventName, eventHandler, false);
- window.alert(element.onmousemove);
- } else
- element.attachEvent(eventName, eventHandler);
- }
- mousemove = function(event) {
- var Current = null;
- for (var i = 0; i < btnList.length; i++) {
- if (btnList[i].testHit(event.clientX, event.clientY) == true)
- Current = btnList[i];
- }
- if (Current != null) {
- for (var i = 0; i < btnList.length; i++) {
- if ((btnList[i] != Current) && (btnList[i].getisChecked() == false))
- btnList[i].setNormal();
- }
- }
- };
- mousedown = function(evnet) {
- var Current = null;
- for (var i = 0; i < btnList.length; i++) {
- if (btnList[i].testMouseDown(event.clientX, event.clientY) == true)
- Current = btnList[i];
- }
- if (Current != null) {
- for (var i = 0; i < btnList.length; i++) {
- if (Current.getGroup() == btnList[i].getGroup()) {
- if (btnList[i] != Current)
- btnList[i].setNormal();
- }
- }
- if (Current.getGroup()==3)
- {
- var Color=Current.Command();
- ColorSelected(Color);
- }
- }
- };
- //安装鼠标移动、点击等方法
- this.InstallEvents = function() {
- //AddEvent(Canvas,"onmousemove",this.mousemove);
- //AddEvent(Canvas,"onmousedown",this.mousedown);
- //Canvas.onmousemove=this.mousemove;
- Canvas.onmousemove = function(event) {
- mousemove(event);
- };
- Canvas.onmousedown = function(event) {
- mousedown(event);
- };
- };
- this.setBorderColorButton=function(ColorButton)
- {
- BorderColor=ColorButton;
- };
- function ColorSelected (color) {
- BorderColor.setColor(color);
- }
- this.getNewCommand = function(DisplayCanvas) {
- for (var i = 0; i < btnList.length; i++) {
- if (btnList[i].getGroup() == 1) {
- if (btnList[i].getisChecked()) {
- var commandId = btnList[i].Command();
- var command = new TCommand(DisplayCanvas, commandId);
- return command;
- }
- }
- }
- return null;
- };
- this.getShapeProperty = function() {
- if (typeof CurrentShapeProperty=="undefined")
- CurrentShapeProperty = new TShapeProperty();
- CurrentShapeProperty.setLineColor(BorderColor.Command());
- for (var i = 0; i < btnList.length; i++) {
- if (btnList[i].getGroup() == 2) {
- if (btnList[i].getisChecked()) {
- CurrentShapeProperty.setLineWidth(btnList[i].Command());
- }
- }
- }
- return CurrentShapeProperty;
- };
- }
图片按钮完整代码(TImageButton)
- function TImageButton(Command, NormalSrc, MouseOnSrc, MouseDownSrc, x, y, width, height, Toolbar, group) {
- var command = Command;
- var NormalSrc = NormalSrc;
- var MouseOnSrc = MouseOnSrc;
- var MouseDownSrc = MouseDownSrc;
- var x = x;
- var y = y;
- var width = width;
- var height = height;
- var Canvas = Toolbar.Canvas;
- var Context = Canvas.getContext("2d");
- var CSN = "Normal";
- var CSO = "MouseOn";
- var CSD = "MouseDown";
- var state = CSN;
- var Group = group;
- var image = new Image();
- CreateButton();
- function CreateButton() {
- LoadImage(NormalSrc);
- }
- function Absx() {
- return Canvas.offsetLeft + Toolbar.x + x;
- };
- function Absy() {
- return Canvas.offsetTop + Toolbar.y + y;
- };
- function PointIn(testx, testy) {
- if ((testx > Absx()) && (testx < (Absx() + width)) && (testy > Absy()) && (testy < (Absy() + height))) {
- return true;
- } else
- return false;
- };
- function Clear() {
- Context.clearRect(Toolbar.x + x, Toolbar.y + y, width, height);
- }
- function LoadImage(newsrc) {
- image.src = newsrc;
- if (image.complete) {
- RenderImage(image);
- } else
- image.onload = function() {
- RenderImage(image);
- };
- }
- function RenderImage(image) {
- Context.drawImage(image, Toolbar.x + x, Toolbar.y + y, width, height);
- }
- function ChangeState(NewState) {
- state = NewState;
- Clear();
- if (NewState == CSN)
- LoadImage(NormalSrc);
- else if (NewState == CSO)
- LoadImage(MouseOnSrc);
- else if (NewState == CSD)
- LoadImage(MouseDownSrc);
- }
- this.testHit = function(dx, dy) {
- if (PointIn(dx, dy)) {
- if (state == CSN) {
- ChangeState(CSO);
- }
- return true;
- }
- return false;
- };
- this.OnClick = function() {
- };
- this.testMouseDown = function(dx, dy) {
- if (PointIn(dx, dy)) {
- ChangeState(CSD);
- this.OnClick();
- return true;
- }
- return false;
- };
- this.getisChecked = function() {
- return (state == CSD);
- };
- this.Command = function() {
- return command;
- };
- this.MoveOn = function() {
- return (state == CSO);
- };
- this.setNormal = function() {
- ChangeState(CSN);
- };
- this.getGroup = function() {
- return Group;
- };
- }
颜色选择框的完整代码(TColorButton)
- <span style="font-size:12px;">function TColorButton(Command,
- x,
- y,
- width,
- height,
- Toolbar,
- group)
- {
- var command=Command;
- var x=x;
- var y=y;
- var width=width;
- var height=height;
- var Canvas=Toolbar.Canvas;
- var Context=Canvas.getContext("2d");
- var CSN="Normal";
- var CSO="MouseOn";
- var CSD="MouseDown";
- var state=CSN;
- var Group=group;
- CreateButton();
- function CreateButton()
- {
- RenderButton();
- }
- function Absx()
- {
- return Canvas.offsetLeft+Toolbar.x+x;
- };
- function Absy()
- {
- return Canvas.offsetTop+Toolbar.y+y;
- };
- function PointIn (testx,testy)
- {
- if ((testx>Absx())&&(testx<(Absx()+width))
- &&(testy>Absy()) && (testy<(Absy()+height)))
- {
- return true;
- }
- else
- return false;
- };
- function Clear()
- {
- Context.clearRect(Toolbar.x+ x,Toolbar.y+ y,width,height);
- }
- function RenderButton()
- {
- Context.fillStyle=command;
- Context.fillRect(Toolbar.x+ x, Toolbar.y+ y,width,height);
- if (state==CSO)
- {
- Context.strokeStyle="#FFCC33";
- Context.lineWidth=2;
- Context.strokeRect(Toolbar.x+ x+2, Toolbar.y+ y+2,width-4,height-4);
- }
- }
- function ChangeState(NewState)
- {
- state=NewState;
- Clear();
- RenderButton();
- }
- this.testHit=function(dx,dy)
- {
- if (PointIn(dx,dy))
- {
- if (state==CSN)
- {
- ChangeState(CSO);
- }
- return true;
- }
- return false;
- };
- this.testMouseDown=function(dx,dy)
- {
- if (PointIn(dx,dy))
- {
- ChangeState(CSD);
- return true;
- }
- return false;
- };
- this.getisChecked=function()
- {
- return (state==CSD);
- };
- this.Command=function()
- {
- return command;
- };
- this.MoveOn=function()
- {
- return (state==CSO);
- };
- this.setNormal=function()
- {
- ChangeState(CSN);
- };
- this.getGroup=function()
- {
- return Group;
- };
- this.setColor=function(color)
- {
- command=color;
- Context.fillStyle=command;
- Context.fillRect(Toolbar.x+ x, Toolbar.y+ y,width,height);
- };
- }