实例介绍
【实例简介】
Canvas绘图工具,使用Javascript编写
实现了基本的绘图功能
【实例截图】
【核心代码】
//用于实现Javascript的继承机制
(function () {
var initializing = false, fnTest = /xyz/.test(function () {
xyz;
}) ? /\b_super\b/ : /.*/;
//基函数Class,什么也不干
this.Class = function () {
};
// 创建一个新函数,继承自该函数
Class.extend = function (prop) {
var _super = this.prototype;
// 实例化一个基函数,但是只建立实例,不调用构造函数
initializing = true;
var prototype = new this();
initializing = false;
// 将属性赋值到新prototype中
for (var name in prop) {
// 检查是否在重写已经存在的函数
prototype[name] = typeof prop[name] == "function" &&
typeof _super[name] == "function" && fnTest.test(prop[name]) ?
(function (name, fn) {
return function () {
var tmp = this._super;
//添加一个新的._super()方法,但是该方法是super-class中的
this._super = _super[name];
//该方法只需要被暂时绑定,所以完成之后移除它
var ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
};
})(name, prop[name]) :
prop[name];
}
// 利用init函数来虚拟类的构造器
function Class() {
// 所有的构建动作其实都是在init方法中完成
if (!initializing && this.init)
this.init.apply(this, arguments);
}
// 填充构建的 prototype 对象
Class.prototype = prototype;
// 强行使构造器指向函数本身而不是父函数
Class.prototype.constructor = Class;
// 使该函数为可扩展的
Class.extend = arguments.callee;
return Class;
};
})();
//实现类继承基制的代码到此结束
//Point类
var Point = Class.extend({
init: function (x, y) {//构造函数
this.x = x;
this.y = y;
}
});
//Vector 向量类
var Vector = Class.extend({
init: function (x, y) {//构造函数
this.x = x;
this.y = y;
}
});
//图幅尺寸大小类
var Size = Class.extend({
init: function (w, h) {//构造函数
this.w = w;
this.h = h;
}
});
//图幅尺寸大小类
var CanvasStyle = Class.extend({
init: function () {//构造函数
this.strokeStyle = null;
this.lineWidth = null;
}
});
//图形边界类
var Bounds = Class.extend({
init: function (x1, y1, x2, y2) {//构造函数
this.left = x1;
this.right = x2;
this.bottom = y1;
this.top = y2;
},
getCenter: function () {//获取边界中心点
var w = this.right - this.left;
var h = this.top - this.bottom;
return new Point(this.left w / 2, this.bottom h / 2);
},
intersect: function (bounds) {//边界与边界是否相交
var inBottom = (
((bounds.bottom >= this.bottom) && (bounds.bottom <= this.top)) ||
((this.bottom >= bounds.bottom) && (this.bottom <= bounds.top))
);
var inTop = (
((bounds.top >= this.bottom) && (bounds.top <= this.top)) ||
((this.top > bounds.bottom) && (this.top < bounds.top))
);
var inLeft = (
((bounds.left >= this.left) && (bounds.left <= this.right)) ||
((this.left >= bounds.left) && (this.left <= bounds.right))
);
var inRight = (
((bounds.right >= this.left) && (bounds.right <= this.right)) ||
((this.right >= bounds.left) && (this.right <= bounds.right))
);
intersects = ((inBottom || inTop) && (inLeft || inRight));
return intersects;
},
extend: function (bounds) {//扩展边界
if (this.left > bounds.left) {
this.left = bounds.left;
}
if (this.bottom > bounds.bottom) {
this.bottom = bounds.bottom;
}
if (this.right < bounds.right) {
this.right = bounds.right;
}
if (this.top < bounds.top) {
this.top = bounds.top;
}
}
});
//图层类定义DrawArea
var DrawArea = Class.extend({
init: function (div) {//构造函数
var size = new Size(parseInt(div.style.width), parseInt(div.style.height));
this.size = size;
this.div = div;
this.style = null;
this.graphic = null;
this.tool = "Line";
this.scale = new Scale(this);
this.pan = new Pan(this);
this.maxBounds = new Bounds(-size.w / 2, -size.h / 2, size.w / 2, size.h / 2);
this.bounds = new Bounds(-size.w / 2, -size.h / 2, size.w / 2, size.h / 2);
this.center = this.bounds.getCenter();
this.zoom = 100;
this.getRes();
this.graphicList = [];
//加入矢量图形的总个数。
this.graphickListCount = 0;
this.selectedGraphicList = [];
this.pointList = [];//交点集合
this.intersectionPoint = null;
//创建一个渲染器。
this._canvas = document.getElementById('canvas2');
this._context = this._canvas.getContext("2d");
this.canvas = document.getElementById('canvas1');
this.context = this.canvas.getContext("2d");
},
getRes: function () {
this.res = 1 / (this.zoom / 100);
return this.res;
},
getResFromZoom: function (zoom) {
return res = 1 / (zoom / 100);
},
addGraphic: function (graphic) {
this.graphicList.push(graphic);
this.graphickListCount = 1;
},
refresh: function () {
this.context.clearRect(0, 0, this.size.w, this.size.h);
if (this.graphicList.length >= 1) {
for (var i = 0; i < this.graphicList.length; i ) {
var x = this.graphicList[i];
x.draw();
}
}
},
moveTo: function (zoom, center) {
if (zoom <= 0) {
return;
}
this.zoom = zoom;
this.center = center;
var res = this.getRes();
var width = this.size.w * res;
var height = this.size.h * res;
//获取新的视图范围。
var bounds = new Bounds(center.x - width / 2, center.y - height / 2, center.x width / 2, center.y height / 2);
this.bounds = bounds;
//记录已经绘制vector的个数
this.refresh();
},
//通过屏幕坐标获取绝对坐标。
getPositionFromPx: function (px) {
return new Point((px.x this.bounds.left / this.res) * this.res,
(this.bounds.top / this.res - px.y) * this.res);
},
//获得一个点的屏幕显示位置。与上一个函数功能相反
getLocalXY: function (point) {
var resolution = this.getRes();
var extent = this.bounds;
var x = (point.x / resolution (-extent.left / resolution));
var y = ((extent.top / resolution) - point.y / resolution);
return {x: x, y: y};
}
});
//Graphic类 图元基类
var Graphic = Class.extend({
init: function (startPoint, endPoint, drawArea) {
this.startPoint = startPoint;
this.endPoint = endPoint;
this.bounds = null;
this.selected = false;
this.hidden = false;
this.drawArea = drawArea;
//this.style=this.drawArea.style;
this.graphicType = null;
},
//获取图元边界
getBounds: function () {
//
},
//为选中的对象绘制控制点
drawTracker: function () {
//虚函数,什么也不做,下同
},
//碰撞检测
hitTest: function (pt) {
return false;
},
//根据光标位置获取控制点
getHandler: function (pt) {
},
//鼠标绘图动作,前画布绘制然后更新到后画布
drawing: function () {
},
//根据对象参数直接在后画布绘图
draw: function () {
},
//将对象转化为Jason
toJSON: function () {
//do something
},
//绘制尺寸
drawRuler: function () {
},
//移动对象
moveTO: function () {
},
//移动控制点
moveHandler: function () {
},
//转变内部点
switchPoints: function () {
}
});
//Line类的定义
var Line = Graphic.extend({
init: function (startPoint, endPoint, drawArea) {
this._super(startPoint, endPoint, drawArea);//调用父类的构造函数
this.lineLength = DistanceOfTwoPoint(startPoint, endPoint);
this.graphicType = "Line"
},
//获取图元边界
getBounds: function () {
this.bounds = new Bounds(startPoint.x, startPoint.y, startPoint.x, startPoint.y);
var bounds = new Bounds(endPoint.x, endPoint.y, endPoint.x, endPoint.y);
this.bounds.extend(bounds);
return this.bounds;
},
drawTracker: function () {
var context = this.drawArea.context;
var sp = this.drawArea.getLocalXY(this.startPoint);
var ep = this.drawArea.getLocalXY(this.endPoint);
context.fillStyle = 'rgb(0,0,0)';
context.fillRect(sp.x - 5, sp.y - 5, 10, 10);
context.fillRect(ep.x - 5, ep.y - 5, 10, 10);
},
hitTest: function (pt) {
var line = new Line(this.startPoint, this.endPoint);
if (DistanceToLine(pt, line) <= 5) {
return true;
}
return false;
},
getHandler: function (pt) {
if (DistanceOfTwoPoint(pt, this.startPoint) <= 5) {
return 1
}
if (DistanceOfTwoPoint(pt, this.endPoint) <= 5) {
return 2
}
return 0;
},
drawing: function () {
var drawArea = this.drawArea;
var _context = this.drawArea._context;
var sp = this.drawArea.getLocalXY(this.startPoint);
var ep = this.drawArea.getLocalXY(this.endPoint);
_context.setLineDash([5, 10]);
_context.lineWidth = 15;
_context.clearRect(0, 0, 10000, 10000);
_context.beginPath();
_context.moveTo(sp.x, sp.y);
_context.lineTo(ep.x, ep.y);
_context.stroke();
_context.closePath();
},
draw: function () {
if (!this.hidden) {
var context = this.drawArea.context;
context.setLineDash([5]);
context.beginPath();
var sp = this.drawArea.getLocalXY(this.startPoint);
var ep = this.drawArea.getLocalXY(this.endPoint);
context.moveTo(sp.x, sp.y);
context.lineTo(ep.x, ep.y);
context.stroke();
context.closePath();
if (this.selected) {
this.drawTracker();//如果选中的话 绘制控制点
}
}
},
//存为JSON对象
toJSON: function () {
//do something
},
//绘制尺寸
drawRuler: function () {
},
//移动对象
moveTO: function (pt) {
this.startPoint.x = this.startPoint.x pt.x;
this.startPoint.y = this.startPoint.y pt.y;
this.endPoint.x = this.endPoint.x pt.x;
this.endPoint.y = this.endPoint.y pt.y;
},
moveHandler: function (handlerNumber, pt) {
if (handlerNumber == 1) {
this.startPoint.x = this.startPoint.x pt.x;
this.startPoint.y = this.startPoint.y pt.y;
}
if (handlerNumber == 2) {
this.endPoint.x = this.endPoint.x pt.x;
this.endPoint.y = this.endPoint.y pt.y;
}
},
switchPoints: function () {
//虽然直线不需要转换点,但是必须有该函数
}
});
//Arc类的定义
var Arc = Graphic.extend({
init: function (origin, startPoint, endPoint, drawArea) {
this.origin = origin;
this.startPoint = startPoint;
this.endPoint = endPoint;
this.drawArea = drawArea;
this.bounds = null;
this.selected = false;
this.hidden = false;
this.style = drawArea.style;
this.r = DistanceOfTwoPoint(origin, startPoint);
this.startRad = GetRad(origin, startPoint);
this.endRad = GetRad(origin, endPoint);
this.relocateEndPoint();
this.liehu = this.liehu();
this.graphicType = "Arc";
},
//获取图元边界
getBounds: function () {
this.bounds = new Bounds(startPoint.x, startPoint.y, startPoint.x, startPoint.y);
var bounds = new Bounds(endPoint.x, endPoint.y, endPoint.x, endPoint.y);
this.bounds.extend(bounds);
return this.bounds;
},
drawTracker: function () {
var context = this.drawArea.context;
var og = this.drawArea.getLocalXY(this.origin);
var sp = this.drawArea.getLocalXY(this.startPoint);
var ep = this.drawArea.getLocalXY(this.endPoint);
context.fillStyle = 'rgb(0,0,0)';
context.fillRect(og.x - 5, og.y - 5, 10, 10);
context.fillRect(sp.x - 5, sp.y - 5, 10, 10);
context.fillRect(ep.x - 5, ep.y - 5, 10, 10);
},
hitTest: function (pt) {
if (DistanceOfTwoPoint(pt, this.origin) - this.r <= 5 && DistanceOfTwoPoint(pt, this.origin) - this.r >= -5) {
return true;
}
return false;
},
getHandler: function (pt) {
if (DistanceOfTwoPoint(pt, this.origin) <= 5) {
return 1
}
if (DistanceOfTwoPoint(pt, this.startPoint) <= 5) {
return 2
}
if (DistanceOfTwoPoint(pt, this.endPoint) <= 5) {
return 3
}
return 0;
},
drawing: function () {
var drawArea = this.drawArea;
var _context = this.drawArea._context;
var pt = this.drawArea.getLocalXY(this.origin);
_context.setLineDash([5]);
_context.clearRect(0, 0, 10000, 10000);
_context.beginPath();
_context.arc(pt.x, pt.y, this.r / this.drawArea.res, this.startRad, this.endRad, false);
_context.stroke();
_context.closePath();
},
draw: function () {
if (!this.hidden) {
var context = this.drawArea.context;
context.setLineDash([5]);
context.beginPath();
pt = this.drawArea.getLocalXY(this.origin);
context.arc(pt.x, pt.y, this.r / this.drawArea.res, this.startRad, this.endRad, false);
context.stroke();
context.closePath();
if (this.selected) {
this.drawTracker();//如果选中的话 绘制控制点
}
}
},
//存为JSON对象
toJSON: function () {
//do something
},
//绘制尺寸
drawRuler: function () {
},
//移动对象
moveTO: function (pt) {
this.startPoint.x = this.startPoint.x pt.x;
this.startPoint.y = this.startPoint.y pt.y;
this.endPoint.x = this.endPoint.x pt.x;
this.endPoint.y = this.endPoint.y pt.y;
},
moveHandler: function (handlerNumber, pt) {
if (handlerNumber == 1) {
this.startPoint.x = this.startPoint.x pt.x;
this.startPoint.y = this.startPoint.y pt.y;
}
if (handlerNumber == 2) {
this.endPoint.x = this.endPoint.x pt.x;
this.endPoint.y = this.endPoint.y pt.y;
}
},
switchPoints: function () {
//虽然直线不需要转换点,但是必须有该函数
},
relocateEndPoint: function () {
var k = this.r / DistanceOfTwoPoint(this.endPoint, this.origin);
this.endPoint.x = k * (this.endPoint.x - this.origin.x) this.origin.x;
this.endPoint.y = k * (this.endPoint.y - this.origin.y) this.origin.y;
},
liehu: function () {
var v1 = new Vector(this.startPoint.x - this.origin.x, this.startPoint.y - this.origin.y);
var v2 = new Vector(this.endPoint.x - this.origin.x, this.endPoint.y - this.origin.y);
if (CrossProduct(v1, v2) > 0) {
return true;
}
return false;
}
});
//Circle类的定义
var Circle = Graphic.extend({
init: function (startPoint, endPoint, drawArea) {
this._super(startPoint, endPoint, drawArea);//调用父类的构造函数
this.r = DistanceOfTwoPoint(startPoint, endPoint);
this.origin = this.startPoint;
this.graphicType = "Circle";
},
//获取图元边界
getBounds: function () {
this.bounds = new Bounds(startPoint.x, startPoint.y, startPoint.x, startPoint.y);
var bounds = new Bounds(endPoint.x, endPoint.y, endPoint.x, endPoint.y);
this.bounds.extend(bounds);
return this.bounds;
},
drawTracker: function () {
var context = this.drawArea.context;
var sp = this.drawArea.getLocalXY(this.startPoint);
var top = new Point(sp.x, sp.y this.r / this.drawArea.res);
var down = new Point(sp.x, sp.y - this.r / this.drawArea.res);
var left = new Point(sp.x - this.r / this.drawArea.res, sp.y);
var right = new Point(sp.x this.r / this.drawArea.res, sp.y);
context.fillStyle = 'rgb(0,0,0)';
context.fillRect(sp.x - 5, sp.y - 5, 10, 10);
context.fillRect(top.x - 5, top.y - 5, 10, 10);
context.fillRect(down.x - 5, down.y - 5, 10, 10);
context.fillRect(left.x - 5, left.y - 5, 10, 10);
context.fillRect(right.x - 5, right.y - 5, 10, 10);
},
hitTest: function (pt) {
if (DistanceOfTwoPoint(pt, this.startPoint) - this.r <= 5 && DistanceOfTwoPoint(pt, this.startPoint) - this.r >= -5) {
return true;
}
return false;
},
getHandler: function (pt) {//未完成
if (DistanceOfTwoPoint(pt, this.startPoint) <= 5) {
return 1
}
if (DistanceOfTwoPoint(pt, this.endPoint) <= 5) {
return 2
}
return 0;
},
drawing: function () {
var drawArea = this.drawArea;
var _context = this.drawArea._context;
var pt = this.drawArea.getLocalXY(this.startPoint);
_context.setLineDash([5]);
_context.clearRect(0, 0, 10000, 10000);
_context.beginPath();
_context.arc(pt.x, pt.y, this.r / this.drawArea.res, 0, 2 * Math.PI, false);
_context.stroke();
_context.closePath();
},
draw: function () {
if (!this.hidden) {
var context = this.drawArea.context;
context.setLineDash([5]);
context.beginPath();
pt = this.drawArea.getLocalXY(this.startPoint);
context.arc(pt.x, pt.y, this.r / this.drawArea.res, 0, 2 * Math.PI, false);
context.stroke();
context.closePath();
if (this.selected) {
this.drawTracker();//如果选中的话 绘制控制点
}
}
},
//存为JSON对象
toJSON: function () {
//do something
},
//绘制尺寸
drawRuler: function () {
},
//移动对象
moveTO: function (pt) {
this.startPoint.x = this.startPoint.x pt.x;
this.startPoint.y = this.startPoint.y pt.y;
this.endPoint.x = this.endPoint.x pt.x;
this.endPoint.y = this.endPoint.y pt.y;
},
moveHandler: function (handlerNumber, pt) {
if (handlerNumber == 1) {
this.startPoint.x = this.startPoint.x pt.x;
this.startPoint.y = this.startPoint.y pt.y;
}
if (handlerNumber == 2) {
this.endPoint.x = this.endPoint.x pt.x;
this.endPoint.y = this.endPoint.y pt.y;
}
},
switchPoints: function () {
//虽然直线不需要转换点,但是必须有该函数
}
});
//Rectangle类的定义
var Rectangle = Graphic.extend({
init: function (startPoint, endPoint, drawArea) {
this._super(startPoint, endPoint, drawArea);//调用父类的构造函数
this.widthofRec = this.endPoint.x - this.startPoint.x;
this.heightofRec = this.endPoint.y - this.startPoint.y;
this.graphicType = "Rec";
},
//获取图元边界
getBounds: function () {
this.bounds = new Bounds(startPoint.x, startPoint.y, startPoint.x, startPoint.y);
var bounds = new Bounds(endPoint.x, endPoint.y, endPoint.x, endPoint.y);
this.bounds.extend(bounds);
return this.bounds;
},
drawTracker: function () {
var context = this.drawArea.context;
var sp = this.drawArea.getLocalXY(this.startPoint);
var topleft = sp;
var topright = new Point(topleft.x this.widthofRec / this.drawArea.res, topleft.y);
var bottomleft = new Point(topleft.x, topleft.y - this.heightofRec / this.drawArea.res);
var bottomright = new Point(topleft.x this.widthofRec / this.drawArea.res, topleft.y - this.heightofRec / this.drawArea.res);
context.fillRect(topleft.x - 5, topleft.y - 5, 10, 10);
context.fillRect(topright.x - 5, topright.y - 5, 10, 10);
context.fillRect(bottomleft.x - 5, bottomleft.y - 5, 10, 10);
context.fillRect(bottomright.x - 5, bottomright.y - 5, 10, 10);
},
hitTest: function (pt) {
var topright = new Point(this.startPoint.x this.widthofRec, this.startPoint.y);
var bottomleft = new Point(this.startPoint.x, this.startPoint.y - this.heightofRec);
var line1 = new Line(this.startPoint, topright);
var line2 = new Line(topright, this.endPoint);
var line3 = new Line(this.endPoint, bottomleft);
var line4 = new Line(bottomleft, this.startPoint);
if (DistanceToLine(pt, line1) <= 5 || DistanceToLine(pt, line2) <= 5 || DistanceToLine(pt, line3) <= 5 || DistanceToLine(pt, line4) <= 5) {
return true;
}
else {
return false;
}
},
//根据光标位置获取控制点
getHandler: function (pt) {
var pointSW = new Point(this.startPoint.x, this.endPoint.y);
var PointNE = new Point(this.endPoint.x, this.startPoint.y);
var lengthNW = DistanceOfTwoPoint(pt, this.startPoint);
var lengthSE = DistanceOfTwoPoint(pt, this.endPoint);
var lengthSW = DistanceOfTwoPoint(pt, pointSW);
var lengthNE = DistanceOfTwoPoint(pt, PointNE);
if (lengthNW <= 5) {
return 1;
}
if (lengthNE <= 5) {
return 2;
}
if (lengthSE <= 5) {
return 3;
}
if (lengthSW <= 5) {
return 4;
}
return 0;
},
drawing: function () {
var drawArea = this.drawArea;
var _context = this.drawArea._context;
var pt = this.drawArea.getLocalXY(this.startPoint);
_context.setLineDash([5]);
_context.clearRect(0, 0, 10000, 10000);
_context.beginPath();
_context.rect(pt.x, pt.y, this.widthofRec / this.drawArea.res, -this.heightofRec / this.drawArea.res);
_context.stroke();
_context.closePath();
},
draw: function () {
if (!this.hidden) {
var context = this.drawArea.context;
context.beginPath();
pt = this.drawArea.getLocalXY(this.startPoint);
context.rect(pt.x, pt.y, this.widthofRec / this.drawArea.res, -this.heightofRec / this.drawArea.res);
context.stroke();
context.closePath();
if (this.selected) {
this.drawTracker();//如果选中的话 绘制控制点
}
}
},
toJSON: function () {
//do something
},
//绘制尺寸
drawRuler: function () {
},
//移动对象
moveTO: function (pt) {
this.startPoint.x = this.startPoint.x pt.x;
this.startPoint.y = this.startPoint.y pt.y;
this.endPoint.x = this.endPoint.x pt.x;
this.endPoint.y = this.endPoint.y pt.y;
},
//移动控制点
moveHandler: function (handlerNumber, pt) {
if (handlerNumber == 1) {
this.startPoint.x = this.startPoint.x pt.x;
this.startPoint.y = this.startPoint.y pt.y;
}
if (handlerNumber == 2) {
this.startPoint.y = this.startPoint.y pt.y;
this.endPoint.x = this.endPoint.x pt.x;
}
if (handlerNumber == 3) {
this.endPoint.x = this.endPoint.x pt.x;
this.endPoint.y = this.endPoint.y pt.y;
}
if (handlerNumber == 4) {
this.startPoint.x = this.startPoint.x pt.x;
this.endPoint.y = this.endPoint.y pt.y;
}
},
//长方形有四种画法,把其他三种画法统一成第一种:向右下角画
switchPoints: function () {
/*
//往右上角画图
if(this.startPoint.x<this.endPoint.x&&this.startPoint.y>this.endPoint.y)
{
var spTemp=this.startPoint;//存放初始开始点
var epTemp=this.endPoint;//和结束点
this.startPoint=new Point(spTemp.x,epTemp.y);//初始点重新赋值
this.endPoint=new Point(epTemp.x,spTemp.y);//结束点重新赋值
}
//往左上角画图
if(this.startPoint.x>this.endPoint.x&&this.startPoint.y<this.endPoint.y)
{
var spTemp=this.startPoint;//存放初始开始点
var epTemp=this.endPoint;//和结束点
this.startPoint=new Point(epTemp.x,epTemp.y);//初始点重新赋值
this.endPoint=new Point(spTemp.x,spTemp.y);//结束点重新赋值
}
//往左下角画图
if(this.startPoint.x>this.endPoint.x&&this.startPoint.y>this.endPoint.y)
{
var spTemp=this.startPoint;//存放初始开始点
var epTemp=this.endPoint;//和结束点
this.startPoint=new Point(epTemp.x,spTemp.y);//初始点重新赋值
this.endPoint=new Point(spTemp.x,epTemp.y);//结束点重新赋值
}
*/
}
});
//缩放控制类
var Scale = Class.extend({
init: function (drawArea) {//构造函数
this.drawArea = drawArea;
this.div = drawArea.div;
this.Events = [["mousewheel", Scale.prototype.wheelChange], ["DOMMouseScroll", Scale.prototype.wheelChange]];
this.bind();
},
wheelChange: function (e) {
var drawArea = this.drawArea;
var delta = e.wheelDelta ? (e.wheelDelta / 120) * 20 : -e.detail / 3 * 20;
var deltalX = drawArea.size.w / 2 - (e.offsetX || e.layerX);
var deltalY = (e.offsetY || e.layerY) - drawArea.size.h / 2;
var px = {x: (e.offsetX || e.layerX), y: (e.offsetY || e.layerY)};
var zoomPoint = this.drawArea.getPositionFromPx(px);
var zoom = this.drawArea.zoom delta;
var newRes = this.drawArea.getResFromZoom(zoom);
var center = new Point(zoomPoint.x deltalX * newRes, zoomPoint.y deltalY * newRes);
this.drawArea.moveTo(zoom, center);
stopEventBubble(e);
/* var point1=new Point(0,0);
var point2=new Point(100,100);
var point3=new Point(0,100);
var point4=new Point(100,0);
var line1=new Line(point1,point2,drawArea);
var line2=new Line(point3,point4,drawArea);
var point5=LinesIntresectPoint(line1,line2);*/
},
bind: function () {
for (var i = 0, len = this.Events.length; i < len; i ) {
var type = this.Events[i][0];
var listener = this.Events[i][1];
listener = bindAsEventListener(listener, this);
this.div.addEventListener(type, listener, true);
}
}
});
//画布平移控制类
var Pan = Class.extend({
init: function (drawArea) {//构造函数
this.drawArea = drawArea;
this.div = drawArea.div;
this.Events = [["mousedown", Pan.prototype.startPan],
["mousemove", Pan.prototype.pan],
["mouseup", Pan.prototype.endPan]];
this.dragging = false;
this.bind();
this.drawing = false;
this.drawingArc = false;
this.startArc = 0;
//用于区别鼠标第几次按下
this.mat = 1;
this.startPoint = null;
this.endPoint = null;
this.endPoint1 = null;//画圆弧需要采集3个点
this.selecting = false;
this.jiaodian = false;
},
startPan: function (e) {
//第一次按下鼠标
if (e.button == 1) {
//按下鼠标中键时设置拖动开关
this.dragging = true;
//设置鼠标样式。
this.drawArea.div.style.cursor = "move";
}
if (e.button == 0 && this.mat == 1) {
if (!this.selecting)
this.drawing = true;
if (this.drawArea.tool == "Arc") {
this.drawingArc = true;
this.startArc = 1;
//alert("1");
}
//在一开始保存点击的位置,不变。
this.startX = (e.offsetX || e.layerX);
this.startY = (e.offsetY || e.layerY);
if (!this.jiaodian) {
this.startPoint = this.drawArea.getPositionFromPx(new Point(this.startX, this.startY));
}
else {
this.startPoint = this.drawArea.intersectionPoint;
}
if (this.selecting) {
for (var i = 0; i < this.drawArea.graphicList.length; i )//判断哪个图元被选中
{
var selectedGraphic = this.drawArea.graphicList[i];
if (selectedGraphic.hitTest(this.startPoint)) {
selectedGraphic.selected = true;
this.drawArea.selectedGraphicList.push(selectedGraphic);
}
}
this.drawArea.refresh();
}
}
//在一开始保存点击的位置,改变。
this.lastX = (e.offsetX || e.layerX);
this.lastY = (e.offsetY || e.layerY);
//第二次按下鼠标 非绘制圆弧时
if (this.mat == 2) {
if (!this.drawingArc) {
this.drawing = false;
var graphic = this.drawArea.graphic;
if (graphic.graphicType != "Rec") {
this.drawArea.addGraphic(graphic);
}
else {
var lt = new Point(graphic.startPoint.x, graphic.startPoint.y);
var rt = new Point(graphic.endPoint.x, graphic.startPoint.y);
var lb = new Point(graphic.startPoint.x, graphic.endPoint.y);
var rb = new Point(graphic.endPoint.x, graphic.endPoint.y);
var line1 = new Line(lt, rt, graphic.drawArea);
var line2 = new Line(rt, rb, graphic.drawArea);
var line3 = new Line(rb, lb, graphic.drawArea);
var line4 = new Line(lb, lt, graphic.drawArea);
this.drawArea.addGraphic(line1);
this.drawArea.addGraphic(line2);
this.drawArea.addGraphic(line3);
this.drawArea.addGraphic(line4);
}
this.mat = 1;//将鼠标控制交还给第一次按鼠标动作
if (graphic.graphicType == "Line") {
this.drawArea.pointList.push(graphic.startPoint);
this.drawArea.pointList.push(graphic.endPoint);
}
if (graphic.graphicType == "Circle") {
this.drawArea.pointList.push(graphic.startPoint);
}
if (graphic.graphicType == "Rec") {
this.drawArea.pointList.push(graphic.startPoint);
this.drawArea.pointList.push(graphic.endPoint);
var point1 = new Point(graphic.startPoint.x, graphic.endPoint.y);
var point2 = new Point(graphic.endPoint.x, graphic.startPoint.y);
this.drawArea.pointList.push(point1);
this.drawArea.pointList.push(point2);
}
if (this.drawArea.graphicList.length >= 1) {
for (var i = 0; i < this.drawArea.graphicList.length - 1; i ) {
var g = this.drawArea.graphicList[i];
if (graphic.graphicType == "Line" && g.graphicType == "Line") {
var point = LinesIntresectPoint(graphic, g);
if (point != null)
this.drawArea.pointList.push(point);
}
if (graphic.graphicType == "Line" && g.graphicType != "Line") {
//debugger;
var pointList1 = LineArcIntresectPoint(graphic, g);
if (pointList1 != null) {
for (var j = 0; j < pointList1.length; j ) {
this.drawArea.pointList.push(pointList1[j]);
}
}
}
if (graphic.graphicType == "Circle" && g.graphicType == "Line") {
var pointList1 = LineArcIntresectPoint(g, graphic);
if (pointList1 != null) {
for (var j = 0; j < pointList1.length; j ) {
this.drawArea.pointList.push(pointList1[j]);
}
}
}
if (graphic.graphicType == "Circle" && g.graphicType != "Line") {
var pointList1 = arcAndArcIntersection(g, graphic);
if (pointList1 != null) {
for (var j = 0; j < pointList1.length; j ) {
this.drawArea.pointList.push(pointList1[j]);
}
}
}
if (graphic.graphicType == "Rec" && g.graphicType == "Line") {
var lt = new Point(graphic.startPoint.x, graphic.startPoint.y);
var rt = new Point(graphic.endPoint.x, graphic.startPoint.y);
var lb = new Point(graphic.startPoint.x, graphic.endPoint.y);
var rb = new Point(graphic.endPoint.x, graphic.endPoint.y);
var line1 = new Line(lt, rt, graphic.drawArea);
var line2 = new Line(rt, rb, graphic.drawArea);
var line3 = new Line(rb, lb, graphic.drawArea);
var line4 = new Line(lb, lt, graphic.drawArea);
var lineList = [line1, line2, line3, line4];
for (var m = 0; m < lineList.length; m ) {
var line = lineList[m];
var point = LinesIntresectPoint(line, g);
if (point != null)
this.drawArea.pointList.push(point);
}
}
if (graphic.graphicType == "Rec" && g.graphicType != "Line") {
var lt = new Point(graphic.startPoint.x, graphic.startPoint.y);
var rt = new Point(graphic.endPoint.x, graphic.startPoint.y);
var lb = new Point(graphic.startPoint.x, graphic.endPoint.y);
var rb = new Point(graphic.endPoint.x, graphic.endPoint.y);
var line1 = new Line(lt, rt, graphic.drawArea);
var line2 = new Line(rt, rb, graphic.drawArea);
var line3 = new Line(rb, lb, graphic.drawArea);
var line4 = new Line(lb, lt, graphic.drawArea);
var lineList = [line1, line2, line3, line4];
for (var m = 0; m < lineList.length; m ) {
var line = lineList[m];
var pointList1 = LineArcIntresectPoint(line, g);
if (pointList1 != null) {
for (var j = 0; j < pointList1.length; j ) {
this.drawArea.pointList.push(pointList1[j]);
}
}
}
}
}
}
}
else {
if (!this.jiaodian) {
this.endPoint = this.drawArea.getPositionFromPx(new Point(this.lastX, this.lastY));
}
else {
this.endPoint = this.drawArea.intersectionPoint;
}
this.startArc = 2;
//alert("2");
}
}
//第三次按下鼠标 绘制圆弧时
if (this.mat == 3) {
this.drawing = false;
this.drawingArc = false;
var graphic = this.drawArea.graphic;
this.drawArea.addGraphic(graphic);
if (graphic.graphicType == "Arc") {
this.drawArea.pointList.push(graphic.origin);
this.drawArea.pointList.push(graphic.startPoint);
this.drawArea.pointList.push(graphic.endPoint);
for (var i = 0; i < this.drawArea.graphicList.length - 1; i ) {
var g = this.drawArea.graphicList[i];
if (g.graphicType == "Line") {
var pointList1 = LineArcIntresectPoint(g, graphic);
if (pointList1 != null) {
for (var j = 0; j < pointList1.length; j ) {
this.drawArea.pointList.push(pointList1[j]);
}
}
}
else {
var pointList1 = arcAndArcIntersection(g, graphic);
if (pointList1 != null) {
for (var j = 0; j < pointList1.length; j ) {
this.drawArea.pointList.push(pointList1[j]);
}
}
}
}
}
this.mat = 1;//将鼠标控制交还给第一次按鼠标动作
this.startArc = 0;
// alert("3");
//debugger;
}
stopEventBubble(e);
},
pan: function (e) {
var drawArea = this.drawArea;
//计算改变的像素值
var dx = (e.offsetX || e.layerX) - this.lastX;
var dy = (e.offsetY || e.layerY) - this.lastY;
this.lastX = (e.offsetX || e.layerX);
this.lastY = (e.offsetY || e.layerY);
this.jiaodian = false;
var cursorPositon = this.drawArea.getPositionFromPx(new Point(this.lastX, this.lastY));
for (var i = 0; i < drawArea.pointList.length; i ) {
if (DistanceOfTwoPoint(cursorPositon, drawArea.pointList[i]) <= 5) {
drawArea.div.style.cursor = "crosshair";
this.jiaodian = true;
drawArea.intersectionPoint = drawArea.pointList[i];
break;
}
}
if (!this.jiaodian) {
drawArea.div.style.cursor = "default";
}
if (this.dragging) {
drawArea.center.x -= dx * drawArea.res;
drawArea.center.y = dy * drawArea.res;
drawArea.moveTo(drawArea.zoom, drawArea.center);
}
//选择动作
if (drawArea.tool == "Pointer") {
this.selecting = true;
}
if (drawArea.tool != "Pointer") {
this.selecting = false;
}
//前画布绘制非圆弧的动作
if (this.drawing) {
if (!this.drawingArc) {
if (!this.jiaodian) {
this.endPoint = drawArea.getPositionFromPx(new Point(this.lastX, this.lastY));
}
else {
this.endPoint = drawArea.intersectionPoint;
}
if (drawArea.tool == "Line") {
drawArea.graphic = new Line(this.startPoint, this.endPoint, this.drawArea);
}
if (drawArea.tool == "Circle") {
drawArea.graphic = new Circle(this.startPoint, this.endPoint, this.drawArea);
}
if (drawArea.tool == "Rectangle") {
drawArea.graphic = new Rectangle(this.startPoint, this.endPoint, this.drawArea);
}
this.mat = 2;//将鼠标控制转移至第二次按鼠标动作
drawArea.graphic.drawing();
}
else {
if (mat = 1 && this.startArc == 1)
this.mat = 2;
if (this.startArc == 2) {
this.endPoint1 = this.drawArea.getPositionFromPx(new Point(this.lastX, this.lastY));
drawArea.graphic = new Arc(this.startPoint, this.endPoint, this.endPoint1, drawArea);
this.mat = 3;
drawArea.graphic.drawing();
}
}
}
stopEventBubble(e);
},
endPan: function (e) {
this.drawArea.div.style.cursor = "default";
this.dragging = false;
this.drawArea._context.clearRect(0, 0, 10000, 10000);
this.drawArea.refresh();
stopEventBubble(e);
this.mat = 1;
},
bind: function () {
for (var i = 0, len = this.Events.length; i < len; i ) {
var type = this.Events[i][0];
var listener = this.Events[i][1];
listener = bindAsEventListener(listener, this);
this.div.addEventListener(type, listener, true);
}
}
});
//下面是一些公用的方法
function bindAsEventListener(func, object) {
return function (event) {
return func.call(object, event || window.event);
};
}
function stopEventBubble(e) {
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
if (e && e.stopPropagation)
e.stopPropagation();
else
window.event.cancelBubble = true;
}
//复制对象
function cloneObj(obj) {
var reObj = {};
for (var id in obj) {
reObj[id] = obj[id];
}
return reObj;
}
//两点之间的距离
function DistanceOfTwoPoint(pt1, pt2) {
var difY = pt2.y - pt1.y;
var difX = pt2.x - pt1.x;
return Math.pow((difX * difX difY * difY), 0.5);
}
//点到直线的距离
function DistanceToLine(pt, line) {
var point1 = line.startPoint;
var point2 = line.endPoint;
var A = point2.y - point1.y;
var B = point1.x - point2.x;
var C = point1.y * (-B) - point1.x * A;
var upElement = A * pt.x B * pt.y C;
if (upElement < 0) {
upElement = -upElement;
}
var downElement = Math.pow((A * A B * B), 0.5);
return upElement / downElement;
}
//点到圆弧的距离
function DistanceToArc(pt, arc) {
if (DistanceOfTwoPoint(pt, arc.origin) >= r - 5 && DistanceOfTwoPoint(pt, arc.origin) <= r 5) {
return true;
}
return false;
}
//求point与origin所在x轴坐标的弧度大小
function GetRad(origin, point) {
if (origin.x == point.x) {
if (point.y < origin.y)
return Math.PI / 2;
else
return Math.PI * 3 / 2;
}
var x = point.x - origin.x;
var y = point.y - origin.y;
if (x > 0) {
if (y < 0)
return Math.atan(-y / x);
else
return 2 * Math.PI - Math.atan(y / x);
}
else {
if (y < 0)
return Math.PI - Math.atan(y / x);
else
return Math.PI Math.atan(-y / x);
}
}
//线段是否相交不求交点
function LinesIntresect(line1, line2) {
var p1 = new Point(line1.startPoint);
var p2 = new Point(line1.endPoint);
var p3 = new Point(line2.startPoint);
var p4 = new Point(line2.endPoint);
var d1 = Direction(p3, p4, p1);
var d2 = Direction(p3, p4, p2);
var d3 = Direction(p1, p2, p3);
var d4 = Direction(p1, p2, p4);
if (d1 * d2 < 0 && d3 * d4 < 0) {
return true;
}
else if (d1 == 0 && OnSegment(p3, p4, p1)) {
return true;
}
else if (d2 == 0 && OnSegment(p3, p4, p2)) {
return true;
}
else if (d3 == 0 && OnSegment(p1, p2, p3)) {
return true;
}
else if (d4 == 0 && OnSegment(p1, p2, p4)) {
return true;
}
else {
return false;
}
}
//线段是否相交并求交点
function LinesIntresectPoint(line1, line2) {
var p1 = new Point(line1.startPoint.x, line1.startPoint.y);
var p2 = new Point(line1.endPoint.x, line1.endPoint.y);
var p3 = new Point(line2.startPoint.x, line2.startPoint.y);
var p4 = new Point(line2.endPoint.x, line2.endPoint.y);
var d1 = Direction(p3, p4, p1);
var d2 = Direction(p3, p4, p2);
var d3 = Direction(p1, p2, p3);
var d4 = Direction(p1, p2, p4);
if (d1 * d2 < 0 && d3 * d4 < 0) {
var x = (d1 * p2.x - d2 * p1.x) / (d1 - d2);
var y = (d1 * p2.y - d2 * p1.y) / (d1 - d2);
return new Point(x, y);
}
else if (d1 == 0 && OnSegment(p3, p4, p1)) {
return new Point(p1.x, p1.y);
}
else if (d2 == 0 && OnSegment(p3, p4, p2)) {
return new Point(p2.x, p2.y);
}
else if (d3 == 0 && OnSegment(p1, p2, p3)) {
return new Point(p3.x, p3.y);
}
else if (d4 == 0 && OnSegment(p1, p2, p4)) {
return new Point(p4.x, p4.y);
}
else {
return null;
}
}
//向量的叉积
function CrossProduct(vector1, vector2) {
return (vector1.x * vector2.y - vector2.x * vector1.y);
}
//三点构成的三角形的有效面积
function Direction(p1, p2, p3) {
var v1 = new Vector((p3.x - p1.x), (p3.y - p1.y));
var v2 = new Vector((p2.x - p1.x), (p2.y - p1.y));
return CrossProduct(v1, v2);
}
//p3是否在p1p2这条线段内
function OnSegment(p1, p2, p3) {
if (p3.x >= Math.min(p1.x, p2.x) && p3.x <= Math.max(p1.x, p2.x) && p3.y >= Math.min(p1.y, p2.y) && p3.y <= Math.max(p1.y, p2.y)) {
return true;
}
else {
return false;
}
}
//线段是否穿过矩形边界
function SegmentCrossBound(line, bound) {
var p3 = new Point(bound.x1, bound.y1);
var p4 = new Point(bound.x2.bound.y2);
var p5 = new Point(bound.x1.bound.y2);
var p6 = new Point(bound.x2.bound.y1);
var line1 = new Line(p3, p4, line.drawArea);
var line2 = new Line(p5, p6, line.drawArea);
if (LinesIntresect(line, line1) || LinesIntresect(line, line2)) {
return true;
}
return false;
}
//点到线段的投影
function pointProjectionToLine(pt, line) {
var p1 = new Point(line.startPoint.x, line.startPoint.y);
var p2 = new Point(line.endPoint.x, line.endPoint.y);
var p3 = new Point(pt.x, pt.y);
var v1 = new Vector(p3.x - p1.x, p3.y - p1.y);
var v2 = new Vector(p2.x - p1.x, p2.y - p1.y);
var m = v1.x * v2.x v1.y * v2.y;
var k = m / line.lineLength / line.lineLength;
var p0 = new Point(0, 0);
p0.x = k * (p2.x - p1.x) p1.x;
p0.y = k * (p2.y - p1.y) p1.y;
return p0;
}
//点到线段的投影在线段内部
function pointProjectionInSegment(pt, line) {
var p1 = new Point(line.startPoint.x, line.startPoint.y);
var p2 = new Point(line.endPoint.x, line.endPoint.y);
var p3 = new Point(pt.x, pt.y);
var v1 = new Vector(p3.x - p1.x, p3.y - p1.y);
var v2 = new Vector(p2.x - p1.x, p2.y - p1.y);
var m = v1.x * v2.x v1.y * v2.y;
var k = m / line.lineLength / line.lineLength;
if (k < 0) {
k = -k;
}
if (k <= 1) {
return true;
}
return false;
}
function LineArcIntresectPoint(line, arc)//求直线与圆弧的交点
{
var lineStartP = new Point(line.startPoint.x, line.startPoint.y);
var lineEndP = new Point(line.endPoint.x, line.endPoint.y);
var origin = new Point(arc.origin.x, arc.origin.y);
var r = arc.r;
//var startAngel=arc.startAngel;
// var endAngel=arc.endAngel;
var d0 = DistanceToLine(origin, line);
var d1 = DistanceOfTwoPoint(origin, lineStartP);
var d2 = DistanceOfTwoPoint(origin, lineEndP);
var flag = pointProjectionInSegment(origin, line);//圆点的投影是否在直线上
var pointList = [];
if (d0 > r)//圆心到线段的距离大于半径,肯定无交点
{
return null;
}
if (d0 == r)//等于半径,可能有一个切点
{
if (!flag) {
return false;
}
else {
var p0 = pointProjectionToLine(origin, line);
pointList.push(p0);
}
}
if (d0 < r)//下于半径,可能无交点,一个交点,或者两个交点
{
if (d1 < r && d2 < r)//线段在圆内部,无交点
{
return null;
}
if (d1 > r && d2 > r && !flag)//线段在圆外部且无交点
{
return null;
}
else {
var intersectionPoints = [];
var p0 = pointProjectionToLine(origin, line);
var p0ToArc = Math.sqrt(r * r - d0 * d0);
if (d1 >= r) {
var k = (DistanceOfTwoPoint(p0, lineStartP) - p0ToArc) / DistanceOfTwoPoint(p0, lineStartP);
var point1 = new Point(0, 0);
point1.x = k * (p0.x - lineStartP.x) lineStartP.x;
point1.y = k * (p0.y - lineStartP.y) lineStartP.y;
pointList.push(point1);
}
if (d2 >= r) {
var k = p0ToArc / DistanceOfTwoPoint(p0, lineEndP);
var point2 = new Point(0, 0);
point2.x = k * (lineEndP.x - p0.x) p0.x;
point2.y = k * (lineEndP.y - p0.y) p0.y;
var d1 = Direction(arc.startPoint, arc.endPoint, point2);
var d2 = Direction(arc.startPoint, arc.endPoint, origin);
pointList.push(point2);
}
}
}
return pointList;
}
function arcAndArcIntersection(arc1, arc2) {
var o1 = arc1.origin;
var o2 = arc2.origin;
var r1 = arc1.r;
var r2 = arc2.r;
var d = DistanceOfTwoPoint(o1, o2);
var pointList = [];
var rdifference = r1 - r2;
if (rdifference < 0)
rdifference = -rdifference;
if (d == (r1 r2)) {
var x = r1 / d * (o2.x - o1.x) o1.x;
var y = r1 / d * (o2.x - o1.x) o1.x;
var point = new Point(x, y);
pointList.push(point);
}
if (d < (r1 r2) && d > rdifference) {
var a = (r1 * r1 d * d - r2 * r2) / (2 * d);
var h = Math.sqrt(r1 * r1 - a * a);
var x = a / d * (o2.x - o1.x) o1.x;
var y = a / d * (o2.y - o1.y) o1.y;
var x1 = x h * (o2.y - o1.y) / d;
var y1 = y - h * (o2.x - o1.x) / d;
var x2 = x - h * (o2.y - o1.y) / d;
var y2 = y h * (o2.x - o1.x) / d;
var point1 = new Point(x1, y1);
var point2 = new Point(x2, y2);
pointList.push(point1);
pointList.push(point2);
}
// debugger;
return pointList;
}
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论