01
2016
04

反向动力学应用-可拖动的圆规(html5版)

之前完成了flash版本的“反向动力学应用-可拖动的圆规”,用flash cc改成了html5版的。

还是先看效果。


源码如下(flash cc中帧上代码):

this.stop();
var stage = this.getStage();
var divider = this.divider;
var legL = divider.legL;
var legR = divider.legR;
var lp = divider.lp;
var mp = divider.mp;
var rp = divider.rp;

var 移动末端;
var 移动端点;
var 关节;
var 固定端点;
var 固定杆;
var 活动杆;

var 可活动长度;
var 活动杆长度;
var 固定杆长度;

var targetX;
var targetY;
var dragType=0;

legL.addEventListener("mousedown", dragLhandler);
lp.addEventListener("mousedown", dragLhandler);

legR.addEventListener("mousedown", dragRhandler);
rp.addEventListener("mousedown", dragRhandler);

divider.addEventListener("mousedown", draghandler);
stage.addEventListener("mouseup", mouseUpHandler);

stage.addEventListener("pressmove", pressMoveHandler);

function mouseUpHandler(e){
	dragType=0;
}
/**
* 整体拖动
*/
function draghandler(e){
	console.log("整体拖动");
	dragType=2;
}
/**
 * 拖动左边
 * @param	e
 */
function dragLhandler(e) {
	console.log("拖动左边");
	e.stopPropagation();
	var p=divider.globalToLocal(stage.mouseX, stage.mouseY);
	targetX = p.x;
	targetY = p.y;
	移动端点 = p;
	移动末端 = lp;关节 = mp;
	固定端点 = rp;
	固定杆 = legR;
	活动杆 = legL;

	活动杆长度 = distance(移动末端, 关节);
	固定杆长度 = distance(固定端点, 关节);
	可活动长度 = distance(移动端点, 关节);
	dragType=1;
}

/**
 * 拖动右边
 * @param	e
 */
function dragRhandler(e) {
	console.log("拖动右边");
	e.stopPropagation();
	var p=divider.globalToLocal(stage.mouseX, stage.mouseY);
	targetX = p.x;
	targetY = p.y;
	移动端点 =p;
	移动末端 = rp;
	关节 = mp;
	固定端点 = lp;
	固定杆 = legL;
	活动杆 = legR;
	活动杆长度 = distance(移动末端, 关节);
	固定杆长度 = distance(固定端点, 关节);
	可活动长度 = distance(移动端点, 关节);
	dragType=1;
}
/**
 * 几何距离
 */
function distance(obj1, obj2) {
	return Math.sqrt((obj1.y - obj2.y) * (obj1.y - obj2.y) + (obj1.x - obj2.x) * (obj1.x - obj2.x));
}
/**
* 鼠标按下拖动
*/
function pressMoveHandler(e) {
	//move();
	if(dragType==1){
		move();
	}
	else if(dragType==2){
		divider.x=stage.mouseX;
		divider.y=stage.mouseY;
	}
}

/**
* 碰撞检测
* @return {[type]} [description]
*/
function hitTest(){ 
	var r1=固定端点.nominalBounds.width/2;
	var r2=移动末端.nominalBounds.width/2;
	return distance(固定端点,移动末端)<=(r1+r2);
}
/**
*
*/
function move() {
	var p=divider.globalToLocal(stage.mouseX, stage.mouseY);
	if(segmentsIntr(移动末端,p,关节,固定端点)){ 
		return;
	}
	if (hitTest()) {
		//trace("撞到了");
		var p1 = new createjs.Point(p.x - targetX, p.y - targetY);
		var p2 = new createjs.Point(移动末端.x - 固定端点.x, 移动末端.y - 固定端点.y);
		if (p1.x * p2.x + p1.y * p2.y < 0) {
			//trace("不能移动");
			return;
		}
	}
	//
	var flag = true;
	var count = 0;
	targetX = p.x;
	targetY = p.y;
	while (flag) {
		move2target(targetX, targetY);

		var angle01 = Math.atan2(targetY - 关节.y, targetX - 关节.x);
		var angle02 = Math.atan2(移动末端.y - 关节.y, 移动末端.x - 关节.x);

		flag = Math.abs((angle02 - angle01) * 180 / Math.PI) > 1.0;
		count++;
		if (count > 10) break;
	}

	固定杆.x = 关节.x;
	固定杆.y = 关节.y;
	固定杆.rotation = Math.atan2(固定端点.y - 关节.y, 固定端点.x - 关节.x) * 180 / Math.PI;

	活动杆.x = 关节.x;
	活动杆.y = 关节.y;
	活动杆.rotation = Math.atan2(移动末端.y - 关节.y, 移动末端.x - 关节.x) * 180 / Math.PI;

	//trace("循环了" + count + "次");
	
	//关节位于元件的(0,0)点
	var offsetX = 关节.x;
	var offsetY = 关节.y;
	var numchildren=divider.getNumChildren();
	for (var i = 0; i < numchildren; i++) {
		var dis = divider.getChildAt(i);
		dis.x -= offsetX;
		dis.y -= offsetY;
	}
	divider.x += offsetX;
	divider.y += offsetY;
}

