Use canvas to implement the paint program. (reproduced in the source and the author AH)
This time the main update features:
Newly added graphics: rectangle, circle, rounded rectangle
The selection of stroke color and fill color is realized.
The code was re-organized using MVC-like patterns.
M layer: The Path planning code for special graphics consists of path planning only, no style design.
V Layer: Design style, call path planning code, actually draw pattern. Complete the fill and stroke here.
C Layer: Judging the selection box content, calling different actual drawing code
Other: event handling and auxiliary calculation functions, etc.
Insufficient: Feel the code structure is still not good enough, sure enough, I am useless object-oriented?
Here are the following:
Here is the source code:
① Ontology HTML5 Code
<!docutype html><!--Date 2015-1-27--by mikuscallion starting at csdn> ② Special Graphics Path Planning code
Dashed function Dashedlinepp (context,x1,y1,x2,y2,dashlength) {//horizontal length var deltax = x2-x1; Vertical length var deltay = y2-y1; Number of dashed lines var numdashed = Math.floor (math.sqrt (Deltax*deltax+deltay*deltay)/dashlength); Start path planning Context.beginpath (); for (var i=0; i<numdashed;i++) {//This notation is too strong//(deltax/numdashed) refers to the length of the dashed line context[i%2===0? "MoveTo": "LineTo"] (x1+ (deltax/numdashed) *i,y1+ (deltay/numdashed) *i); }}//Rounded Rectangle function roundedrectpp (Context,cornerx,cornery,width,height,cornerradius) {//Start path planning context.beginpath (); Set the start position (not the vertex is to not produce a small tail)//In order not to produce a small tail to make a judgment if (Width > 0) {context.moveto (cornerx+cornerradius,cornery); }else{Context.moveto (cornerx-cornerradius,cornery); }//upper right corner context.arcto (Cornerx+width,cornery,cornerx+width,cornery+height,cornerradius); Bottom right Corner (note: Due to the arcto movement, the current point has reached: Cornerx+width,cornery+cornerradius, so do not set MoveTo) Context.arcto (Cornerx+width, Cornery+height,cornerx,cornery+height, Cornerradius); Lower left corner context.arcto (Cornerx,cornery+height,cornerx,cornery,cornerradius); Upper left corner if (Width > 0) {context.arcto (Cornerx,cornery,cornerx+cornerradius,cornery,cornerradius); }else{Context.arcto (Cornerx,cornery,cornerx-cornerradius,cornery,cornerradius); }}//Grid line function GRIDPP (context,stepx,stepy) {//Start path planning context.beginpath (); Plot the x-axis grid//Note: Canvas draws a line at two pixel boundaries//due to the positioning mechanism, the 1px line will become 2px//So +0.5 for (Var i=stepx+0.5;i<context.canvas.width;i =I+STEPX) {//Open path//context.beginpath (); Context.moveto (i,0); Context.lineto (I,context.canvas.height); }//Draw y-axis grid for (Var i=stepy+0.5;i<context.canvas.height;i=i+stepy) {//context.beginpath (); Context.moveto (0,i); Context.lineto (Context.canvas.width,i); }};//axis function axespp (context,axesmargin,htspace,vtspace,ticklong) {function Mikuloc (locx,locy) {this.x = LocX ; This.y = Locy; } var OrigiNloc = new Mikuloc (Axesmargin, Context.canvas.height-axesmargin); var axesw = context.canvas.width-(axesmargin*2); var Axesh = context.canvas.height-(axesmargin*2); Context.beginpath (); X, Y axis planning horizontalaxispp (); VERTICALAXISPP (); X, Y axis label Planning verticalaxistickspp (); HORIZONTALAXISTICKSPP (); function horizontalaxispp () {Context.moveto (originloc.x, ORIGINLOC.Y); Context.lineto (originloc.x + AXESW, originloc.y); } function verticalaxispp () {Context.moveto (originloc.x, ORIGINLOC.Y); Context.lineto (originloc.x, Originloc.y-axesh); } function verticalaxistickspp () {var deltax; The y-coordinate of the current vertical tick var nowticky =originloc.y-vtspace; For (Var i=1;i<= (axesh/vtspace); i++) {if (i%5 = = = 0) {Deltax=ticklong; }else {DELTAX=TICKLONG/2; }//Move to the current tick start Context.moveto (originloc.x-deltax,nowticky); Context.lineto (Originloc.x+deltax,nowticky); Nowticky=nowticky-vtspace; }} function horizontalaxistickspp () {var deltay; var Nowtickx = Originloc.x+htspace; For (Var i=1;i<= (axesw/htspace); i++) {if (i%5 = = = 0) {DeltaY = Ticklong; }else{DeltaY = TICKLONG/2; } context.moveto (Nowtickx,originloc.y+deltay); Context.lineto (Nowtickx,originloc.y-deltay); Nowtickx = Nowtickx + htspace; }}};//Auxiliary Locator line function GUIDEWIRESPP (context,x,y) {Context.beginpath (); Drawhorizontalline (y); Drawverticalline (x); function Drawhorizontalline (y) {context.moveto (0,y+0.5); Context.lineto (context.canvas.width,y+0.5); } function Drawverticalline (x) {Context.moveto (x+0.5,0); Context.lineto (X+0.5,context.canvas.height); }}
③ drawing software main code
Vars--------------------------------------------------------var canvas =document.getelementbyid ("Canvas"), Context =canvas.getcontext ("2d"),//drawing surface variable drawingsurfaceimagedata,//mouse pressed related object MouseDown = {},//rubber Band Rectangle Object rubberbandrect = {},//current mouse coordinates loc ={}, Drag the identity variable dragging = false; CONTROLS//Erase canvas control var Eraseallbutton = document.getElementById ("Eraseallbutton"); The control of the axis var axescheckbox = document.getElementById ("Axescheckbox"); Control of the grid line var Gridcheckbox = document.getElementById ("Gridcheckbox"); The control of the auxiliary line var guidewirescheckbox = document.getElementById ("Guidewirescheckbox"); The control of the line color var strokecolorselectbox =document.getelementbyid ("Strokecolorselectbox"); Line Style control var linetypeselectbox = document.getElementById ("Linetypeselectbox"); Control of line width var linewidthselectbox = document.getElementById ("Linewidthselectbox"); Pattern Fill Color Control var fillcolorselectbox = document.getElementById ("Fillcolorselectbox");//Auxiliary function--------------------------- -----------------------------------------------//Convert window coordinates to canvas coordinates function Windowtocanvas (x, y) { Gets the margin object of the canvas element var bbox = Canvas.getboundingclientrect (); Returns a Coordinate object//a JSON-like notation for return {x:x-bbox.left* (Canvas.width/bbox.width), Y:y-bbox.top* (Canvas.height/bbox.height)}; }//Save the current drawing surface data function Savedrawingsurface () {//Get drawing surface data from the context Drawingsurfaceimagedata = Co Ntext.getimagedata (0,0,canvas.width,canvas.height); }//Restores the current drawing surface function Restoredrawingsurface () {//restores the drawing surface data to the context Context.putimagedata (Drawin gsurfaceimagedata,0,0); }//Update rubber band rectangle function UpdaterubberbandRectangle () {//Get the width of the rectangle rubberbandrect.width = Math.Abs (loc.x-mousedown.x); Get the high rubberbandrect.height of the rectangle = Math.Abs (LOC.Y-MOUSEDOWN.Y); Gets the position of the rectangle vertex (left,top)//If the mouse-pressed point (the starting point) is at the left of the current point//here draw one to understand if (loc.x > Mousedown.x) { Rubberbandrect.left = mousedown.x; }else{rubberbandrect.left = loc.x; } if (Loc.y > mousedown.y) {rubberbandrect.top = MOUSEDOWN.Y; }else{rubberbandrect.top = loc.y; }}//Draw the rubber band Rectangle diagonal (Controller) function Drawrubberbandshape () {//Get current line type var Linetype = Linetypeselectbox.value; Gets the current line color var linecolor = Strokecolorselectbox.value; Gets the current line width var linewidth = linewidthselectbox.value; Gets the current fill color var fillcolor = Fillcolorselectbox.value; Have changedThe context brush property is to do brush protection context.save (); Context.strokestyle = LineColor; Context.linewidth = linewidth; Context.fillstyle = FillColor; Note Path planning, style planning separate if (linetype = = = "Solid") {Drawlinewithrubberbandrect (); }else if (Linetype = = = "Dashed") {Drawdashedlinewithrubberbandrect (5); }else if (Linetype = = = "Arc") {Drawarcwithrubberbandrect (); }else if (Linetype = = = "Rect") {drawrectwithrubberbandrect (); }else if (Linetype = = = "Roundedrect") {Drawroundedrectwithrubberbandrect (20); } context.restore (); }//Update rubber band Rectangle + diagonal Function Updaterubberband () {updaterubberbandrectangle (); Drawrubberbandshape (); }//Initialize function initialization () {//Clear canvas context.clearrect (0,0,canvas.width,canvas. height); The color of the drawing grid and coordinates is the default if (axescheckbox.checked) {drawaxes (40); } if (gridcheckbox.checked) {DrawGrid (10,10); }}//actual drawing function------------------------------------------------------------------------------//Draw a line with a rubber band rectangle function Drawlinewithrubberbandrect () {Context.beginpath (); Context.moveto (MOUSEDOWN.X,MOUSEDOWN.Y); Context.lineto (LOC.X,LOC.Y); Context.stroke (); }//Use a rubber band rectangle to draw a circle function Drawarcwithrubberbandrect () {//Circle radius var radius; var h = rubberbandrect.height; var w = rubberbandrect.width; Using the Pythagorean theorem to calculate the hypotenuse is the radius radius=math.sqrt (h*h+w*w); actually draw Context.beginpath (); Context.arc (Mousedown.x,mousedown.y,radius,0,math.pi*2,false); Context.stroke (); Context.fill (); }//Use a rubber band rectangle to draw a rectangle (that is, draw yourself) function drawrectwIthrubberbandrect () {Context.beginpath (); Context.rect (Rubberbandrect.left,rubberbandrect.top,rubberbandrect.width,rubberbandrect.height); Context.stroke (); Context.fill (); }//Draw a dashed function drawdashedlinewithrubberbandrect (dashlength) {//route planning Dashedli with a rubber band rectangle Nepp (context,mousedown.x,mousedown.y,loc.x,loc.y,dashlength); Context.stroke (); }//Draw rounded Rectangle function drawroundedrectwithrubberbandrect (RADIUS) {//with a rubber-band rectangle using a rubber band rectangle to make the path planning of the rounded rectangle ROUNDEDRECTPP (Context,rubberbandrect.left,rubberbandrect.top,rubberbandrect.width,rubberbandrect.height,radius ); Context.stroke (); Context.fill (); }//Draw grid line function DrawGrid (stepx,stepy) {//Style settings context.save (); Context.strokestyle = "Lightgray"; Context.linewidth = 0.5; GRIDPP (context,stepx,stepy); Context.stroke (); Context.restore (); }//Draw axis function drawaxes (axesmargin) {context.save (); Context.strokestyle = "#a2a2a2"; Context.linewidth = 1; AXESPP (context,40,10,10,10); Context.stroke (); Context.restore (); }//Draw auxiliary locator line function drawguidewires (x, y) {context.save (); Context.strokestyle = "Red"; Context.linewidth = 0.5; GUIDEWIRESPP (Context,x,y); Context.stroke (); Context.restore (); }//event hander-----------------------------------------------------Canvas.onmousedown = function (e) {lo C =windowtocanvas (E.clientx,e.clienty); E.preventdefault (); Savedrawingsurface (); mousedown.x = loc.x; MOUSEDOWN.Y = LOC.Y; dragging = true; } Canvas.onmousemove = function (e) {if (dragging) {e.preventdefault (); loc = Windowtocanvas (E.clientx,e.clienty); Restoredrawingsurface (); Updaterubberband (); } if (dragging&&guidewirescheckbox.checked) {drawguidewires (LOC.X,LOC.Y); }} canvas.onmouseup = function (e) {loc = Windowtocanvas (E.clientx,e.clienty); Restoredrawingsurface (); Updaterubberband (); dragging = false; }//The operation that needs to be erased requires reinitialization of Eraseallbutton.onclick = function (e) {context.clearrect (0,0,canvas.wid Th,canvas.height); Initialization (); Savedrawingsurface (); } Axescheckbox.onchange = function (e) {initialization (); } Gridcheckbox.onchange = function (e) {initialization (); }//mian----------------------------------------------initialization ();
Canvas---Canvas drawing, rounded rectangles, circles, rectangles, graphics fills, MVC mode re-integration Code Edition