You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:02:40