javascript - SVG - 示例 |物理电缆(重力)

标签 javascript svg physics

有人知道类似电缆(或基本上任何绳子或绳索)行为的好例子吗?
我目前正在编写一个半模块化合成器。我正在使用 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);
 

};
编辑

这是另一个摇动电缆的 fiddle (只需拖动顶部的灰色圆圈)
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)");
这是我目前正在处理的屏幕截图。
Roland System 100 in javascript html5 and css3

最佳答案

在过去的几年里,我多次遇到过这个问题。因为我自己一直在寻找一个很好的解决方案。到目前为止我还没有发现任何有形的东西,所以我想出了自己的:

  • 使用物理模拟(d3 力模拟、matter.js 等)
  • 添加重力
  • 电缆由主体组成,彼此链接/约束如下:o-o-o-o-o
  • 使用这些实体的位置绘制一条平滑线。 d3.line().curve(d3.curveBasis)或类似的会为你做到这一点。

  • SVG Cables Example
    Shotty

    关于javascript - SVG - 示例 |物理电缆(重力),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18291603/

    相关文章:

    javascript - Node : Asynchronous map for blocking jobs

    javascript - 如何检测网站是否允许您上传文件?

    如果它匹配数组中的多个单词,Javascript 选择字符串

    javascript - 如何使用 SVG.invent() 创建自定义 svg.js 元素?

    javascript - 使用 JavaScript 选择 SVG 和路径元素

    javascript - 单击 SVG 后如何与另一个 SVG 交互

    javascript - 计算结果向量弹跳圆/球

    c++ - Minecraft 类碰撞

    algorithm - 哪些算法可以让我模拟行星物理?

    javascript - TS2307 : Cannot find module './images/logo.png'