有人知道类似电缆(或基本上任何绳子或绳索)行为的好例子吗?
我目前正在编写一个半模块化合成器。我正在使用 Raphael.js 作为电缆。但它们似乎太僵硬了。我想添加一些物理,所以当我拖动一端而另一端未连接时,另一端会垂下并以略微弯曲的方式移动。我想我正在寻找的是重力。
现在电缆的行为如下:
jsFiddle
使用此代码:
window.onload = function() {
var r = Raphael("cables", 1420, 795),
discattr = {
fill: "#aaa",
stroke: "#ddd"
};
function curve(x, y, ax, ay, bx, by, zx, zy, color) {
var movrattr = {
fill: color || Raphael.getColor(),
stroke: "none"
};
var path = [
["M", x, y],
["C", ax, ay, bx, by, zx, zy]
],
path2 = [
["M", x, y],
["L", ax, ay],
["M", bx, by],
["L", zx, zy]
],
curve = r.path(path).attr({
stroke: color || Raphael.getColor(),
"stroke-width": 4
}).shadow(),
controls = r.set(
r.path(path2).attr({
stroke: "none"
}),
r.circle(x, y, 7).attr(discattr).emboss(1).light(-100,-100,30,'#aaaaaa','diffuse'),
r.circle(ax, ay, 0).attr({
stroke: "none"
}),
r.circle(bx, by, 0).attr({
stroke: "none"
}),
r.circle(zx, zy, 7).attr(discattr).emboss(1).light(-100,-100,30,'#aaaaaa','diffuse')
),
mover = r.set(
r.circle(zx, zy + 9, 7).attr(movrattr)
);
mover[0].move = function(x, y) {
var X = this.attr("cx") + x,
Y = this.attr("cy") + y;
this.attr({
cx: X,
cy: Y
});
// path[1][5] = X;
// path[1][6] = Y;
// path2[3][2] = X;
// path2[3][3] = Y;
controls[1].update(x, y);
controls[4].update(x, y, true);
};
mover[0].update = function(x, y, dragging) {
if (!dragging) return false;
var X = this.attr("cx") + x,
Y = this.attr("cy") + y;
this.attr({
cx: X,
cy: Y
});
};
controls[1].update = function(x, y) {
var X = this.attr("cx") + x,
Y = this.attr("cy") + y;
this.attr({
cx: X,
cy: Y
});
path[0][3] = X;
path[0][4] = Y;
path2[0][4] = X;
path2[0][5] = Y;
controls[2].update(x, y);
};
controls[2].update = function(x, y) {
var X = this.attr("cx") + x,
Y = this.attr("cy") + y;
this.attr({
cx: X,
cy: Y
});
path[1][5] = X;
path[1][6] = Y;
path2[1][6] = X;
path2[1][7] = Y;
curve.attr({
path: path
});
controls[0].attr({
path: path2
});
};
controls[3].update = function(x, y) {
var X = this.attr("cx") + x,
Y = this.attr("cy") + y;
this.attr({
cx: X,
cy: Y
});
path[1][3] = X;
path[1][4] = Y;
path2[2][7] = X;
path2[2][8] = Y;
curve.attr({
path: path
});
controls[0].attr({
path: path2
});
};
controls[4].update = function(x, y, dragging) {
var X = this.attr("cx") + x,
Y = this.attr("cy") + y;
this.attr({
cx: X,
cy: Y
});
path[1][5] = X;
path[1][6] = Y;
path2[3][8] = X;
path2[3][9] = Y;
controls[3].update(x, y);
console.log(dragging)
if (dragging) return false;
mover[0].update(x, y, 'true');
};
controls.drag(move, up);
mover.drag(drag, up);
}
function move(dx, dy) {
this.update(dx - (this.dx || 0), dy - (this.dy || 0));
this.dx = dx;
this.dy = dy;
}
function drag(dx, dy) {
this.move(dx - (this.dx || 0), dy - (this.dy || 0));
this.dx = dx;
this.dy = dy;
}
function up() {
this.dx = this.dy = 0;
}
var newCable = function(){
curve(20, 20, 40, 270, 100, 270, 120, 20, "hsb(" + Math.random() + ", .75, .75)");
};
$('#newCable').on('click', newCable);
};
编辑
这是另一个摇动电缆的小提琴(只需拖动顶部的灰色圆圈)
jsFiddle
var r = Raphael("holder", window.innerWidth, window.innerHeight)
function findReflected(coord, about) {
var diff = about - coord;
return about + diff;
}
function curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, cx3, cy3, x3, y3, color) { //zx --x1
var cx2b = findReflected(cx2, x2),
cy2b = findReflected(cy2, y2),
path = [
["M", x1, y1],
["C", cx1, cy1, cx2, cy2, x2, y2, "S", cx3, cy3, x3, y3]
],
path2 = [
["M", x1, y1],
["L", cx1, cy1],
["M", cx2, cy2],
["L", cx2b, cy2b],
["M", x3, y3],
['L', cx3, cy3]
],
curve = r.path(path).attr({
stroke: color || Raphael.getColor(),
"stroke-width": 4,
"stroke-linecap": "round"
}),
controls = r.set(
r.path(path2).attr({
stroke: "none"
}),
r.circle(x1, y1, 7).attr({
fill: "#ccc",
stroke: "none"
}),
r.circle(cx1, cy1, 5).attr({
fill: "transparent",
stroke: "none"
}),
r.circle(cx2, cy2, 5).attr({
fill: "transparent",
stroke: "none"
}),
r.circle(x2, y2, 5).attr({
fill: "transparent",
stroke: "none"
}),
r.circle(cx2b, cy2b, 5).attr({
fill: "transparent",
stroke: "none"
}),
r.circle(cx3, cy3, 5).attr({
fill: "transparent",
stroke: "none"
}),
r.circle(x3, y3, 7).attr({
fill: "#ccc",
stroke: "none"
})
);
controls[1].update = function (x, y) {
var X = this.attr("cx") + x,
Y = this.attr("cy") + y;
this.attr({
cx: X,
cy: Y
});
path[0][1] = X;
path[0][2] = Y;
path2[0][1] = X;
path2[0][2] = Y;
controls[2].update(x, y);
};
controls[2].update = function (x, y) {
var X = this.attr("cx") + x,
Y = this.attr("cy") + y;
this.attr({
cx: X,
cy: Y
});
path[1][1] = X;
path[1][2] = Y;
path2[1][1] = X;
path2[1][2] = Y;
curve.attr({
path: path
});
controls[0].attr({
path: path2
});
};
controls[3].update = function (x, y, doReflect) {
var X = this.attr("cx") + x,
Y = this.attr("cy") + y;
this.attr({
cx: X,
cy: Y
});
path[1][3] = X;
path[1][4] = Y;
path2[2][1] = X;
path2[2][2] = Y;
curve.attr({
path: path
});
controls[0].attr({
path: path2
});
if (typeof doReflect === undefined || doReflect == null) controls[5].update(-x, -y, false);
};
controls[4].update = function (x, y) {
var X = this.attr("cx") + x,
Y = this.attr("cy") + y;
this.attr({
cx: X,
cy: Y
});
path[1][5] = X;
path[1][6] = Y;
controls[3].update(x, y, false);
controls[5].update(x, y, false);
};
controls[5].update = function (x, y, doReflect) {
var X = this.attr("cx") + x,
Y = this.attr("cy") + y;
this.attr({
cx: X,
cy: Y
});
path2[3][1] = X;
path2[3][2] = Y;
controls[0].attr({
path: path2
});
if (typeof doReflect === undefined || doReflect == null) controls[3].update(-x, -y, false);
};
controls[6].update = function (x, y) {
var X = this.attr("cx") + x,
Y = this.attr("cy") + y;
this.attr({
cx: X,
cy: Y
});
path[1][8] = X;
path[1][9] = Y;
path2[5][1] = X;
path2[5][2] = Y;
curve.attr({
path: path
});
controls[0].attr({
path: path2
});
};
controls[7].update = function (x, y) {
var X = this.attr("cx") + x,
Y = this.attr("cy") + y;
this.attr({
cx: X,
cy: Y
});
path[1][10] = X;
path[1][11] = Y;
path2[4][1] = X;
path2[4][2] = Y;
controls[1].update(x, y);
controls[4].update(x, y);
controls[6].update(x, y);
};
controls.drag(move, up);
var count = 0;
var shake;
$('circle:eq(6)').on('mousedown', function () {
shake = setInterval(function () {
count++;
if (count <= 4) {
controls[4].update(-1, 0);
controls[1].update(2, 0);
} else if (count <= 12) {
controls[4].update(1, 0);
controls[1].update(-2, 0);
} else if (count <= 16) {
controls[4].update(-1, 0);
controls[1].update(2, 0);
} else {
count = 0;
}
}, 30);
}).on('mouseup', function () {
clearInterval(shake);
});
}
function move(dx, dy) {
this.update(dx - (this.dx || 0), dy - (this.dy || 0));
this.dx = dx;
this.dy = dy;
}
function up() {
this.dx = this.dy = 0;
}
curve(100, 350, 100, 300, 100, 300, 100, 200, 100, 100, 100, 50, "hsb(0.2, 0.7, 0.8)");