马黑黑 发表于 2023-6-17 12:21

用clip-path:polygon()内切正多边形

<style>

#mydiv {
        width: 200px;
        height: 200px;
        background: rebeccapurple;
        border-radius: 50%;
}

.papa > div, .papa > p { margin: 20px 0; }

.papa label, .papa input { margin: 0 8px; }

</style>

<div class="papa">
        <p>
                <input id="btnReset" type="button" value="重置" />
                <label for="numLen">宽高:</label>
                <input id="numLen" type="number" value="200" min="100" max="1000" />
                <label for="numPoint">边数:</label>
                <input id="numPoint" type="number" value="3" min="3" max="360" />
                <label for="numThick">边厚:</label>
                <input id="numThick" type="number" value="10" min="5" max="40" />
                <input id="btnOk" type="button" value="裁剪" />
        </p>
        <div id="mydiv"></div>
        <div id="msgBox"></div>
</div>

<script>

let clipBox = (xx,points,thick) => {
        if(points < 3) points = 3;
        let x0 = y0 = r = xx / 2, pointsAr = [`200px 0, 0 0, 0 ${xx}px, ${xx}px ${xx}px, ${xx}px ${xx/2}px`];
        for(let i = 0; i <= points; i ++) {
                let hudu = Math.PI / 180 * 360 / points * i;
                let x1 = x0 + Math.cos(hudu) * (r - thick), y1 = y0 + Math.sin(hudu) * (r - thick);
                pointsAr.push(x1 + 'px ' + y1 + 'px');
        }
        pointsAr.push(`${xx}px ${xx/2}px`);
        pointsAr.push(`${xx}px 0px`);
        return `polygon(${pointsAr.join(',')})`;
}

let limit = (box,min,max) => {
        if(box.value < min) box.value = min;
        if(box.value > max) box.value = max;
}

numPoint.onchange = () => limit(numPoint,3,360);

numLen.onchange = () => limit(numLen,40,600);

numThick.onchange = () => limit(numThick,5,40);

btnOk.onclick = () => {
        mydiv.style.width = numLen.value + 'px';
        mydiv.style.height = numLen.value + 'px';
        mydiv.style.clipPath = clipBox(numLen.value, numPoint.value, numThick.value);
        msgBox.innerText = 'clip-path: ' + mydiv.style.clipPath + ';';
}

btnReset.onclick = () => {
        mydiv.style.clipPath = '';
        mydiv.style.width = '200px';
        mydiv.style.height = '200px';
        numLen.value = '200';
        numPoint.value = '3';
        numThick.value = '10';
        msgBox.innerText = '';
}

</script>

马黑黑 发表于 2023-6-17 12:22

代码
<style>

#mydiv {
        width: 200px;
        height: 200px;
        background: rebeccapurple;
        border-radius: 50%;
}

.papa > div, .papa > p { margin: 20px 0; }

.papa label, .papa input { margin: 0 8px; }

</style>

<div class="papa">
        <p>
                <input id="btnReset" type="button" value="重置" />
                <label for="numLen">宽高:</label>
                <input id="numLen" type="number" value="200" min="100" max="1000" />
                <label for="numPoint">边数:</label>
                <input id="numPoint" type="number" value="3" min="3" max="360" />
                <label for="numThick">边厚:</label>
                <input id="numThick" type="number" value="10" min="5" max="40" />
                <input id="btnOk" type="button" value="裁剪" />
        </p>
        <div id="mydiv"></div>
        <div id="msgBox"></div>
</div>

<script>

let clipBox = (xx,points,thick) => {
        if(points < 3) points = 3;
        let x0 = y0 = r = xx / 2, pointsAr = [`200px 0, 0 0, 0 ${xx}px, ${xx}px ${xx}px, ${xx}px ${xx/2}px`];
        for(let i = 0; i <= points; i ++) {
                let hudu = Math.PI / 180 * 360 / points * i;
                let x1 = x0 + Math.cos(hudu) * (r - thick), y1 = y0 + Math.sin(hudu) * (r - thick);
                pointsAr.push(x1 + 'px ' + y1 + 'px');
        }
        pointsAr.push(`${xx}px ${xx/2}px`);
        pointsAr.push(`${xx}px 0px`);
        return `polygon(${pointsAr.join(',')})`;
}

let limit = (box,min,max) => {
        if(box.value < min) box.value = min;
        if(box.value > max) box.value = max;
}

numPoint.onchange = () => limit(numPoint,3,360);

numLen.onchange = () => limit(numLen,40,600);

numThick.onchange = () => limit(numThick,5,40);

btnOk.onclick = () => {
        mydiv.style.width = numLen.value + 'px';
        mydiv.style.height = numLen.value + 'px';
        mydiv.style.clipPath = clipBox(numLen.value, numPoint.value, numThick.value);
        msgBox.innerText = 'clip-path: ' + mydiv.style.clipPath + ';';
}

btnReset.onclick = () => {
        mydiv.style.clipPath = '';
        mydiv.style.width = '200px';
        mydiv.style.height = '200px';
        numLen.value = '200';
        numPoint.value = '3';
        numThick.value = '10';
        msgBox.innerText = '';
}

</script>

马黑黑 发表于 2023-6-17 12:25

本帖最后由 马黑黑 于 2023-6-17 12:26 编辑

核心思路:

先从外围起剪,到 {100%, 50%} 处往里水平切厚度单位的距离,然后里面的切法交给 for 语句完成,回到往里切厚度单位的那个点后,沿原路返回 {100%, 50%} 处,再裁剪外围尚未裁剪的部分并回到起点。

马黑黑 发表于 2023-6-17 12:32

需要突破本例的一些限定的,请在本地测试时修改如下JS语句:

numPoint.onchange = () => limit(numPoint,3,360); /* 边数限制 */

numLen.onchange = () => limit(numLen,40,600); /* 正方形尺寸 */

numThick.onchange = () => limit(numThick,5,40); /* 预留厚度 */

马黑黑 发表于 2023-6-17 12:33

脚本边数可以使用浮点数,可以试试

红影 发表于 2023-6-17 15:54

这个厉害了,可以任意得到规定范围里的边数和边厚的镂空多边形,还是返回路径。太赞了{:4_199:}

红影 发表于 2023-6-17 15:56

这个用对应角度来找到一个个多边形的点,这思路绝对太棒了{:4_199:}

红影 发表于 2023-6-17 15:57

又开发了一个特别好的在线工具,黑黑厉害{:4_199:}

红影 发表于 2023-6-17 16:03

又去看了看前面裁剪多边形的帖子,昨天回来喝多了酒,都没仔细去理解{:4_173:}

梦缘 发表于 2023-6-17 16:54

问好老师,欣赏精彩佳作,谢谢分享!{:4_191:}

马黑黑 发表于 2023-6-17 16:55

梦缘 发表于 2023-6-17 16:54
问好老师,欣赏精彩佳作,谢谢分享!

{:4_190:}

马黑黑 发表于 2023-6-17 16:57

红影 发表于 2023-6-17 15:54
这个厉害了,可以任意得到规定范围里的边数和边厚的镂空多边形,还是返回路径。太赞了

内镂空前几天做过的。我的这个方法比张鑫旭等大佬们的方法要好得多,不过我没有和他们做过交流。

马黑黑 发表于 2023-6-17 17:00

红影 发表于 2023-6-17 15:56
这个用对应角度来找到一个个多边形的点,这思路绝对太棒了

因为不想额外处理 for 语句,就是不想重新排序角度,都从 0 夹角开始,所以,所有的最大化多边形的切割起点,都从三点钟方向开始。

马黑黑 发表于 2023-6-17 17:01

红影 发表于 2023-6-17 16:03
又去看了看前面裁剪多边形的帖子,昨天回来喝多了酒,都没仔细去理解

这个理解起来并不难。程序代码中,重点要消化的是polygon路径的设计与计算。

马黑黑 发表于 2023-6-17 17:02

红影 发表于 2023-6-17 15:57
又开发了一个特别好的在线工具,黑黑厉害

这个,严格意义上讲,还不能算式工具把,就是玩玩,或许有用,弄个切割路径还行的

南无月 发表于 2023-6-17 17:27

全自动的切割机。。。好用。。。{:4_187:}

马黑黑 发表于 2023-6-17 17:28

南无月 发表于 2023-6-17 17:27
全自动的切割机。。。好用。。。

剪刀好切啥都顺

南无月 发表于 2023-6-17 17:42

马黑黑 发表于 2023-6-17 17:28
剪刀好切啥都顺

花黑牌的是名牌儿。。{:4_170:}杠杠的

马黑黑 发表于 2023-6-17 18:11

南无月 发表于 2023-6-17 17:42
花黑牌的是名牌儿。。杠杠的

注资六毛

红影 发表于 2023-6-17 19:48

马黑黑 发表于 2023-6-17 16:57
内镂空前几天做过的。我的这个方法比张鑫旭等大佬们的方法要好得多,不过我没有和他们做过交流。

这个能弄出任意边数的镂空呢{:4_199:}
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: 用clip-path:polygon()内切正多边形