Canvas版实现画图、虚线、辅助线、线条颜色、线条宽度
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Canvas实现画图、虚线、辅助线、线条颜色、线条宽度,整合加强版
使用Canv as实现画图程序。
本次更新主要实现了一下功能:
虚线实线的选择、辅助线、线条颜色选择、线条宽度选择
进一步整理了下代码,发现了不少很有用的写法,具体看下面。
效果截图:
源代码:
①HTML代码
[html]view plainc opy
1.<!docuty pe html>
2.<!--date 2014-12-28-->
3.<html>
4.<head>
5.<meta http-equiv="conten t-type" conten t="text/html; charse t=utf-8" />
6.<styletype="text/css">
7. canvas{
8. backgr ound-color: rgb(247, 247, 247);
9. margin-top: 10px;
10. }
11.</style>
12.</head>
13.<body>
14.<div class="contro ls">
15.线条类型<select id="lineTy peSel ectBo x">
16.<option value="solid">实线</option>
17.<option value="dashed">虚线</option>
18.</select>
19.线条颜色<select id="stroke Color Selec tBox">
20.<option value="black">black</option>
21.<option value="red">red</option>
22.<option value="blue">blue</option>
23.</select>
24.线条宽度<select id="lineWi dthSe lectB ox">
25.<option value="1">1</option>
26.<option value="2">2</option>
27.<option value="4">4</option>
28.</select>
29.网格线<inputid="gridCh eckBo x" type="checkb ox" checke d="checke d" >
30.坐标轴<inputid="axesCh eckBo x" type="checkb ox" checke d="checke d" >
31.辅助线
<inputid="guideW iresC heckB ox" type="checkb ox" checke d="checke d" >
32.<inputtype="button" value="清除画布ww w.qqpar" id="eraseA llBut ton">
33.</div>
34.<!--canvas默认大小300*150-->
35.<canvas id="canvas" width="800" height="500">
36.</canvas>
37.</body>
38.<!--导入绘制坐标、网格的js文件-->
39.<script type = "text/javasc ript"src ="mikuCa nvasA xes.js"></script>
40.<!--导入绘制虚线的js文件-->
41.<script type = "text/javasc ript"src ="mikuCa nvasL ine.js"></script>
42.<!--导入主要绘图js文件-->
43. <!--
44.全局变量定义
45.函数:窗口坐标转换为Canv as坐标、保存\还原当前绘图表面数据、橡皮筋法相关函数、绘
制辅助线相关函数、初始化函数
46.事件处理:鼠标down,move,up事件、按钮点击事件、单选框变化事件
47. -->
48.<script type = "text/javasc ript"src ="mikuCa nvasP aintA ppMai n.js"></script>
49.</html>
②绘制坐标轴与网格
[html]view plainc opy
1.<!docuty pe html>
2.<!--date 2014-12-28-->
3.<html>
4.<head>
5.<meta http-equiv="conten t-type"conten t="text/html; charse t=utf-8"/>
6.<styletype="text/css">
7. canvas{
8.
9. }
10.</style>
11.<script type = "text/javasc ript"src ="mikuCa nvasA xes.js"></script>
12.</head>
13.<body>
14.<div class="contro ls">
15.网格线<inputid="gridCh eckBo x"type="checkb ox"checke d="checke d">
16.坐标轴<inputid="axesCh eckBo x"type="checkb ox"checke d="checke d">
17.<inputtype="button"value="清除画布"id="eraseA llBut ton">
18.</div>
19.<!--canvas默认大小300*150-->
20.<canvas id="canvas"width="800"height="500">
21.</canvas>
22.</body>
23.<script type="text/javasc ript">
24. //Vars--------------------------------------------------------
25. var canvas =docume nt.getEle mentB yId("canvas"),
26.contex t =canvas.getCon text("2d"),
27. //正在绘制的绘图表面变量
28. drawin gSurf aceIm ageDa ta,
29. //鼠标按下相关对象
30.moused own = {},
31. //橡皮筋矩形对象
32.rubber bandR ect = {},
33. //拖动标识变量
34.draggi ng = false;
35. //控制对象
36. var eraseA llBut ton = docume nt.getEle mentB yId("eraseA llBut ton"),
37.axesCh eckBo x = docume nt.getEle mentB yId("axesCh eckBo x"),
38. //检测axes Check Box是否被选中
39.haveAx es = axesCh eckBo x.checke d;
40. var gridCh eckBo x = docume nt.getEle mentB yId("gridCh eckBo x");
41. var haveGr id = gridCh eckBo x.checke d;
42. //Functi ons---------------------------------------------------
43. //将窗口坐标转换为Can vas坐标
44. //传入参数:窗口坐标(x,y)
45. functi on window ToCan vas(x,y){
46. //获取canv as元素的边距对象
47. var bbox = canvas.getBou nding Clien tRect();
48. //返回一个坐标对象
49. //类似json的一种写法
50. return {
51. x : x - bbox.left*(canvas.width/bbox.width),
52. y : y - bbox.top*(canvas.height/bbox.height)
53. };
54. }
55. //保存当前绘图表面数据
56. functi on saveDr awing Surfa ce(){
57. //从上下文中获取绘图表面数据
58.drawin gSurf aceIm ageDa ta = contex t.getIma geDat a(0,0,canvas.width,canvas.heigh
t);
59. }
60. //还原当前绘图表面
61. functi on restor eDraw ingSu rface(){
62. //将绘图表面数据还原给上下文
63. contex t.putIma geDat a(drawin gSurf aceIm ageDa ta,0,0);
64. }
65. //橡皮筋相关函数
66.
67. //更新橡皮筋矩形+对角线
68. //传入参数:坐标对象lo c
69. functi on update Rubbe rband(loc){
70. update Rubbe rband Recta ngle(loc);
71. drawRu bberb andSh ape(loc);
72. }
73. //更新橡皮筋矩形
74. //传入参数:坐标对象lo c
75. functi on update Rubbe rband Recta ngle(loc){
76. //获得矩形的宽
77.rubber bandR ect.width= Math.abs(loc.x - moused own.x);
78. //获得矩形的高
79.rubber bandR ect.height = Math.abs(loc.y - moused own.y);
80. //获得矩形顶点的位置(left,top)
81. //如果鼠标按下的点(起点)在当前点的的左侧
82. //这里画一下图就懂了
83. if(loc.x > moused own.x){
84.rubber bandR ect.left = moused own.x;
85. }else{
86.rubber bandR ect.left = loc.x;
87. }
88. if(loc.y > moused own.y){
89.rubber bandR ect.top = moused own.y;
90. }else{
91.rubber bandR ect.top = loc.y;
92. }
93. }
94. //绘制橡皮筋矩形的对角线
95. //传入参数:坐标对象lo c
96. functi on drawRu bberb andSh ape(loc){
97. //alert("draw");
98. contex t.beginP ath();
99. contex t.moveTo(moused own.x,moused own.y);
100. contex t.lineTo(loc.x,loc.y);
101. contex t.stroke();
102. }
103. //事件处理----------------------------------------------------- 104.canvas.onmous edown = functi on(e){
105. var loc =window ToCan vas(e.client X,e.client Y);
106. e.preven tDefa ult();
107. saveDr awing Surfa ce();
108.moused own.x = loc.x;
109.moused own.y = loc.y;
110.draggi ng = true;
111. }
112.
113.canvas.onmous emove = functi on(e){
114. var loc;
115. if(draggi ng){
116. e.preven tDefa ult();
117.loc = window ToCan vas(e.client X,e.client Y);
118. restor eDraw ingSu rface();
119. update Rubbe rband(loc);
120. }
121. }
122.canvas.onmous eup = functi on(e){
123.loc = window ToCan vas(e.client X,e.client Y);
124. restor eDraw ingSu rface();
125. update Rubbe rband(loc);
126.draggi ng = false;
127. }
128.eraseA llBut ton.onclic k = functi on(e){
129. contex t.clearR ect(0,0,canvas.width,canvas.height);
130. initia lizat ion();
131. saveDr awing Surfa ce();
132. }
133.axesCh eckBo x.onchan ge = functi on(e){
134.haveAx es = axesCh eckBo x.checke d;
135. initia lizat ion();
136. }
137.gridCh eckBo x.onchan ge = functi on(e){
138.haveGr id = gridCh eckBo x.checke d;
139. initia lizat ion();
140. }
141. //Initia lizat ion---------------------------------------------- 142. functi on initia lizat ion(){
143. //清除画布
144. contex t.clearR ect(0,0,canvas.width,canvas.height);
145. if(haveAx es){
146. drawAx es(contex t,40);
147. }
148. if(haveGr id){
149. drawGr id(contex t,10,10);
150. }
151. }
152. //入口
153. initia lizat ion();
154.</script>
155.</html>
②绘制网格与坐标轴的js文件
[javasc ript]view plainc opy
1.//Classe s----------------------------------------------------
2.functi on mikuLo c(locX,locY){
3.this.x = locX;
4.this.y = locY;
5.}
6.//Conten ts---------------------------------------------------
7.var GRID_S TYLE = "lightg ray",
8. GRID_L INE_W IDTH= 0.5;
9.
10.var AXES_S TYLE = "#a2a2a2",
11. AXES_L INE_W IDTH= 1,
12. VERTIC AL_TI CK_SP ACING = 10,
13. HORIZO NTAL_TIKE_SPACI NG = 10,
14. TICK_W IDTH= 10;
15.//Functi on---------------------------------------------------
16.//绘制网格
17.//传入参数为:绘图环境,x轴间隔,y轴间隔
18.functi on drawGr id(contex t,stepx,stepy){
19. contex t.save();
20. contex t.stroke Style = GRID_S TYLE;
21.//设置线宽为0.5
22. contex t.lineWi dth = GRID_L INE_W IDTH;
23.//绘制x轴网格
24.//注意:canvas在两个像素的边界处画线
25.//由于定位机制,1px的线会变成2px
26.//于是要+0.5
27.for(var i=stepx+0.5;i<contex t.canvas.width;i=i+stepx){
28.//开启路径
29. contex t.beginP ath();
30. contex t.moveTo(i,0);
31. contex t.lineTo(i,contex t.canvas.height);
32. contex t.stroke();
33. }
34.//绘制y轴网格
35.for(var i=stepy+0.5;i<contex t.canvas.height;i=i+stepy){
36. contex t.beginP ath();
37. contex t.moveTo(0,i);
38. contex t.lineTo(contex t.canvas.width,i);
39. contex t.stroke();
40. }
41. contex t.restor e();
42.};
43.//Functi on---------------------------------------------------
44.//绘制坐标轴
45.//传入参数为:绘图环境,坐标轴边距
46.functi on drawAx es(contex t,axesMa rgin){
47.//保存样式
48. contex t.save();
49.var origin Loc = new mikuLo c(axesMa rgin, contex t.canvas.height-axesMa rgin);
50.var axesW= contex t.canvas.width - (axesMa rgin*2),
51. axesH= contex t.canvas.height - (axesMa rgin*2);
52.//设置坐标绘图样式绘图样式
53. contex t.stroke Style = AXES_S TYLE;
54. contex t.lineWi dth = AXES_L INE_W IDTH;
55.//绘制x,y轴
56. drawHo rizon talAx is();
57. drawVe rtica lAxis();
58. drawVe rtica lAxis Ticks();
59. drawHo rizon talAx isTic ks();
60.//恢复样式
61. contex t.restor e();
62.
63.//绘制x轴
64.functi on drawHo rizon talAx is(){
65. contex t.beginP ath();
66. contex t.moveTo(origin Loc.x, origin Loc.y);
67. contex t.lineTo(origin Loc.x + axesW, origin Loc.y);
68. contex t.stroke();
69. }
70.//绘制y轴
71.functi on drawVe rtica lAxis(){
72. contex t.beginP ath();
73. contex t.moveTo(origin Loc.x, origin Loc.y);
74. contex t.lineTo(origin Loc.x, origin Loc.y - axesH);
75. contex t.stroke();
76. }
77.//绘制垂直轴小标标
78.functi on drawVe rtica lAxis Ticks(){
79.var deltaX;
80.//当前垂直ti ck的y轴坐标
81.var nowTic kY =origin Loc.y-VERTIC AL_TI CK_SP ACING;
82.for(var i=1;i<=(axesH/VERTIC AL_TI CK_SP ACING);i++){
83.if(i%5 === 0){
84. deltaX=TICK_W IDTH;
85. }else {
86. deltaX=TICK_W IDTH/2;
87. }
88. contex t.beginP ath();
89.//移动到当前的tick起点
90. contex t.moveTo(origin Loc.x-deltaX,nowTic kY);
91. contex t.lineTo(origin Loc.x+deltaX,nowTic kY);
92. contex t.stroke();
93. nowTic kY=nowTic kY-VERTIC AL_TI CK_SP ACING;
94. }
95. }
96.//绘制水平轴小标标
97.functi on drawHo rizon talAx isTic ks(){
98.var deltaY;
99.var nowTic kX = origin Loc.x+HORIZO NTAL_TIKE_SPACI NG;
100.for(var i=1;i<=(axesW/HORIZO NTAL_TIKE_SPACI NG);i++){ 101.if(i%5 === 0){
102. deltaY = TICK_W IDTH;
103. }else{
104. deltaY = TICK_W IDTH/2;
105. }
106. contex t.beginP ath();
107. contex t.moveTo(nowTic kX,origin Loc.y+deltaY);
108. contex t.lineTo(nowTic kX,origin Loc.y-deltaY);
109. contex t.stroke();
110. nowTic kX = nowTic kX + HORIZO NTAL_TIKE_SPACI NG;
111. }
112. }
113.};
③绘制虚线
[javasc ript]view plainc opy
1.//绘制虚线
2.//传入参数:上下文,起点,终点,虚线间隔
3.functi on drawDa shedL ine(contex t,x1,y1,x2,y2,dashLe ngth){
4.//运用三元表达式实现默认参数
5. dashLe ngth= dashLe ngth===undefi ned ? 5 : dashLe ngth;
6.//水平长度
7.var deltaX = x2 - x1;
8.//垂直长度
9.var deltaY = y2 - y1;
10.//虚线数量
11.var numDas hed = Math.floor(
12. Math.sqrt(deltaX*deltaX+deltaY*deltaY)/dashLe ngth
13. );
14.//开始绘制
15. contex t.beginP ath();
16.for(var i=0; i<numDas hed;i++){
17.//这种写法太强大了
18.//(deltaX/numDas hed)是指虚线的长度
19. contex t[i%2===0 ? "moveTo":"lineTo"](x1+(deltaX/numDas hed)*i,y1+(deltaY/nu
mDas hed)*i);
20. }
21.//要记得描线啊
22. contex t.stroke();
23.//结束绘制
24. contex t.closeP ath();
25.}
④主要绘图代码
[javasc ript]view plainc opy
1.//Vars--------------------------------------------------------
2.var canvas =docume nt.getEle mentB yId("canvas"),
3. contex t =canvas.getCon text("2d"),
4.//正在绘制的绘图表面变量
5. drawin gSurf aceIm ageDa ta,
6.//鼠标按下相关对象
7. moused own = {},
8.//橡皮筋矩形对象
9. rubber bandR ect = {},
10.//拖动标识变量
11. draggi ng = false;
12.
13.//控件
14.//擦除画布的控制
15.var eraseA llBut ton = docume nt.getEle mentB yId("eraseA llBut ton");
16.//坐标轴的控制
17.var axesCh eckBo x = docume nt.getEle mentB yId("axesCh eckBo x");
18.//网格线的控制
19.var gridCh eckBo x = docume nt.getEle mentB yId("gridCh eckBo x");
20.//辅助线的控制
21.var guideW iresC heckB ox = docume nt.getEle mentB yId("guideW iresC heckB ox");
22.//线条颜色的控制
23.var stroke Color Selec tBox=docume nt.getEle mentB yId("stroke Color Selec tBox");
24.//线条样式的控制
25.var lineTy peSel ectBo x = docume nt.getEle mentB yId("lineTy peSel ectBo x");
26.//线条宽度的控制
27.var lineWi dthSe lectB ox = docume nt.getEle mentB yId("lineWi dthSe lectB ox");
28.//Functi ons---------------------------------------------------
29.//将窗口坐标转换为Can vas坐标
30.//传入参数:窗口坐标(x,y)
31.functi on window ToCan vas(x,y){
32.//获取canv as元素的边距对象
33.var bbox = canvas.getBou nding Clien tRect();
34.//返回一个坐标对象
35.//类似json的一种写法
36.return {
37. x : x - bbox.left*(canvas.width/bbox.width),
38. y : y - bbox.top*(canvas.height/bbox.height)
39. };
40. }
41.//保存当前绘图表面数据
42.functi on saveDr awing Surfa ce(){
43.//从上下文中获取绘图表面数据
44. drawin gSurf aceIm ageDa ta = contex t.getIma geDat a(0,0,canvas.width,canvas.heigh
t);
45. }
46.//还原当前绘图表面
47.functi on restor eDraw ingSu rface(){
48.//将绘图表面数据还原给上下文
49. contex t.putIma geDat a(drawin gSurf aceIm ageDa ta,0,0);
50. }
51.//橡皮筋相关函数
52.
53.//更新橡皮筋矩形+对角线
54.//传入参数:坐标对象lo c
55.functi on update Rubbe rband(loc){
56. update Rubbe rband Recta ngle(loc);
57. drawRu bberb andSh ape(loc);
58. }
59.//更新橡皮筋矩形
60.//传入参数:坐标对象lo c
61.functi on update Rubbe rband Recta ngle(loc){
62.//获得矩形的宽
63. rubber bandR ect.width= Math.abs(loc.x - moused own.x);
64.//获得矩形的高
65. rubber bandR ect.height = Math.abs(loc.y - moused own.y);
66.//获得矩形顶点的位置(left,top)
67.//如果鼠标按下的点(起点)在当前点的的左侧
68.//这里画一下图就懂了
69.if(loc.x > moused own.x){
70. rubber bandR ect.left = moused own.x;
71. }else{
72. rubber bandR ect.left = loc.x;
73. }
74.if(loc.y > moused own.y){
75. rubber bandR ect.top = moused own.y;
76. }else{
77. rubber bandR ect.top = loc.y;
78. }
79. }
80.//绘制橡皮筋矩形的对角线
81.//传入参数:坐标对象lo c
82.functi on drawRu bberb andSh ape(loc){
83.//获取当前线条类型
84.var lineTy pe = lineTy peSel ectBo x.value;
85.//获取当前线条颜色
86.var lineCo lor = stroke Color Selec tBox.value;
87.//获取当前线条宽度
88.var lineWi dth = lineWi dthSe lectB ox.value;
89.//有改变con text画笔属性就要做画笔保护
90. contex t.save();
91. contex t.stroke Style = lineCo lor;
92. contex t.lineWi dth = lineWi dth;
93.if(lineTy pe === "solid"){
94.//alert("draw");
95.//注意重新开始路径
96. contex t.beginP ath();
97. contex t.moveTo(moused own.x,moused own.y);
98.//这里可以更改成画虚线
99. contex t.lineTo(loc.x,loc.y);
100. contex t.stroke();
101. }else if(lineTy pe === "dashed"){
102. drawDa shedL ine(contex t,moused own.x,moused own.y,loc.x,loc.y); 103. }
104. contex t.restor e();
105. }
106.
107.//绘制辅助用的线-------------------------
108.//绘制水平线
109.functi on drawHo rizon talLi ne(y){
110. contex t.beginP ath();
111. contex t.moveTo(0,y+0.5);
112. contex t.lineTo(contex t.canvas.width,y+0.5);
113. contex t.stroke();
114. }
115.//绘制垂直线
116.functi on drawVe rtica lLine(x){
117. contex t.beginP ath();
118. contex t.moveTo(x+0.5,0);
119. contex t.lineTo(x+0.5,contex t.canvas.height);
120. contex t.stroke();
121. }
122.//绘制辅助用的线
123.functi on drawGu ideWi res(x,y){
124.//画笔保护
125. contex t.save();
126. contex t.stroke Style = "red";
127. contex t.lineWi dth = 0.5;
128. drawHo rizon talLi ne(y);
129. drawVe rtica lLine(x);
130. contex t.restor e();
131. }
132.//初始化函数
133.functi on initia lizat ion(){
134.//清除画布
135. contex t.clearR ect(0,0,canvas.width,canvas.height); 136.//绘制网格与坐标的颜色是默认的
137.if(axesCh eckBo x.checke d){
138. drawAx es(contex t,40);
139. }
140.if(gridCh eckBo x.checke d){
141. drawGr id(contex t,10,10);
142. }
143. }
144.//EventHander-----------------------------------------------------145. canvas.onmous edown = functi on(e){
146.var loc =window ToCan vas(e.client X,e.client Y);
147. e.preven tDefa ult();
148. saveDr awing Surfa ce();
149. moused own.x = loc.x;
150. moused own.y = loc.y;
151. draggi ng = true;
152. }
153.
154. canvas.onmous emove = functi on(e){
155.var loc;
156.if(draggi ng){
157. e.preven tDefa ult();
158. loc = window ToCan vas(e.client X,e.client Y);
159. restor eDraw ingSu rface();
160. update Rubbe rband(loc);
161. }
162.if(draggi ng&&guideW iresC heckB ox.checke d){
163. drawGu ideWi res(loc.x,loc.y);
164. }
165. }
166. canvas.onmous eup = functi on(e){
167. loc = window ToCan vas(e.client X,e.client Y);
168. restor eDraw ingSu rface();
169. update Rubbe rband(loc);
170. draggi ng = false;
171. }
172.
173.//需要擦除的操作需要重新初始化
174. eraseA llBut ton.onclic k = functi on(e){
175. contex t.clearR ect(0,0,canvas.width,canvas.height);
176. initia lizat ion();
177. saveDr awing Surfa ce();
178. }
179. axesCh eckBo x.onchan ge = functi on(e){
180. initia lizat ion();
181. }
182. gridCh eckBo x.onchan ge = functi on(e){
183. initia lizat ion();
184. }
185.//Mian----------------------------------------------
186. initia lizat ion();
本文由CSDN博客,博客ID:MIKUSc allio n原创发布,转载请注明出处!。