function move2target(targetX, targetY) {
	var angle01 = Math.atan2(targetY - 关节.y, targetX - 关节.x);
	//var 活动杆rotation:Number = angle01 * 180 / Math.PI;

	移动端点.x = 关节.x + 可活动长度 * Math.cos(angle01);
	移动端点.y = 关节.y + 可活动长度 * Math.sin(angle01);
	var tx = targetX - 移动端点.x;
	var ty = targetY - 移动端点.y;
	关节.x += tx;
	关节.y += ty;

	var targetX2 = 关节.x;
	var targetY2 = 关节.y;
	var angle02 = Math.atan2(targetY2 - 固定端点.y, targetX2 - 固定端点.x);
	//var 固定杆rotation:Number = angle02 * 180 / Math.PI;

	关节.x = 固定端点.x + 固定杆长度 * Math.cos(angle02);
	关节.y = 固定端点.y + 固定杆长度 * Math.sin(angle02);

	移动末端.x = 关节.x + 活动杆长度 * Math.cos(angle01);
	移动末端.y = 关节.y + 活动杆长度 * Math.sin(angle01);
}

/**
* 計算线段ab和线段cd是否相交
* 复制于:http://www.cnblogs.com/i-gps/archive/2012/06/19/2554992.html
* @param  {[type]} a [description]
* @param  {[type]} b [description]
* @param  {[type]} c [description]
* @param  {[type]} d [description]
* @return {[type]}   [description]
*/
function segmentsIntr(a, b, c, d){  
  
	/** 1 解线性方程组, 求线段交点. **/  
	// 如果分母为0 则平行或共线, 不相交  
    var denominator = (b.y - a.y)*(d.x - c.x) - (a.x - b.x)*(c.y - d.y);  
    if (denominator==0) {  
        return false;  
	}  
   
	// 线段所在直线的交点坐标 (x , y)      
    var x = ( (b.x - a.x) * (d.x - c.x) * (c.y - a.y)   
                + (b.y - a.y) * (d.x - c.x) * a.x   
                - (d.y - c.y) * (b.x - a.x) * c.x ) / denominator ;  
    var y = -( (b.y - a.y) * (d.y - c.y) * (c.x - a.x)   
                + (b.x - a.x) * (d.y - c.y) * a.y   
                - (d.x - c.x) * (b.y - a.y) * c.y ) / denominator;  
  
	/** 2 判断交点是否在两条线段上 **/  
    if (  
        // 交点在线段1上  
        (x - a.x) * (x - b.x) <= 0 && (y - a.y) * (y - b.y) <= 0  
        // 且交点也在线段2上  
         && (x - c.x) * (x - d.x) <= 0 && (y - c.y) * (y - d.y) <= 0  
        ){  
    	//相交
    	//console.log("相交");
  		return true; 
        // 返回交点p 
        return {  
                x :  x,  
                y :  y  
            }  
    }  
    //否则不相交 
    //console.log("不相交");
    return false  
  
}


遇到问题:

  1. createjs中没有“mousemove”事件,但是有“pressmove”事件,用起来更方便,目前还没发现bug;

  2. flash cc中变量用中文名,格式化之后会出错,var和中文变量名会连在一起;

  3. createjs中碰撞检测只有一个hitTest(x,y),还是用的本地坐标,碰撞检测还是自己写算了;

  4. 虽然加了碰撞检测,但是拖动太快的话,会直接穿过去,所以加了一个线段相交的检测;

  5. 注册点的问题,元件是直接从flash as版本中复制过来的,发布之后发现,元件的注册点不是舞台上元件的坐标原点,而是元件的变形中心点,修改变形中心点,和左边远点重合之后恢复正常。

flash cc(最新版的animate cc)还是很好用的,直接用createjs库的话,有很大一部分时间实在创建元件,写布局。用flash cc就可以专注于逻辑的实现了。

可以看看flash cc导出的js文件,有好多实现思路是可以借鉴的,还有好多方法和属性是没有在api中公开的,都可以参考。


如果能针对单个项目自定义修改html模板就好了,因为有时候我们需要写一些css样式(比如背景色,margin属性等),加一些二外的js库(比如屏幕自适应);如果能实现像as一样,有文档类、链接类就更方便了,写在帧上不太适合做大一点的项目。



源码打包下载

« 上一篇下一篇 »

相关文章:

显示fps  (2020-1-19 9:16:17)

js保留有效数字  (2019-7-30 15:32:12)

js的parseInt方法  (2019-2-15 9:12:44)

闪电效果  (2017-11-28 15:4:19)

HTML5本地存储——IndexedDB  (2017-5-17 19:59:58)

js中判断一个对象的类型  (2017-3-30 14:27:35)

解九连环  (2016-12-1 20:58:11)

DataURL与File,Blob,canvas对象之间的互相转换的Javascript  (2016-11-25 14:58:41)

js生成条形码-barcode  (2016-10-12 15:59:51)

GeoJSON格式  (2016-9-23 13:28:44)

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。