html5+canvas多实体交互

html代码

<!DOCTYPEhtml PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml">
<head>
<metahttp-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>canvas实例</title>
<style>
    body { background-color:yellow;}
    #c1 { background-color: white; }
</style>
	<script type="text/javascript" src="./draw.js"></script>
</head>

<body>
    <button onclick="selectEntity(0)">绘制皮带秤</button>
    <button onclick="selectEntity(1)">绘制皮带</button>
    
<canvas id="c1" width="500px" height="500px">
<span>不支持canvas</span>
</canvas>
</body>
</html>

js代码

function Position(x, y){
	this.x = x;
	this.y = y;
}

var Vector = function (x, y) {
    var vec = {
        vx: x,
        vy: y,
        // 缩放
        scale: function (scale) {
            vec.vx *= scale;
            vec.vy *= scale;
        },
        //加 另一个向量
        add: function (vec2) {
            vec.vx += vec2.vx;
            vec.vy += vec2.vy;
        },
        //减 另一个向量
        sub: function (vec2) {
            vec.vx -= vec2.vx;
            vec.vy -= vec2.vy;
		},
		equal:function(vec2){
			if((Math.abs(vec2.vx - vec.vx) < 0.01) && (Math.abs(vec2.vy - vec.vy) < 0.01))
				return true;
			return false;
		},
        //相反方向
        negate: function () {
            vec.vx = -vec.vx;
            vec.vy = -vec.vy;
        },
        //向量长度
        length: function () {
            return Math.sqrt(vec.vx * vec.vx + vec.vy * vec.vy);
        },
        //向量长度的平方
        lengthSquared: function () {
            return vec.vx * vec.vx + vec.vy * vec.vy;
        },
        //标准化
        normalize: function () {
            var len = Math.sqrt(vec.vx * vec.vx + vec.vy * vec.vy);
            if (len) {
                vec.vx /= len;
                vec.vy /= len;
            }
            return len;
		},
        //旋转
        rotate: function (angle) {
            var vx = vec.vx,
                vy = vec.vy,
                cosVal = Math.cos(angle),
                sinVal = Math.sin(angle);
            vec.vx = vx * cosVal - vy * sinVal;
            vec.vy = vx * sinVal + vy * cosVal;
        },
        //调试
        toString: function () {
            return '(' + vec.vx.toFixed(3) + ',' + vec.vy.toFixed(3) + ')';
        }
    };
    return vec;
};

function Draw(context){
	this.context = context;
}

function Circle(context, center){
	Draw.call(this, context);
	this.center = center;
	this.radius = 10.0;
}
Circle.prototype = new Draw();
Circle.prototype.draw = function(){
	//外圆
	this.context.fillStyle = "#555555";
	this.context.strokeStyle = "#333333";
	this.context.beginPath();
	this.context.arc(this.center.x, this.center.y, this.radius, 0, 2*Math.PI, true);
	this.context.closePath();
	this.context.stroke();
	this.context.fill();
	//内圆
	this.context.fillStyle = "#888888";
	this.context.beginPath();
	this.context.arc(this.center.x, this.center.y, this.radius * 0.5, 0, 2*Math.PI, true);
	this.context.closePath();
	this.context.fill();
};

function Line(context, lineWeight, startPosition, endPosition){
	Draw.call(this, context);
	this.startPosition = startPosition;
	this.endPosition = endPosition;
	this.strokeStyle = "rgba(0,255,0,1.0)";
	this.lineWeight = lineWeight;
}
Line.prototype = new Draw();
Line.prototype.draw = function(){
	this.context.strokeStyle = this.strokeStyle;
	this.context.lineWidth = this.lineWeight;
	this.context.moveTo(this.startPosition.x, this.startPosition.y);
	this.context.lineTo(this.endPosition.x, this.endPosition.y);
	this.context.stroke();
};

Line.prototype.select = function(position){
	var v1 = Vector((position.x - this.startPosition.x), (position.y - this.startPosition.y));
	var dir1 = Vector((position.x - this.startPosition.x), (position.y - this.startPosition.y));
	dir1.normalize();

	var v2 = Vector((this.endPosition.x - this.startPosition.x), (this.endPosition.y - this.startPosition.y));
	var dir2 = Vector((this.endPosition.x - this.startPosition.x), (this.endPosition.y - this.startPosition.y));
	dir2.normalize();

	//判断方向向量和距离
	if(dir1.equal(dir2) && v1.length() <= v2.length()){
		this.strokeStyle =  "rgba(0,255,255,0.5)";
		return true;
	}
	else 
		this.strokeStyle =  "rgba(0,255,0,1.0)";
	return false;
};

function Arrow(context, startPosition, endPosition){
	Draw.call(this, context);
	this.startPosition = startPosition;
	this.endPosition = endPosition;
}
Arrow.prototype = new Draw();
Arrow.prototype.draw = function(){
	var step = 15;
	var dir = Vector((this.endPosition.x - this.startPosition.x), (this.endPosition.y - this.startPosition.y));
	dir.normalize();
	this.context.fillStyle = "rgba(0,255,0,0.2)";
	this.context.save();
	this.context.translate(this.endPosition.x - step * dir.vx, this.endPosition.y - step * dir.vy);
	
	this.context.moveTo(-step * dir.vy , step * dir.vx);
	this.context.lineTo(step * dir.vx, step * dir.vy);
	this.context.lineTo(step * dir.vy , -step * dir.vx);
	this.context.stroke();
	this.context.restore();
}

