这段脚本算是比较值的研究的。
除了使用图形对象外,还有注意的是整个脚本都使用的自动布局,没有给任何一个容器或控件具体的边界值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 |
/** * @fileoverview 展示怎样使用图形对象自定义绘制 ScriptUI 元素 * @class 展示怎样使用图形对象自定义绘制 ScriptUI 元素 * 描述 * 动态的改变 ScriptUI 组件的颜色,需要使用图形自定义对象 * 创建一个滑动条,用户可以使用滑动条来设置颜色的 RGB 通道 * 然后使用获得的颜色创建新 Pen 和 Brush 类型 * 每个 Pen 和 Brush 对象创建时都有笔刷类型,颜色值和线宽属性 * 颜色参数的数组为三个 RGB 值和表示 Alpha(透明度) 值的第四个数字 * 所有值的范围都在 0~1 * 比如,要设置窗口的颜色为亮灰色 * graphicsObject.backgroundColor = graphicsObject.newBrush(g.PenType.SOLID_COLOR, [0.75,0.75,0.75,1], 1) * 具体查看 worldcter.com -> 下载库中的《ExtendScript参考手册》 * @constructor 构造函数 */ function ColorSelector() {} /** * 该片段的函数部分,创建一个窗口和它的 ScriptUI 组件 * 定义三个面板:介绍面板、显示当前颜色值的面板、控件面板 * 控件面板包含单项选择按钮来选择背景或前景 * 滑动条来选择新的颜色值 * 随着滑动条移动,它们的事件处理函数会应用新颜色到窗口的背景或前景上 * 事件处理函数使用一个辅助函数,changeColor(), * 这个函数是实际执行改变颜色,通过创建 Pen 和 Brush对象和使用他们来设置图形对象的颜色属性 * @return True 如果该片段正常运行,否则返回false * @type 布尔 */ ColorSelector.prototype.run = function() { // 构建窗口和组件 // 注意这里的窗口和下面所有容器都没有定义边界值 // 使用的自动布局 var win = new Window("window", "颜色选择器", undefined, {resizeable: false}); // 容器或窗口默认为竖向排列 // win.orientation = "row"; // 定义容器子元素的对齐,可以被子元素的 alignment 重写 // 可以试试不同参数:top, bottom, center win.alignChildren = "fill"; // 介绍面板:面板内的文字颜色将会改变 var instPnl = win.add("panel", undefined, "介绍"); // 改动甚至删除下面的子元素对齐代码都不会影响布局 // 原因在于定义了 st.characters 属性 // 让一行容纳50个字符 // 猜测是 instPnl 的自动布局对象有一个默认的边距 // 一行 50 个字符超过这个边距了,所以 instPnl 边距会被撑到刚好容纳 50 个字符的长度 // 但是也失去了靠左或者靠右的显示效果,毕竟能容纳 50 个字符已经超过限制了 // 这个案例中测试出默认长度似乎是29,不过我觉得是30,因为是中文字符的关系所以显示会有些不同 // 所以如果 st.characters 属性值设置小于30,或者干脆删除这段代码 // instPnl.alignChildren 的属性值就可以起作用了 // 因为每行的字符长度小于默认的边界,所以有空余空间来显示排列类型的不同 instPnl.alignChildren = "left"; // instPnl.margins = [100,100,100,100]; var st = instPnl.add("statictext", undefined, "", {multiline: true}); st.text = "使用单选按钮来选择前景或者背景。" + "然后调整底部面板中的滑动条,每个滑动条分别代表一种颜色:红、绿和蓝。" + "滑动条的值会显示在“颜色值”面板。\n\n" + "使用图形对象你可以:\n" + "* 改变背景颜色\n" + "* 改变前景颜色\n" + "* 改变独立元素或整个窗口\n\n" + "这个案例改变面板内的颜色。"; st.characters = 50; // 创建显示当前颜色值的面板 // panel 的定向为 cloumn(默认),这样其子元素就可以横向居中显示了 // 然后将子元素的定向设置为 row,这样子元素的内容又可以横向排列了 // 注意理解 orientation 和 alignChildren 属性的作用效果 var colPnl = win.add("panel", undefined, "颜色值"); colPnl.orientation = "cloumn"; // colPnl.alignChildren = "right"; gp1 = colPnl.add("group"); // group 类型通常是用来排版的,没有外观,也不会显示标题 gp1.orientation = "row"; // group 的默认定向为 row,这点和 Window 和 Panel 不同 gp1.add("statictext", undefined, "红:"); var RedText = gp1.add("statictext", undefined, "0.5000"); gp1.add("statictext", undefined, "绿:"); var GreenText = gp1.add("statictext", undefined, "0.5000"); gp1.add("statictext", undefined, "蓝:"); var BlueText = gp1.add("statictext", undefined, "0.5000"); gp1.add("statictext", undefined, "Alpha:"); var AlphaText = gp1.add("statictext", undefined, "1"); // 控制滑动条怎样移动和选择前景/背景的面板 var sliderPnl = win.add("panel", undefined, "颜色控制"); // 第一个字符串元素定义了水平对齐,第二个元素定义了垂直对齐 // 水平对齐值必须为left、right、center或fill // 垂直对齐值必须为top,bottom,center或fill sliderPnl.alignChildren = ["fill", "fill"]; gp3 = sliderPnl.add("group"); gp3.orientation = "row"; // gp3 的子元素为横向排列 gp3.alignment = "center"; // gp3 在父级面板中的对齐方式为中心对齐 // gp3.alignChildren = "column"; var foreBtn = gp3.add("radiobutton", undefined, "前景"); var backBtn = gp3.add("radiobutton", undefined, "背景"); var lockBtn = gp3.add("checkbox", undefined, "滑动条锁"); foreBtn.value = true; // 设置一个默认值,不设置的话就没有默认值,而不是选择某个作为缺省值 sliderRed = sliderPnl.add("slider", undefined, 5, 0, 10); sliderGreen = sliderPnl.add("slider", undefined, 5, 0, 10); sliderBlue = sliderPnl.add("slider", undefined, 5, 0, 10); sliderAlpha = sliderPnl.add("slider", undefined, 10, 0, 10); // 滑动条的事件处理函数捕获改动的值并应用颜色 sliderRed.onChanging = function() { var newVal = 0; if (sliderRed.value != 0) { // 这个条件语句没有太大意义 // 设置 newVal 值时给一个初始值 0,但是实际上直接赋值下面的操作运算就可以 // 可能意思是 0 就是 0,不需要再缩小10倍了,为阅读代码的人强调一下 newVal = sliderRed.value/10; } RedText.text = newVal; if (lockBtn.value) { sliderGreen.value = sliderBlue.value = this.value; GreenText.text = BlueText.text = RedText.text; } // 应用颜色 changeColor(1, newVal, foreBtn.value); }; sliderGreen.onChanging = function() { newVal = 0; if(sliderGreen.value != 0) { newVal = sliderGreen.value / 10; } GreenText.text = newVal; if(lockBtn.value) { sliderRed.value = sliderBlue.value = this.value; BlueText.text = RedText.text = GreenText.text; } changeColor(2, newVal, foreBtn.value); } sliderBlue.onChanging = function() { newVal = 0; if(sliderBlue.value != 0) { newVal = sliderBlue.value / 10; } BlueText.text = newVal; if(lockBtn.value) { sliderGreen.value = sliderRed.value = this.value; RedText.text = GreenText.text = BlueText.text; } changeColor(3, newVal, foreBtn.value); } // 这是我添加的,Alpha 值不参与滑动条锁了 // 但是这个透明度有些问题,下面有个测试代码,一会再说 sliderAlpha.onChanging = function() { newVal = 0; if(sliderAlpha.value != 0) { newVal = sliderAlpha.value / 10; } //newVal = sliderAlpha.value / 10; AlphaText.text = newVal; changeColor(4, newVal, foreBtn.value); }; win.show(); // 应用颜色改变窗口和面板 function changeColor(color, val, foreground) { try { var Red = parseFloat(RedText.text); var Green = parseFloat(GreenText.text); var Blue = parseFloat(BlueText.text); var Alpha = parseFloat(AlphaText.text); switch(color) { case 1: Red = val; break; case 2: Green = val; break; case 3: Blue = val; break; case 4: Alpha = val; break; default: return; } // 颜色:红、绿、蓝、Alpha var colArr = [Red, Green, Blue, Alpha]; // 获取窗口和每个面板相关的 ScriptUIGraphics 对象 var g = win.graphics; var g2 = sliderPnl.graphics; var g3 = colPnl.graphics; var c, c2, c3; if (foreground) { // 操作前景 // 为每个颜色创建一个 Pen 对象 // 指定类型、颜色、线宽 // 注意在参考手册中,没有线宽这个参数 c = g.newPen(g.PenType.SOLID_COLOR, colArr, 1); // 为了显示变化,让 g2 和 g3 直接变为一个定值 c2 = g2.newPen(g2.PenType.SOLID_COLOR, [0,0,0,1], 1); c3 = g3.newPen(g3.PenType.SOLID_COLOR, [0,0,0,1], 1); // 设置新 Pen 对象为图形对象的前景色 g.foregroundColor = c; g2.foregroundColor = c2; g3.foregroundColor = c3; } else { // 操作背景 // 为每个颜色创建一个 Pen 对象 // 指定类型、颜色、线宽 c = g.newBrush(g.BrushType.SOLID_COLOR, colArr, 1); // File.fs 会返回平台名称 if (File.fs == "Windows") { defColor = [0.933, 0.918, 0.848, 1]; } else { defColor = [0.949, 0.949, 0.949, 1]; } c2 = g2.newBrush(g2.BrushType.SOLID_COLOR, defColor, 1); c3 = g3.newBrush(g3.BrushType.SOLID_COLOR, defColor, 1); // 设置新 Brush 对象作为图形对象的背景色 g.backgroundColor = c; g2.backgroundColor = c2; g3.backgroundColor = c3; } } catch (error) {alert(error);} } return true; }; /** * "main program":构造一个匿名实例并运行 */ new ColorSelector().run(); |
接着来说一说更改透明度的问题。
上面的代码在更改透明度的时候,并没有预想中的窗口变成半透明。
一开始是我以为代码有点复杂,有些地方出错了我没发现。然后就写了一个简化版。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
var w = new Window("window", "Hello", undefined); //w.orientation = "column"; w.alignChildren = "fill"; var text = w.add("statictext", undefined, "0.5"); text.characters = 50; //text.alignment = "center"; var slider = w.add("slider", undefined, 5, 0, 10); w.show(); w.center(); slider.onChange = function() { try { var a = this.value/10; //var A = parseFloat(text.text); //var A = a; var colArr = [0.75,0.75,0.75,a]; text.text = a; g = w.graphics; c = g.newBrush(g.BrushType.SOLID_COLOR, colArr, 1); //alert(colArr); g.backgroundColor = c; } catch (e) {alert(e);} }; |
测试发现还是会出现问题,并不是想象中那样窗口呈现半透明状态,虽然不使用事件响应函数直接设置,确实会呈现半透明。
但是现在想要的效果就是使用滑动条来控制窗口透明度啊。
最后发现在调节滑动条的时候,窗口中的文字和滑动条的圆点会出现叠加的现象,看起来就是窗口是变半透明了,但是变化之前的窗口状态并没有消失,所以是新的半透明窗口叠加在了原窗口状态上。
但是在操作前景时,文字确实会由滑动条控制透明度,所以这个应该是一个BUG吧。
(完)