简体   繁体   English

带有 OnDraw 的 ScriptUi 自定义形状按钮

[英]ScriptUi custom shape button with OnDraw

I wrote a script with a dialog with custom round buttons (something like the official adobe ones).我写了一个带有自定义圆形按钮的对话框的脚本(类似于官方的 adobe 按钮)。
Being ignorant of mathematics, I drew the button with straight lines, like this:由于不懂数学,我用直线画了按钮,像这样:

    ButtonPanel ();
    function ButtonPanel () {
        var Panel = new Window ("dialog");
        Panel.text = "Panel";
        var Button = Panel.add ("button");
        Button.text = "Exit";
        Button.preferredSize.width = 170;
        Button.onClick = function () {
                Panel.close ();
            }
        Draw (Button);
        Panel.show ();
        function Draw (Obj) {
            if (Obj.type == "button") {
                Obj.graphics.foregroundColor = Obj.graphics.newPen (Obj.graphics.PenType.SOLID_COLOR, [1, 1, 1], 1);
                Obj.graphics.font = ScriptUI.newFont (Obj.graphics.font.name, "Bold", Obj.graphics.font.size);
                Obj.onDraw = function (Event) {
                    with (Obj) {
                        graphics.drawOSControl ();
                        graphics.newPath ();
                        graphics.moveTo ((size[0] / 340) * 25, (size[1] / 50) * 0);
                        graphics.lineTo ((size[0] / 340) * 17.73, (size[1] / 50) * 1.06);
                        graphics.lineTo ((size[0] / 340) * 11.98, (size[1] / 50) * 3.65);
                        graphics.lineTo ((size[0] / 340) * 7.32, (size[1] / 50) * 7.32);
                        graphics.lineTo ((size[0] / 340) * 3.65, (size[1] / 50) * 11.98);
                        graphics.lineTo ((size[0] / 340) * 1.06, (size[1] / 50) * 17.73);
                        graphics.lineTo ((size[0] / 340) * 0, (size[1] / 50) * 25);
                        graphics.lineTo ((size[0] / 340) * 1.06, (size[1] / 50) * 32.26);
                        graphics.lineTo ((size[0] / 340) * 3.65, (size[1] / 50) * 38.02);
                        graphics.lineTo ((size[0] / 340) * 7.32, (size[1] / 50) * 42.68);
                        graphics.lineTo ((size[0] / 340) * 11.98, (size[1] / 50) * 46.35);
                        graphics.lineTo ((size[0] / 340) * 17.73, (size[1] / 50) * 48.93);
                        graphics.lineTo ((size[0] / 340) * 25, (size[1] / 50) * 50);
                        graphics.lineTo ((size[0] / 340) * 315, (size[1] / 50) * 50);
                        graphics.lineTo ((size[0] / 340) * 322.25, (size[1] / 50) * 48.93);
                        graphics.lineTo ((size[0] / 340) * 328, (size[1] / 50) * 46.35);
                        graphics.lineTo ((size[0] / 340) * 332.66, (size[1] / 50) * 42.68);
                        graphics.lineTo ((size[0] / 340) * 336.34, (size[1] / 50) * 38.02);
                        graphics.lineTo ((size[0] / 340) * 338.92, (size[1] / 50) * 32.26);
                        graphics.lineTo ((size[0] / 340) * 340, (size[1] / 50) * 25);
                        graphics.lineTo ((size[0] / 340) * 338.92, (size[1] / 50) * 17.73);
                        graphics.lineTo ((size[0] / 340) * 336.34, (size[1] / 50) * 11.98);
                        graphics.lineTo ((size[0] / 340) * 332.66, (size[1] / 50) * 7.32);
                        graphics.lineTo ((size[0] / 340) * 328, (size[1] / 50) * 3.65);
                        graphics.lineTo ((size[0] / 340) * 322.25, (size[1] / 50) * 1.06);
                        graphics.lineTo ((size[0] / 340) * 315, (size[1] / 50) * 0);
                        graphics.lineTo ((size[0] / 340) * 25, (size[1] / 50) * 0);
                        graphics.closePath ();
                        graphics.fillPath (graphics.newBrush (graphics.BrushType.SOLID_COLOR, [1, 0, 0]));
                        graphics.closePath ();
                        if (text) {
                            graphics.drawString (text, (graphics.newPen (graphics.PenType.SOLID_COLOR, [1, 1, 1], 1)), (size[0] - graphics.measureString (text, graphics.font, size[0])[0]) / 2, (size[1] - graphics.measureString (text, graphics.font, size[1])[1]) / 2, graphics.font);
                            }
                        if (Event.mouseOver) {
                            graphics.fillPath (graphics.newBrush (graphics.BrushType.SOLID_COLOR, [1, 1, 1]));
                            if (text) {
                                graphics.drawString (text, (graphics.newPen (graphics.PenType.SOLID_COLOR, [1, 0, 0], 1)), (size[0] - graphics.measureString (text, graphics.font, size[0])[0]) / 2, (size[1] - graphics.measureString (text, graphics.font, size[1])[1]) / 2, graphics.font);
                                }
                            }
                        }
                    }
                }
            }
        }