function TextString(text, context, startPosition, endPosition){
	Draw.call(this, context);
	this.startPosition = startPosition;
	this.endPosition = endPosition;
	this.strokeStyle =  "rgba(0,255,0,1.0)";
	this.text = text;
}
TextString.prototype = new Draw();
TextString.prototype.draw = function(){
	this.context.fillStyle = "#ff0000";
	this.context.strokeStyle = "green";
	this.context.font = "20px sans-serif";
	this.context.fillText(this.text, this.startPosition.x, this.startPosition.y);
};

function BeltWeight(name, context, startPosition, endPosition){
	Draw.call(this, context);
	this.circle = new Circle(context, startPosition);
	this.line = new Line(context, 5, startPosition, endPosition);
	this.arrow = new Arrow(context, startPosition, endPosition);
	this.text = new TextString(name, context, startPosition, endPosition);
}
BeltWeight.prototype = new Draw();
BeltWeight.prototype.draw = function(){
	this.circle.draw();
	this.line.draw();
	this.arrow.draw();
	this.text.draw();
}

BeltWeight.prototype.select = function(position){
	return this.line.select(position);
}

function Belt(name, context, startPosition, endPosition){
	Draw.call(this, context);
	this.startCircle = new Circle(context, startPosition);
	this.line = new Line(context, 10, startPosition, endPosition);
	this.endCircle = new Circle(context, endPosition);
	this.text = new TextString(name, context, startPosition, endPosition);
}
Belt.prototype = new Draw();
Belt.prototype.draw = function(){
	this.startCircle.draw();
	this.line.draw();
	this.endCircle.draw();
	this.text.draw();
}

Belt.prototype.select = function(position){
	return this.line.select(position);
}

var entityType = 0;
function selectEntity(type){
	entityType = type;
}

function Handle(context, clientWidth, clientHeight){
	this.context = context;
	this.clientWidth = clientWidth;
	this.clientHeight = clientHeight;

	this.mouseFlag = false;
	this.startPosition = null;
	this.endPosition = null;

	this.beltWeights = [];
	this.belts = [];
	this.curEntity = null;
	this.selectBeltIndex = -1;
	this.selectBeltWeightIndex = -1;
	this.entityType = 0;
}

Handle.prototype.setEntityType = function(entityType){
	this.entityType = entityType;
}

Handle.prototype.mousedown = function(position){
	this.mouseFlag = true;
	this.startPosition = position;
};

Handle.prototype.mousemove = function(position){
	this.endPosition = position;
	this.context.clearRect(0,0,this.clientWidth, this.clientHeight);
	this.selectBeltWeightIndex = -1;
	this.selectBeltIndex = -1;

	if(this.mouseFlag){

		if(entityType == 0)
			this.curEntity = new BeltWeight("BeltWeight" + this.beltWeights.length, this.context, this.startPosition, this.endPosition);
		else
			this.curEntity = new Belt("Belt" + this.belts.length, this.context, this.startPosition, this.endPosition);
		this.curEntity.draw();

		for(var index=0; index<this.beltWeights.length; ++index){
			this.beltWeights[index].select(position);
			this.beltWeights[index].draw();
		}

		for(var index=0; index<this.belts.length; ++index){
			this.belts[index].select(position);
			this.belts[index].draw();
		}

	}else{

		for(let index=0; index<this.beltWeights.length; ++index){
			var bSelect = this.beltWeights[index].select(position);
			if(bSelect)
				this.selectBeltWeightIndex = index;
			this.beltWeights[index].draw();
		}

		for(let index=0; index<this.belts.length; ++index){
			var bSelect = this.belts[index].select(position);
			if(bSelect)
				this.selectBeltIndex = index;
			this.belts[index].draw();
		}
	}
};

Handle.prototype.mouseup = function(){
	this.mouseFlag = false;

	if(entityType == 0){
		this.beltWeights.push(this.curEntity);
	}else{
		this.belts.push(this.curEntity);
	}

	this.context.clearRect(0,0,this.clientWidth,this.clientHeight);
	for(let index=0; index<this.beltWeights.length; ++index){
		this.beltWeights[index].draw();
	}

	for(let index=0; index<this.belts.length; ++index){
		this.belts[index].draw();
	}
};

Handle.prototype.keydown = function(){

	if(this.selectBeltWeightIndex != -1)
		this.beltWeights.splice(this.selectBeltWeightIndex, 1);
	this.selectBeltWeightIndex = -1;

	if(this.selectBeltIndex != -1)
		this.belts.splice(this.selectBeltIndex, 1);
	this.selectBeltIndex = -1;


	this.context.clearRect(0,0,this.clientWidth, this.clientHeight);

	for(let index=0; index<this.beltWeights.length; ++index){
		this.beltWeights[index].draw();
	}

	for(let index=0; index<this.belts.length; ++index){
		this.belts[index].draw();
	}
};

window.onload = function() {
	var canvas = document.getElementById('c1');
	if ( ! canvas || ! canvas.getContext ) { return false; }
	var handle = new Handle(canvas.getContext('2d'), canvas.clientWidth, canvas.clientHeight);

	canvas.onmousedown = function(ev) {
		var ev = ev || window.event;
		handle.mousedown(new Position(ev.clientX-canvas.offsetLeft,ev.clientY-canvas.offsetTop));
	};

	canvas.onmousemove = function(ev) {
		var ev = ev || window.event;//获取event对象
		handle.mousemove(new Position(ev.clientX-canvas.offsetLeft,ev.clientY-canvas.offsetTop));
	};

	canvas.onmouseup = function(ev) {
		document.onmousemove = null;
		document.onmouseup = null;
		handle.mouseup();
	};

	function onkeydown(e) {
			var keyID = e.keyCode ? e.keyCode :e.which;
			if(keyID === 46)  { // delete
				handle.keydown();
				e.preventDefault();
			}
		}

	canvas.addEventListener('keydown', onkeydown, true);
	window.addEventListener('keydown', onkeydown, true);
};

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值