之前完成了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
}
遇到问题:
-
createjs中没有“mousemove”事件,但是有“pressmove”事件,用起来更方便,目前还没发现bug;
-
flash cc中变量用中文名,格式化之后会出错,var和中文变量名会连在一起;
-
createjs中碰撞检测只有一个hitTest(x,y),还是用的本地坐标,碰撞检测还是自己写算了;
-
虽然加了碰撞检测,但是拖动太快的话,会直接穿过去,所以加了一个线段相交的检测;
-
注册点的问题,元件是直接从flash as版本中复制过来的,发布之后发现,元件的注册点不是舞台上元件的坐标原点,而是元件的变形中心点,修改变形中心点,和左边远点重合之后恢复正常。
flash cc(最新版的animate cc)还是很好用的,直接用createjs库的话,有很大一部分时间实在创建元件,写布局。用flash cc就可以专注于逻辑的实现了。
可以看看flash cc导出的js文件,有好多实现思路是可以借鉴的,还有好多方法和属性是没有在api中公开的,都可以参考。
如果能针对单个项目自定义修改html模板就好了,因为有时候我们需要写一些css样式(比如背景色,margin属性等),加一些二外的js库(比如屏幕自适应);如果能实现像as一样,有文档类、链接类就更方便了,写在帧上不太适合做大一点的项目。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。