如何用Adobe Illustrator结合JavaScript生成类迷彩半随机六边形图案
解决Illustrator中六边形迷彩图案连通区域过小的问题
你的问题核心在于纯随机选色没有考虑相邻六边形的颜色关联性——每个六边形独立随机挑色,自然很难形成大面积的连通色块。下面给你两种改进思路,从简单到进阶,都能在Illustrator JS脚本里实现:
思路1:加权随机选色(优先和邻域同色)
这个方法是给当前六边形的相邻色块颜色更高的选中概率,让同色更容易扩散:
mySelection = app.activeDocument.selection; myDoc = app.activeDocument; // 第一步:检测相邻六边形(需根据你的网格布局调整) function getHexNeighbors(hex) { let neighbors = []; mySelection.forEach(otherHex => { if (otherHex !== hex && isAdjacent(hex, otherHex)) { neighbors.push(otherHex); } }); return neighbors; } // 判断两个六边形是否相邻(替换为你的实际间距阈值) function isAdjacent(hexA, hexB) { const centerA = hexA.position; const centerB = hexB.position; const distance = Math.sqrt(Math.pow(centerA[0]-centerB[0],2) + Math.pow(centerA[1]-centerB[1],2)); return distance < 100; // 示例阈值,需根据你的六边形尺寸调整 } // 第二步:加权随机选色逻辑 const swatchColors = myDoc.swatches.filter(s => s.colorType !== ColorType.NONE).slice(0, 3); // 取前3个迷彩色 mySelection.forEach(hex => { const neighbors = getHexNeighbors(hex); const neighborColors = neighbors.map(n => n.fillColor); // 统计邻域内各颜色的出现次数 const colorCount = {}; neighborColors.forEach(color => { const colorId = color.toHexString(); colorCount[colorId] = (colorCount[colorId] || 0) + 1; }); // 构建加权选色池:邻域颜色权重更高 let weightedPool = []; Object.keys(colorCount).forEach(colorId => { const color = swatchColors.find(s => s.color.toHexString() === colorId); if (color) { // 给邻域已存在的颜色3倍权重,可按需调整 for(let i=0; i<colorCount[colorId]*3; i++) { weightedPool.push(color); } } }); // 加入基础色池,保证偶尔出现新色块 weightedPool = weightedPool.concat(swatchColors); // 随机选色并应用 const randomIndex = Math.floor(Math.random() * weightedPool.length); hex.fillColor = weightedPool[randomIndex].color; });
关键调整点:
isAdjacent里的距离阈值需要你实际测量相邻六边形的中心间距来替换,确保能准确识别邻居。- 权重倍数(示例里的
*3):数值越大,同色块连通性越强;数值越小,越接近原始的纯随机效果。
思路2:细胞自动机扩散(进阶,模拟自然迷彩)
如果想要更接近真实迷彩的不规则大色块,可以用种子扩散的逻辑:先随机生成几个"种子"色块,再让颜色向邻域逐步扩散:
mySelection = app.activeDocument.selection; myDoc = app.activeDocument; const swatchColors = myDoc.swatches.filter(s => s.colorType !== ColorType.NONE).slice(0, 3); const seedCount = 5; // 初始种子数量,越多色块越细碎 const iterations = 3; // 扩散次数,越多色块覆盖范围越大 // 第一步:随机生成种子并上色 const seeds = []; for(let i=0; i<seedCount; i++) { const randomHex = mySelection[Math.floor(Math.random() * mySelection.length)]; randomHex.fillColor = swatchColors[i % swatchColors.length].color; seeds.push(randomHex); } // 第二步:迭代扩散颜色 for(let iter=0; iter<iterations; iter++) { const updatedHexes = []; mySelection.forEach(hex => { if (!updatedHexes.includes(hex) && !seeds.includes(hex)) { const neighbors = getHexNeighbors(hex); const neighborColors = neighbors.map(n => n.fillColor).filter(c => c); // 统计邻域中出现次数最多的颜色 const colorCount = {}; neighborColors.forEach(color => { const colorId = color.toHexString(); colorCount[colorId] = (colorCount[colorId] || 0) + 1; }); if (Object.keys(colorCount).length > 0) { const mostCommonColorId = Object.keys(colorCount).reduce((a, b) => colorCount[a] > colorCount[b] ? a : b); const mostCommonColor = swatchColors.find(s => s.color.toHexString() === mostCommonColorId); if (mostCommonColor) { hex.fillColor = mostCommonColor.color; updatedHexes.push(hex); } } } }); } // 复用邻域检测函数(和思路1一致) function getHexNeighbors(hex) { let neighbors = []; mySelection.forEach(otherHex => { if (otherHex !== hex && isAdjacent(hex, otherHex)) { neighbors.push(otherHex); } }); return neighbors; } function isAdjacent(hexA, hexB) { const centerA = hexA.position; const centerB = hexB.position; const distance = Math.sqrt(Math.pow(centerA[0]-centerB[0],2) + Math.pow(centerA[1]-centerB[1],2)); return distance < 100; // 替换为你的实际阈值 }
关键调整点:
seedCount和iterations是核心参数:种子越少、扩散次数越多,生成的色块越大越连贯;反之则色块更细碎。- 可以先给所有六边形填充一个基础底色,再运行脚本,效果会更自然。
额外提示:
- 确保你的六边形是无重叠、规则排列的,否则邻域检测会出错。
- 如果你的六边形是通过网格工具生成的,可以直接利用Illustrator的图层/编组信息来快速定位邻居,不用依赖坐标计算。
内容的提问来源于stack exchange,提问作者Johannes
相关产品推荐
相关产品推荐

