使用原生JavaScript的Canvas实现拖拽式图形绘制,支持画笔、线条、箭头、三角形、矩形、平行四边形、梯形以及多边形和圆形,不依赖任何库和插件,有演示demo
前言
需要用到图形绘制,没有找到完整的图形绘制实现,所以自己实现了一个 - -
一、实现的功能
1、基于oop思想构建,支持坐标点、线条(由坐标点组成,包含方向)、多边形(由多个坐标点组成)、圆形(包含圆心坐标点和半径)等实体
2、原生JavaScript实现,不依赖任何第三方js库和插件
3、多图形绘制(支持画笔、线条、箭头、三角形、矩形、平行四边形、梯形以及多边形和圆形绘制)
4、拖拽式绘制(鼠标移动过程中不断进行canvas重绘)
5、图片绘制(作为背景图片时重绘会发生闪烁现象,暂时有点问题,后面继续完善)
5、清空绘制功能
6、新版本优化绘制性能(使用共享坐标变量数组,减少了大量的对象创建操作)
7、新版本支持箭头绘制功能
二、完整实现代码
- DrawingTools =(function(){
- //公共方法
- var getDom=function(id){return document.getElementById(id)};
- var isNull=function(s){return s==undefined||typeof(s)=='undefined'||s==null||s=='null'||s==''||s.length<1};
- var hideDefRM=function(){document.oncontextmenu=function(){return false}};//屏蔽浏览器默认鼠标事件
- /**绘图容器*/
- var cbtCanvas;
- /**绘图对象*/
- var cxt;
- /**绘制的图形列表*/
- var shapes=new Array();
- var graphkind={'cursor':0,'pen':1,'line':2,'trian':3,'rect':4,'poly':5,'circle':6,'arrow':21,'parallel':41,'trapezoid':42};
- //背景图片绘制配置
- var bgPictureConfig={
- pic:null,//背景图片地址或路径
- repaint:true,//是否作为永久背景图,每次清除时会进行重绘
- };
- //加载并绘制图片(src:图片路径或地址),默认重绘背景图
- var loadPicture=function(src){
- if(isNull(bgPictureConfig.repaint)||bgPictureConfig.repaint){bgPictureConfig.pic=src}
- var img = new Image();
- img.onload = function(){cxt.drawImage(img,0,0)}
- img.src =src;
- }
- //绘图基础配置
- var paintConfig={lineWidth:1,//线条宽度,默认1
- strokeStyle:'red',//画笔颜色,默认红色
- fillStyle:'red',//填充色
- lineJoin:"round",//线条交角样式,默认圆角
- lineCap:"round",//线条结束样式,默认圆角
- };
- //重新载入绘制样式
- var resetStyle=function(){
- cxt.strokeStyle=paintConfig.strokeStyle;
- cxt.lineWidth=paintConfig.lineWidth;
- cxt.lineJoin=paintConfig.lineJoin;
- cxt.lineCap=paintConfig.lineCap;
- cxt.fillStyle=paintConfig.fillStyle;
- }
- //鼠标图形
- var cursors=['crosshair','pointer'];
- /** 切换鼠标样式*/
- var switchCorser=function(b){
- cbtCanvas.style.cursor=((isNull(b)?isDrawing():b)?cursors[0]:cursors[1]);
- }
- //操作控制变量组
- var ctrlConfig={
- kind:0,//当前绘画分类
- isPainting:false,//是否开始绘制
- startPoint:null,//起始点
- cuGraph:null,//当前绘制的图像
- cuPoint:null,//当前临时坐标点,确定一个坐标点后重新构建
- cuAngle:null,//当前箭头角度
- vertex:[],//坐标点
- }
- /**获取当前坐标点*/
- var getCuPoint=function(i){
- return ctrlConfig.cuPoint[i];
- }
- /**设置当前坐标点*/
- var setCuPoint=function(p,i){
- return ctrlConfig.cuPoint[i]=p;
- }
- /**设置当前临时坐标点值*/
- var setCuPointXY=function(x,y,i){
- if(isNull(ctrlConfig.cuPoint)){
- var arr=new Array();
- arr[i]=new Point(x,y);
- ctrlConfig.cuPoint=arr;
- }else if(isNull(ctrlConfig.cuPoint[i])){
- setCuPoint(new Point(x,y),i);
- }else{
- ctrlConfig.cuPoint[i].setXY(x,y);
- }
- return getCuPoint(i);
- }
- /**是否正在绘制*/
- var isDrawing=function (){
- return ctrlConfig.isPainting;
- }
- /**开始绘制状态*/
- var beginDrawing=function(){
- ctrlConfig.isPainting=true;
- }
- /**结束绘制状态*/
- var stopDrawing=function(){
- ctrlConfig.isPainting=false;
- }
- /**是否有开始坐标点*/
- var hasStartPoint=function(){
- return !isNull(ctrlConfig.startPoint);
- }
- /**设置当前绘制的图形*/
- var setCuGraph=function(g){
- ctrlConfig.cuGraph=g;
- }
- /**获取当前绘制的图形*/
- var getCuGraph=function(){
- return ctrlConfig.cuGraph;
- }
- /**设置开始坐标点(线条的起始点,三角形的顶点,圆形的圆心,四边形的左上角或右下角,多边形的起始点)*/
- var setStartPoint=function(p){
- ctrlConfig.startPoint=p;
- }
- /**获取开始坐标点*/
- var getStartPoint=function(){
- return ctrlConfig.startPoint;
- }
- /**清空全部*/
- var clearAll=function(){
- cxt.clearRect(0,0,cbtCanvas.width,cbtCanvas.height);
- }
- /**重绘*/
- var repaint=function(){
- clearAll();
- /*
- if(bgPictureConfig.repaint){
- loadPicture(bgPictureConfig.pic);
- }*/
- }
- /**点(坐标,绘图的基本要素,包含x,y坐标)*/
- var Point=(function(x1,y1){
- var x=x1,y=y1;
- return{
- set:function(p){
- x=p.x,y=p.y;
- },
- setXY:function(x2,y2){
- x=x2;y=y2;
- },
- setX:function(x3){
- x=x3;
- },
- setY:function(y3){
- y=y3;
- },
- getX:function(){
- return x;
- },
- getY:function(){
- return y;
- }
- }
- });
- /**多角形(三角形、矩形、多边形),由多个点组成*/
- var Poly=(function(ps1){
- var ps=isNull(ps1)?new Array():ps1;
- var size=ps.length;
- return{
- set:function(ps2){
- ps=ps2;
- },
- getSize:function(){
- return size;
- },
- setPoint:function(p,i){
- if(isNull(p)&&isNaN(i)){
- return;
- }
- ps[i]=p;
- },
- setStart:function(p1){
- if(isNull(ps)){
- ps=new Array();
- return ps.push(p1);
- }else{
- ps[0]=p1;
- }
- },
- add:function(p){
- if(isNull(ps)){
- ps=new Array();
- }
- return ps.push(p);
- },
- pop:function(){
- if(isNull(ps)){
- return;
- }
- return ps.pop();
- },
- shift:function(){
- if(isNull(ps)){
- return;
- }
- return ps.shift;
- },
- get:function(){
- if(isNull(ps)){
- return null;
- }
- return ps;
- },
- draw:function(){
- cxt.beginPath();
- for(i in ps){
- if(i==0){
- cxt.moveTo(ps[i].getX(),ps[i].getY());
- }else{
- cxt.lineTo(ps[i].getX(),ps[i].getY());
- }
- }
- cxt.closePath();
- cxt.stroke();
- }
- }
- });
- /*线条(由两个点组成,包含方向)*/
- var Line=(function(p1,p2,al){
- var start=p1,end=p2,angle=al;
- var drawLine=function(){
- cxt.beginPath();
- cxt.moveTo(p1.getX(),p1.getY());
- cxt.lineTo(p2.getX(),p2.getY());
- cxt.stroke();
- }
- //画箭头
- var drawArrow=function() {
- var vertex =ctrlConfig.vertex;
- var x1=p1.getX(),y1=p1.getY(),x2=p2.getX(),y2=p2.getY();
- var el=50,al=15;
- //计算箭头底边两个点(开始点,结束点,两边角度,箭头角度)
- vertex[0] = x1,vertex[1] = y1, vertex[6] = x2,vertex[7] = y2;
- //计算起点坐标与X轴之间的夹角角度值
- var angle = Math.atan2(y2 - y1, x2 - x1) / Math.PI * 180;
- var x = x2 - x1,y = y2 - y1,length = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
- if (length < 250) {
- el/=2,al/2;
- }else if(length<500){
- el*=length/500,al*=length/500;
- }
- vertex[8] = x2 - el * Math.cos(Math.PI / 180 * (angle + al));
- vertex[9] = y2- el * Math.sin(Math.PI / 180 * (angle + al));
- vertex[4] = x2- el* Math.cos(Math.PI / 180 * (angle - al));
- vertex[5] = y2 - el * Math.sin(Math.PI / 180 * (angle - al));
- //获取另外两个顶点坐标
- x=(vertex[4]+vertex[8])/2,y=(vertex[5]+vertex[9])/2;
- vertex[2] = (vertex[4] + x) / 2;
- vertex[3] = (vertex[5] + y) / 2;
- vertex[10] = (vertex[8] +x) / 2;
- vertex[11] = (vertex[9] +y) / 2;
- //计算完成,开始绘制
- cxt.beginPath();
- cxt.moveTo(vertex[0], vertex[1]);
- cxt.lineTo(vertex[2], vertex[3]);
- cxt.lineTo(vertex[4], vertex[5]);
- cxt.lineTo(vertex[6], vertex[7]);
- cxt.lineTo(vertex[8], vertex[9]);
- cxt.lineTo(vertex[10], vertex[11]);
- cxt.closePath();
- cxt.fill();
- cxt.stroke();
- }
- return{
- setStart:function(s){
- start=s;
- },
- setEnd:function(e){
- end=e;
- },
- getStart:function(){
- return start;
- },
- getEnd:function(){
- return end;
- },
- draw:function(){
- if(angle){
- drawArrow();
- }else{
- drawLine();
- }
- }
- }
- });
- /**圆形(包含圆心点和半径)*/
- var Circle=(function(arr){
- //包含起始点(圆心)和结束点,以及圆半径
- var startPoint=arr.start,endPoint=arr.end,radius=arr.radius;
- /*绘制圆*/
- var drawCircle=function(){
- cxt.beginPath();
- var x=startPoint.getX();
- var y=startPoint.getY();
- if(isNull(radius)){
- radius=calculateRadius(startPoint,endPoint);
- }
- //x,y,半径,开始点,结束点,顺时针/逆时针
- cxt.arc(x,y,radius,0,Math.PI*2,false); // 绘制圆
- cxt.stroke();
- }
- //计算圆半径
- var calculateRadius=function(p1,p2){
- var width=p2.getX()-p1.getX();
- var height=p2.getY()-p1.getY();
- //如果是负数
- if(width<0||height<0){
- width=Math.abs(width);
- }
- //计算两点距离=平方根(width^2+height^2)
- c=Math.sqrt(Math.pow(width,2)+Math.pow(height,2));
- return c;
- }
- return{
- set:function(params){
- startPoint=params.start;
- endPoint=params.end;
- radius=params.radius;
- },
- setPoint:function(p1){
- p=p1;
- },
- getPoint:function(){
- return p;
- },
- setRadius:function(r1){
- radius=r1;
- },
- getRadius:function(){
- return radius;
- },
- calcRadius:calculateRadius,
- //绘制
- draw:drawCircle,
- }
- });
- /**绘制线条工具方法*/
- var drawLine=function(p){
- cxt.beginPath();
- cxt.moveTo(startPosition.getX(),startPosition.getY());
- cxt.lineTo(p.getX(),p.getY());
- cxt.stroke();
- }
- /**绘制三角形工具方法*/
- var drawTrian=function(ps){
- cxt.beginPath();
- var a=ps.get();
- cxt.moveTo(a[0].getX(),a[0].getY());
- cxt.lineTo(a[1].getX(),a[1].getY());
- cxt.lineTo(a[2].getX(),a[2].getY());
- cxt.closePath();
- cxt.stroke();
- }
- /**绘制矩形工具方法*/
- var drawRect=function(p2){
- var p=getStartPoint();
- var width=p.getX()-p2.getX();
- var height=p.getY()-p2.getY();
- cxt.beginPath();
- cxt.strokeRect(x,y,width,height);//绘制矩形
- }
- /*绘制多边形工具方法*/
- var drawpolygon=function(ps){
- if(ps.length>1){//保证只有两个坐标点才是矩形
- cxt.beginPath();
- var p=ctrlConfig.startPoint;
- var x=p.getX();
- var y=p.getY();
- cxt.moveTo(x,y);
- for(p1 in ps){
- cxt.lineTo(p1.getX(),p1.getY());
- }
- cxt.stroke();
- }
- }
- /*绘制圆角矩形工具方法*/
- var drawRoundedRect=function(x,y,width,height,radius){
- cxt.beginPath();
- cxt.moveTo(x,y+radius);
- cxt.lineTo(x,y+height-radius);
- cxt.quadraticCurveTo(x,y+height,x+radius,y+height);
- cxt.lineTo(x+width-radius,y+height);
- cxt.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);
- cxt.lineTo(x+width,y+radius);
- cxt.quadraticCurveTo(x+width,y,x+width-radius,y);
- cxt.lineTo(x+radius,y);
- cxt.quadraticCurveTo(x,y,x,y+radius);
- cxt.stroke();
- }
- /*绘制圆工具方法*/
- var drawCircle=function(c){
- var p=c.getPoint();//坐标点
- var x=p.getX();
- var y=p.getY();
- var r=c.getRadius();
- cxt.beginPath();
- //x,y,半径,开始点,结束点,顺时针/逆时针
- cxt.arc(x,y,r,0,Math.PI*2,false); // 绘制圆
- cxt.stroke();
- }
- //计算圆半径工具方法
- var calculateRadius=function(p1,p2){
- var width=p2.getX()-p1.getX();
- var height=p2.getY()-p1.getY();
- //如果是负数
- if(width<0||height<0){
- width=Math.abs(width);
- }
- //计算两点距离=平方根(width^2+height^2)
- c=Math.sqrt(Math.pow(width,2)+Math.pow(height,2));
- return c;
- }
- //鼠标按键点击(首次点击确定开始坐标点,拖动鼠标不断进行图形重绘)
- var mouseDown = function(e){
- var btnNum = e.button;
- if(btnNum==0){
- console.log("选择:"+ctrlConfig.kind);
- //设置起始点
- switch(ctrlConfig.kind){
- case graphkind.pen://画笔(不松开鼠标按键一直画)
- beginDrawing();//开始绘制
- cxt.beginPath();
- cxt.moveTo(e.offsetX,e.offsetY);
- break;
- case graphkind.poly://多边形
- var p=new Point(e.offsetX,e.offsetY);
- if(isDrawing()){
- getCuGraph().add(p);//添加到
- }else{//第一次确定开始坐标
- beginDrawing();//开始绘制
- setStartPoint(p);
- var poly=new Poly();
- poly.add(p);
- setCuGraph(poly);//设置当前绘制图形
- }
- break;
- case graphkind.line://线条
- case graphkind.arrow://方向
- case graphkind.trian://三角形
- case graphkind.rect://矩形
- case graphkind.parallel://平行四边形
- case graphkind.trapezoid://梯形
- beginDrawing();//开始绘制
- var p=new Point(e.offsetX,e.offsetY);
- setStartPoint(p);
- var poly=new Poly();
- poly.add(p);
- setCuGraph(poly);//设置当前绘制图形
- break;
- case graphkind.circle://圆
- console.log("确定图形绘制开始坐标点:"+e.offsetX+","+e.offsetY);//点击确定图形的开始坐标点
- beginDrawing();//开始绘制
- var p=new Point(e.offsetX,e.offsetY);
- setStartPoint(p);
- var circle= new Circle({'start':p});
- setCuGraph(circle);
- break;
- case ctrlConfig.cursor: //手型鼠标
- default://默认是手型鼠标,不允许绘制
- }
- }else if(btnNum==2){
- console.log("右键由于结束多边形绘制");
- if(isDrawing()){
- if(ctrlConfig.kind==graphkind.poly){
- repaint();
- getCuGraph().draw();
- stopDrawing();//结束绘制
- }
- }
- }
- hideDefRM();//屏蔽浏览器默认事件
- }
- //鼠标移动(拖动,根据鼠标移动的位置不断重绘图形)
- var mouseMove = function(e){
- if(isDrawing()&&hasStartPoint()){//检查是否开始绘制,检查是否有开始坐标点
- //画笔不需要重绘
- if(ctrlConfig.kind>1){
- repaint();//重绘
- }
- var p=setCuPointXY(e.offsetX,e.offsetY,0);//设置共享的临时坐标点,用于防止重复创建对象
- switch(ctrlConfig.kind){
- case graphkind.pen://画笔(一直画)
- cxt.lineTo(e.offsetX,e.offsetY);
- cxt.stroke();
- break;
- case graphkind.poly://多边形
- var poly=getCuGraph(poly);
- var size=poly.getSize();
- poly.setPoint(p,(size-1));
- poly.draw();
- break;
- case graphkind.line://线条
- var line=new Line(getStartPoint(),p,false);
- ctrlConfig.cuGraph=line;
- line.draw();
- break;
- case graphkind.arrow://方向
- var line=new Line(getStartPoint(),p,true);
- ctrlConfig.cuGraph=line;
- line.draw();
- break;
- case graphkind.trian://三角形
- var lu=getStartPoint();
- var x2=p.getX();
- var x1=lu.getX();
- //三角形左边的点坐标计算方法:(x1-(x2-x1),y2)
- var x3=x1-(x2-x1);
- var l=setCuPointXY(x3,p.getY(),1);//设置共享的临时坐标点,用于防止重复创建对象
- var poly=getCuGraph();//获取当前图形
- poly.set([lu,p,l]);
- poly.draw();//即时绘制
- break;
- case graphkind.parallel://平行四边形
- var lu=getStartPoint();
- var x3=p.getX();
- var x1=lu.getX();
- //平行四边形两个未知坐标点计算方法:(x1-(x3-x1),y3),(x1+(x3-x1),y1)
- var x2=x3+(x3-x1);
- var x4=x1-(x3-x1);
- var ld=setCuPointXY(x2,lu.getY(),1);//设置共享的临时坐标点,用于防止重复创建对象
- var ru=setCuPointXY(x4,p.getY(),2);//设置共享的临时坐标点,用于防止重复创建对象
- var poly=getCuGraph();//获取当前图形
- poly.set([lu,ru,p,ld]);
- poly.draw();//即时绘制
- break;
- case graphkind.trapezoid://梯形
- var lu=getStartPoint();
- var x3=p.getX();
- var x1=lu.getX();
- //梯形两个未知坐标点计算方法:(x3-(x3-x1)/2,y1),(x1-(x3-x1)/2,y3)
- var x2=x3-(x3-x1)/2;
- var x4=x1-(x3-x1)/2;
- var ld=setCuPointXY(x2,lu.getY(),1);
- var ru=setCuPointXY(x4,p.getY(),2);
- var poly=getCuGraph();
- poly.set([lu,ru,p,ld]);
- poly.draw();
- break;
- case graphkind.rect://矩形
- var lu=getStartPoint();
- //矩形右上角和左上角坐标计算方法
- var ld=setCuPointXY(lu.getX(),p.getY(),1);
- var ru=setCuPointXY(p.getX(),lu.getY(),2);
- var poly=getCuGraph();
- poly.set([lu,ru,p,ld]);
- poly.draw();
- break;
- case graphkind.circle://圆
- var circle=getCuGraph();//获取当前图形
- circle.set({'start':getStartPoint(),'end':p});
- circle.draw();//即时绘制
- break;
- }
- }
- }
- //鼠标按键松开
- var mouseUp = function(e){
- if(isDrawing()){
- //console.log("松开鼠标按键:"+e.offsetX+","+e.offsetY);
- //画笔不需要重绘
- if(ctrlConfig.kind>1){
- repaint();
- getCuGraph().draw();
- }
- if(ctrlConfig.kind!=graphkind.poly){//多边形绘制鼠标按键松开不结束绘制,多边形只有右键点击才能结束绘制
- stopDrawing();//结束绘制
- }
- }
- }
- //鼠标移出
- var mouseOut = function(e){
- console.log("鼠标移出绘制区域"+e.offsetX+","+e.offsetY);
- if(isDrawing()){
- console.log("停止绘制");
- if(ctrlConfig.kind>1){
- repaint();
- getCuGraph().draw();
- }
- stopDrawing();//停止绘制
- }
- }
- return{
- isNull:isNull,
- getDom:getDom,
- clear:function(){
- stopDrawing();//停止绘制
- repaint();
- },
- /**初始化*/
- init:function(params){
- cbtCanvas=getDom(params.id);
- //浏览器是否支持Canvas
- if (cbtCanvas.getContext){
- /**绘图对象*/
- cxt=cbtCanvas.getContext("2d");
- cbtCanvas.onmousedown = mouseDown;
- cbtCanvas.onmouseup = mouseUp;
- cbtCanvas.onmousemove = mouseMove;
- cbtCanvas.onmouseout = mouseOut;
- resetStyle();//载入样式
- return true;
- }else{
- return false;
- }
- },
- /**设置背景图片*/
- setBgPic:loadPicture,
- /**选择图形类型*/
- begin:function(k){
- console.log("选择绘制图形:"+k);
- if(isNaN(k)){//如果不是数字,先转换为对应字符
- ctrlConfig.kind=kind[k];
- }else{
- ctrlConfig.kind=k;
- }
- switchCorser(true);//切换鼠标样式
- },
- /*手型,并停止绘图*/
- hand:function(){
- ctrlConfig.kind=0;
- stopDrawing();//停止绘制
- switchCorser(false);//切换鼠标样式
- }
- }
- })
三、使用方式
1、图形类型
0:鼠标,1:画笔,2:线条,3:三角形,4:矩形,5:多边形,6:圆形,21:箭头,41:平行四边形,42:梯形
var graphkind={'cursor':0,'pen':1,'line':2,'trian':3,'rect':4,'poly':5,'circle':6,'arrow':21,'parallel':41,'trapezoid':42};
2、初始化以及使用背景图片和画笔选择
- var drawUtil=new DrawingTools();
- //初始化,(如果浏览器不支持H5,会初始化失败,返回false)
- if(drawUtil.init({'id':'calibrationCanvas'})){
- //加载图片
- var imgsrc='图片地址';
- if(!drawUtil.isNull(imgsrc)){
- drawUtil.setBgPic(imgsrc,true);//设置背景图片(异步加载图片)
- }
- }
- drawUtil.begin(1);//选择画笔
2、绘制箭头
- drawUtil.begin(21);
四、演示demo
使用原生JavaScript的Canvas实现拖拽式图形绘制,支持画笔、线条、箭头、三角形、矩形、平行四边形、梯形以及多边形和圆形,不依赖任何库和插件,有演示demo的更多相关文章
- 原生js实现Canvas实现拖拽式绘图,支持画笔、线条、箭头、三角形和圆形等等图形绘制功能,有实例Demo
前言 需要用到图形绘制,没有找到完整的图形绘制实现,所以自己实现了一个 - - 演示地址:查看演示DEMO 新版本支持IE5+(你没看错,就是某软的IE浏览器)以上任意浏览器的Canvas绘图:htt ...
- 基于JS的WEB会议室预订拖拽式图形界面的实现
06年的一篇blog,转到这个博客上: 很早之前写的,后来由于这个功能模块取消,最终没有上线,所以与Server交互的那部分还没有写,不过那部分方案我也已经出来了,而且现在客户端这一部分已经通过了比较 ...
- canvas 图片拖拽旋转之二——canvas状态保存(save和restore)
引言 在上一篇日志“canvas 图片拖拽旋转之一”中,对坐标转换有了比较深入的了解,但是仅仅利用坐标转换实现的拖拽旋转,会改变canvas坐标系的状态,从而影响画布上其他元素的绘制.因此,这个时候需 ...
- 拖拽系列一、JavaScript实现简单的拖拽效果
前端拖拽相关应用汇总 在现实生活中就像男孩子牵着(拖着)女朋友的手穿过马路:从马路的一端走到另一端这种场景很常见: 而在前端开发中拖拽效果也算是前端开发中应用最常见.最普遍的特效:其拖拽涉及知 ...
- EgLine V0.3—LVGL官方拖拽式UI编辑工具(可导出代码)
** EdgeLine ** 是LVGL官方团队退出的一款拖拽式UI编辑工具,现在还处于测试间断,目前最新版本为v0.3,已经可导出代码. 注意: 使用该软件需要注册lvgl账号,这一步可能需要代理 ...
- day23—JavaScript实现DIV盒子拖拽(原生方式)
转行学开发,代码100天——2018-04-08 <!doctype html> <html> <head> <meta charset="utf- ...
- HTML5新特性之Canvas+drag(拖拽图像实现图像反转)
1.什么是canvas 在网页上使用canvas元素时,会创建一块矩形区域,默认矩形区域宽度300px,高度150px.. 页面中加入canvas元素后,可以通过javascript自由控制.可以在其 ...
- HTML5 -canvas拖拽、移动 绘制图片可操作移动,拖动
关于canvas 的基础知识就不多说了,可以进这个网址学习 http://www.w3school.com.cn/html5/html_5_canvas.asp 对于canvas 和 SVG 其实一开 ...
- canvas 图片拖拽旋转之一——坐标转换translate
引言 对canvas中绘制的图片进行旋转操作,需要使用ctx.translate变换坐标系,将图片旋转的基点设为坐标系的原点,然后ctx.rotate旋转. 这个时候,因为canvas坐标系发生了旋转 ...
随机推荐
- 不可不知的socket和TCP连接过程
html { font-family: sans-serif } body { margin: 0 } article,aside,details,figcaption,figure,footer,h ...
- Redis缓存项目应用架构设计一
一些项目整理出的项目中引入缓存的架构设计方案,希望能帮助你更好地管理项目缓存,作者水平有限,如有不足还望指点. 一.基础结构介绍 项目中对外提供方法的是CacheProvider和MQProvider ...
- Java面向对象 正则表达式
Java面向对象 正则表达式 知识概要: (1)正则表达式的特点 (2)正则表达的匹配 (3)正则表达式的切割,替换,获取 (4)正则表达式的练习 正则表达式:符合 ...
- 阿里云AliYun表格存储(Table Store)相关案例
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- redis的发布订阅模式pubsub
前言 redis支持发布订阅模式,在这个实现中,发送者(发送信息的客户端)不是将信息直接发送给特定的接收者(接收信息的客户端),而是将信息发送给频道(channel),然后由频道将信息转发给所有对这个 ...
- CSS滤镜效果
使用 filter: blur() 生成毛玻璃效果 使用 filter: drop-shadow() 生成整体阴影效果 使用 filter: opacity() 生成透明度 blur生成阴影 通常我们 ...
- Django REST FrameWork中文教程2:请求和响应
从这一点开始,我们将真正开始覆盖REST框架的核心.我们来介绍几个基本的构建块. 请求对象REST框架引入了Request扩展常规的对象HttpRequest,并提供更灵活的请求解析.Request对 ...
- JavaWeb之Maven配置
Maven和C#的nuget类似,可以通过设置就能引入框架等第三方,方便又省事.Java中使用Maven来管理第三方.今天尝试着配置了一下. 一.JDK的安装 关于JDK的安装可以查看百度经验,设置P ...
- Android基础知识笔记01—框架结构与四大组件
-----------Andriod 01--------------->>> Andriod系统架构 linux内核与驱动层. 系统运行库层. 应用框架层. 应用层 内核驱动 ...
- Locust性能测试框架,从入门到精通
1. Locust简介 Locust是使用Python语言编写实现的开源性能测试工具,简洁.轻量.高效,并发机制基于gevent协程,可以实现单机模拟生成较高的并发压力. 主要特点如下: 使用普通的P ...