【问题标题】:ScriptUi custom shape button with OnDraw带有 OnDraw 的 ScriptUi 自定义形状按钮
【发布时间】:2023-01-31 11:30:00
【问题描述】:

我写了一个带有自定义圆形按钮的对话框的脚本(类似于官方的 adobe 按钮)。
由于不懂数学,我用直线画了按钮,像这样:

    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);
                                }
                            }
                        }
                    }
                }
            }
        }

但是我在this site 上看到可以用几何公式绘制各种形状。
有谁知道如何用“几何计算”绘制按钮两侧的半圆?


更新

在弄乱了 stib 的代码和链接站点的代码之后,我想出了这个最终脚本:

    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 (12.5, 0);
                        for (var i = 0; i < Math.PI; i += Math.PI / 100) {
                            graphics.lineTo ((-12.5 * Math.sin (i)) + 12.5, (-12.5 * Math.cos (i)) + 12.5);
                            }
                            graphics.lineTo (157.5, 25);
                        for (var i = 0; i < Math.PI; i += Math.PI / 100) {
                            graphics.lineTo ((12.5 * Math.sin (i)) + 157.5, (12.5 * Math.cos (i)) + 12.5);
                            }
                        graphics.lineTo (12.5, 0);
                        graphics.closePath ();
                        graphics.fillPath (graphics.newBrush (graphics.BrushType.SOLID_COLOR, [1, 0, 0]));
                        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);
                                }
                            }
                        }
                    }
                }
            }
        }

【问题讨论】:

    标签: javascript photoshop adobe-indesign extendscript adobe-scriptui


    【解决方案1】:

    钱币。你知道循环是正确的吗?

    您链接到的站点仅使用直线,但使用各种曲线的公式生成每个段。给定从 x 轴到该点的角度 θ 和半径 r 是圆周上的点的公式为 [ cos(θ), sin(θ) ] * r。您可以决定在半圆中需要多少段,然后循环多次调用该公式。

        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
            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, [123,456], 123, 45);
    

    【讨论】:

    • 是的,我知道循环,但如果我不知道如何处理它们,它们可能对我来说毫无用处,这就是为什么我以粗略的方式手工绘制它们。
    • 我猜到了该站点的脚本是如何工作的,但我不知道数学公式以及如何应用它们。在弄乱了你的脚本和网站的脚本之后,我设法完成了一些事情。您的脚本中还有一些我不明白的地方。为什么括号后面没有花括号,为什么有两个半径?
    • 他们是错别字。已修复
    【解决方案2】:

    如果您查看 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);
    

    或者简单地

    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);
    

    因此,现在只需用 [ cos(θ), sin(θ) ] * r 替换 x 和 y 值即可,正如 stib 在他更好(更快)的答案中向您展示的那样。

    【讨论】:

    • 是的,我已经知道我可以输入正确的值(乱七八糟的脚本是我为了得到类似于曲线的东西而手工完成的计算),但很可能这些值是近似值,结果绘制得不太好。所以我一直在寻找一种自动放置它们的方法。
    最近更新 更多