However I have seen on this site that it is possible to draw the various shapes with a geometric formulas.但是我在 这个网站上看到可以用几何公式绘制各种形状。
Does anyone know how the half circles on the sides of the button could be drawn with "geometric calculations"?有谁知道如何用“几何计算”绘制按钮两侧的半圆?

Oof.钱币。 You know that loops are a thing right?你知道循环是正确的吗?

The site you link to is just using straight lines but is generating each segment using the formula for the various curves.您链接到的站点仅使用直线,但使用各种曲线的公式生成每个段。 The formula for a point on the circumference of a circle given the angle θ from the x axis to the point, and the radius r is [ cos(θ), sin(θ) ] * r .给定从 x 轴到该点的角度θ和半径r的圆周上一点的公式为[ cos(θ), sin(θ) ] * r You can decide how many segments you want in the half circle and make a loop to call that formula that many times.您可以决定在半圆中需要多少段,然后循环多次调用该公式。

    function halfCircle(
        radius, //radius of the half circle
        segStart, //coordinates of the start of the segment
        angleStart, // angle of the start of the segment from the positive x axis
        radius, //radius of the half circle
        numSegments //how many segments to draw
    )

    var circle = {
        x: function(i, r){ return Math.cos(i) * r},
        y: function(i, r){ return Math.cos(i) * r}
    }

    var g = this.graphics;
    g.newPath();
    g.moveTo(segStart);

    var increment = Math.pi / numSegments; //Pi in radians is 180°
    var offset = angleStart * Math.pi / 180;
    for (var i = 0; i < numSegments; i++){
        g.lineTo(
            circle.x(i * increment + offset, radius) + segStart, 
            circle.y(i * increment + offset, radius) + segStart
        );
    }

    halfCircle(340, 16, [123,456], 180);

If you look at the values of size[0] which is 170 and size[1], which is 25 you can rewrite the semi circle code with the exact values:如果您查看 size[0] 的值为 170 和 size[1] 的值为 25,您可以使用精确值重写半圆代码:

graphics.lineTo ((size[0] / 340) * 17.73, (size[1] / 50) * 1.06);
graphics.lineTo ((size[0] / 340) * 11.98, (size[1] / 50) * 3.65);
graphics.lineTo ((size[0] / 340) * 7.32, (size[1] / 50) * 7.32);
graphics.lineTo ((size[0] / 340) * 3.65, (size[1] / 50) * 11.98);
graphics.lineTo ((size[0] / 340) * 1.06, (size[1] / 50) * 17.73);
graphics.lineTo ((size[0] / 340) * 0, (size[1] / 50) * 25);
graphics.lineTo ((size[0] / 340) * 1.06, (size[1] / 50) * 32.26);
graphics.lineTo ((size[0] / 340) * 3.65, (size[1] / 50) * 38.02);
graphics.lineTo ((size[0] / 340) * 7.32, (size[1] / 50) * 42.68);
graphics.lineTo ((size[0] / 340) * 11.98, (size[1] / 50) * 46.35);
graphics.lineTo ((size[0] / 340) * 17.73, (size[1] / 50) * 48.93);

or simply或者简单地

graphics.lineTo (8.865, 0.53);
graphics.lineTo (5.99, 1.825);
graphics.lineTo (3.66, 3.66);
graphics.lineTo (1.825, 5.99);
graphics.lineTo (0.53, 8.865);
graphics.lineTo (0, 12.5);
graphics.lineTo (0.53, 8.865);
graphics.lineTo (1.825, 5.99);
graphics.lineTo (3.66, 3.66);
graphics.lineTo (5.99, 1.825);
graphics.lineTo (8.865, 0.53);

So it's now simply a matter of substituting the x an y values with [ cos(θ), sin(θ) ] * r as stib has shown you in his much better (and quicker) answer.因此,现在只需将 x 和 y 值替换为[ cos(θ), sin(θ) ] * r ,因为 stib 在他更好(更快)的答案中向您展示了这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM