马黑黑 发表于 2023-6-23 07:02

用 clip-path: polygon() 绘制桃心形

<style>
#mydiv {
        width: 300px;
        height: 300px;
        background: purple;
        transform: rotate(-180deg);
}
#msgBox { display: none; }
</style>

<div id="mydiv"></div>
<p>
        <label for="angle">边缘系数 : </label>
        <input id="angle" type="range" value="50" />
        <span id="points">50</span>
        <input id="loukong" type="checkbox" />
        <label for="loukong">镂空</label>
        <br><br>
        <button id="showCode" value="1">查看代码</button>
        <br><br>
</p>
<div id="msgBox"></div>

<script>

let toPercent = (num1,num2) => (num2 / num1 * 100).toFixed(2) + '%'; /* 转百分比 */

let mkHeart = (ww = 200, angle = 50, hollow = false) => {
        let a = ww / 2, arr = hollow ? [`0% 0%, 100% 0%, 100% 100%, 50% 100%`] : [];
        for(let i = 0; i <= 2 * Math.PI; i += Math.PI/angle) {
                let x = a/17 * 16 * Math.pow(Math.sin(i), 3) + a;
                let y = a/17 * (13 * Math.cos(i) - 5 * Math.cos(2 * i) - 2 * Math.cos(3 * i) - Math.cos(4 * i)) + a + 13;
                arr.push(toPercent(a * 2, x) + ' ' + toPercent(a * 2, y));
        }
        if(hollow) arr.push(`50% 100%, 0% 100%`);
        return `polygon(${arr.join(', ')})`;
}

msgBox.innerText = mydiv.style.clipPath = mkHeart();

showCode.onclick = () => showCode.innerText === '查看代码' ? (msgBox.style.display = 'block', showCode.innerText = '收起代码') : (msgBox.style.display = 'none', showCode.innerText = '查看代码');

loukong.onclick = angle.onchange = () => {
        msgBox.innerText = mydiv.style.clipPath = mkHeart(200,angle.value,loukong.checked);
        points.innerText = angle.value;
}

</script>

马黑黑 发表于 2023-6-23 07:10

核心JS代码:

let toPercent = (num1,num2) => (num2 / num1 * 100).toFixed(2) + '%'; /* 转百分比 */

let mkHeart = (ww = 200, angle = 50, hollow = false) => {
/*        桃心形坐标方程式:
        x = 16 * sint ^ 3
        y = 13 * cost - 5 * cos2t - cos4t
*/
        let a = ww / 2, arr = hollow ? [`0% 0%, 100% 0%, 100% 100%, 50% 100%`] : [];
        for(let i = 0; i <= 2 * Math.PI; i += Math.PI/angle) {
                let x = a/17 * 16 * Math.pow(Math.sin(i), 3) + a;
                let y = a/17 * (13 * Math.cos(i) - 5 * Math.cos(2 * i) - 2 * Math.cos(3 * i) - Math.cos(4 * i)) + a + 13;
                arr.push(toPercent(a * 2, x) + ' ' + toPercent(a * 2, y));
        }
        if(hollow) arr.push(`50% 100%, 0% 100%`);
        return `polygon(${arr.join(', ')})`;
}函数 mkHeart(参数1, 参数2, 参数3) 的各参数都有预定值:参数1 ww 为200,是待剪裁正方形的宽高尺寸,参数2 angle 是边缘系数,默认50,值越大边缘越平滑;参数3 hollow 是镂空与否,默认为不镂空。该函数调用方法:

方法一:mkHeart();
方法二:mkHeart(300, 90, true); // true 镂空,false 不镂空

马黑黑 发表于 2023-6-23 07:15

因为使用了百分比,所生成的 clip-path 代码适用于任意尺寸的正方形元素:

<style>
.mybox {
    width: 400px;
    height: 400px;
    background: red;
    clip-path: polygon(50.00% 71.21%, 50.01% 71.44%, 50.09% 72.14%, 50.31% 73.27%, 50.72% 74.78%, 51.39% 76.60%, 52.35% 78.64%, 53.63% 80.81%, 55.26% 83.01%, 57.24% 85.13%, 59.56% 87.09%, 62.19% 88.77%, 65.10% 90.12%, 68.23% 91.05%, 71.53% 91.52%, 74.92% 91.49%, 78.33% 90.96%, 81.67% 89.92%, 84.86% 88.40%, 87.82% 86.43%, 90.48% 84.06%, 92.76% 81.35%, 94.60% 78.35%, 95.95% 75.12%, 96.78% 71.74%, 97.06% 68.26%, 96.78% 64.74%, 95.95% 61.21%, 94.60% 57.71%, 92.76% 54.28%, 90.48% 50.91%, 87.82% 47.64%, 84.86% 44.45%, 81.67% 41.34%, 78.33% 38.31%, 74.92% 35.36%, 71.53% 32.46%, 68.23% 29.64%, 65.10% 26.87%, 62.19% 24.18%, 59.56% 21.58%, 57.24% 19.09%, 55.26% 16.74%, 53.63% 14.54%, 52.35% 12.55%, 51.39% 10.79%, 50.72% 9.29%, 50.31% 8.09%, 50.09% 7.21%, 50.01% 6.68%, 50.00% 6.50%, 49.99% 6.68%, 49.91% 7.21%, 49.69% 8.09%, 49.28% 9.29%, 48.61% 10.79%, 47.65% 12.55%, 46.37% 14.54%, 44.74% 16.74%, 42.76% 19.09%, 40.44% 21.58%, 37.81% 24.18%, 34.90% 26.87%, 31.77% 29.64%, 28.47% 32.46%, 25.08% 35.36%, 21.67% 38.31%, 18.33% 41.34%, 15.14% 44.45%, 12.18% 47.64%, 9.52% 50.91%, 7.24% 54.28%, 5.40% 57.71%, 4.05% 61.21%, 3.22% 64.74%, 2.94% 68.26%, 3.22% 71.74%, 4.05% 75.12%, 5.40% 78.35%, 7.24% 81.35%, 9.52% 84.06%, 12.18% 86.43%, 15.14% 88.40%, 18.33% 89.92%, 21.67% 90.96%, 25.08% 91.49%, 28.47% 91.52%, 31.77% 91.05%, 34.90% 90.12%, 37.81% 88.77%, 40.44% 87.09%, 42.76% 85.13%, 44.74% 83.01%, 46.37% 80.81%, 47.65% 78.64%, 48.61% 76.60%, 49.28% 74.78%, 49.69% 73.27%, 49.91% 72.14%, 49.99% 71.44%, 50.00% 71.21%);
}
</style>

<div class="mybox"></div>

马黑黑 发表于 2023-6-23 07:29

板凳楼,代码产生的效果是一个尖尖朝上的桃心形,可以在 CSS 代码中加入 transform: rotate(xxdeg) 语句改变朝向,例如:

transform: rotate( -180deg);

马黑黑 发表于 2023-6-23 07:47

纯CSS制作的桃心形:

<style>
.mybox {
        width: var(--ww);
        height: var(--ww);
        background: red;
        position: relative;
        transform: rotate(-135deg);
        margin: calc(var(--ww) / 2);
        --ww: 120px;
}
.mybox::before, .mybox::after {
        position: absolute;
        content: '';
        width: 100%;
        height: 100%;
        background: inherit;
        border-radius: 50%;
}
.mybox::before {
        top: calc(var(--ww) / 2);
}
.mybox::after {
        left: calc(var(--ww) / 2);
}
</style>

<div class="mybox"></div>

马黑黑 发表于 2023-6-23 08:03

<p>五楼代码的效果:<br><br></p>
<style>
.mybox {
      width: var(--ww);
      height: var(--ww);
      background: red;
      position: relative;
      transform: rotate(-135deg);
      margin: calc(var(--ww) / 2);
      --ww: 120px;
}
.mybox::before, .mybox::after {
      position: absolute;
      content: '';
      width: 100%;
      height: 100%;
      background: inherit;
      border-radius: 50%;
}
.mybox::before {
      top: calc(var(--ww) / 2);
}
.mybox::after {
      left: calc(var(--ww) / 2);
}
</style>

<div class="mybox"></div>

红影 发表于 2023-6-23 09:10

马黑黑 发表于 2023-6-23 08:03
五楼代码的效果:

.mybox {


先去回想了一下纯CSS制作的心形,差点忘了。终于想起来了,是用两个半圆扣在旋转过的方形上的{:4_173:}

红影 发表于 2023-6-23 09:12

还是用 clip-path: polygon() 绘制的桃心形更漂亮,而且可以选择是否镂空,这个太厉害了{:4_199:}

红影 发表于 2023-6-23 09:18

边缘系数可调,更加清楚地看到了边缘少的时候锯齿很明显。去试了一下,从小到大一点点看着它的变化,非常有趣。感觉到36以上就已经感觉比较光滑了呢{:4_173:}
而且是用百分比设定的,可以适应任何尺寸的正方形。这个真的太好了{:4_199:}

红影 发表于 2023-6-23 09:39

都是数学公式的运用呢。这么好的帖子又想置顶了,可惜置顶的不少了,算了{:4_173:}

马黑黑 发表于 2023-6-23 10:24

红影 发表于 2023-6-23 09:39
都是数学公式的运用呢。这么好的帖子又想置顶了,可惜置顶的不少了,算了

不用置顶的,已经置顶的,非必要的也可以放下来了

马黑黑 发表于 2023-6-23 10:25

红影 发表于 2023-6-23 09:18
边缘系数可调,更加清楚地看到了边缘少的时候锯齿很明显。去试了一下,从小到大一点点看着它的变化,非常有 ...

40的边缘系数吧,比较靠谱

马黑黑 发表于 2023-6-23 10:26

红影 发表于 2023-6-23 09:10
先去回想了一下纯CSS制作的心形,差点忘了。终于想起来了,是用两个半圆扣在旋转过的方形上的

实际上是整体旋转。两个圆是伪元素做的,移动一下位置。

马黑黑 发表于 2023-6-23 10:26

红影 发表于 2023-6-23 09:12
还是用 clip-path: polygon() 绘制的桃心形更漂亮,而且可以选择是否镂空,这个太厉害了

前面做的,如果需要,也都可以做镂空的

小辣椒 发表于 2023-6-23 12:30

黑黑辛苦,又出新的教程{:4_178:}

马黑黑 发表于 2023-6-23 12:35

小辣椒 发表于 2023-6-23 12:30
黑黑辛苦,又出新的教程

喝水
{:4_190:}

南无月 发表于 2023-6-23 17:37

马黑黑 发表于 2023-6-23 07:15
因为使用了百分比,所生成的 clip-path 代码适用于任意尺寸的正方形元素:




试试这一楼的代码

马黑黑 发表于 2023-6-23 18:16

南无月 发表于 2023-6-23 17:37
试试这一楼的代码

试的怎么样

醉美水芙蓉 发表于 2023-6-23 18:33

马黑黑 发表于 2023-6-23 19:15

醉美水芙蓉 发表于 2023-6-23 18:33
这个非常漂亮!谢谢老师分享教程!

喝茶
{:4_180:}
页: [1] 2 3 4 5
查看完整版本: 用 clip-path: polygon() 绘制桃心形