马黑黑 发表于 2023-6-20 22:42

用clip-path: polygon() 画心形

<style>
#mydiv {
        width: 300px;
        height: 300px;
        border: 1px solid gray;
        position: relative;
        margin: 30px auto;
        --clip: '';
}
#mydiv::before {
        position: absolute;
        content: '';
        width: 100%;
        height: 100%;
        background: pink;
        clip-path: var(--clip);
}
#msgBox { display: none; }
</style>

<div id="mydiv"></div>
<p><button id="showCode" value="1">查看代码</button>
<div id="msgBox"></div>

<script>

let ww = parseInt(window.getComputedStyle(mydiv).getPropertyValue('width'));

let mkPercent = (num1, num2) => (num2 / num1 * 100).toFixed(2) + '%';

let toRect = (r,theta) => {
        let x = r * Math.cos(theta) + ww / 2,
                y = r * Math.sin(theta) + ww / 4;
        return (mkPercent(ww,x) + ' ' + mkPercent(ww,y));
}

let clipBox = (max,points) => {
        let arr = [];
        for(let i = 0; i < points; i ++) {
                let a = 360 / points * i;
                let r = max * (1 + Math.sin(a));
                arr.push(toRect(r,a));
        }
        return `polygon(${arr.join(', ')})`;
}

showCode.onclick = () => msgBox.style.display = 'block';

mydiv.style.setProperty('--clip',clipBox(ww / 3,3600));
msgBox.innerText = window.getComputedStyle(mydiv).getPropertyValue('--clip');

</script>

马黑黑 发表于 2023-6-20 22:42

本帖最后由 马黑黑 于 2023-6-20 22:44 编辑

一楼代码<style>
#mydiv {
        width: 300px;
        height: 300px;
        border: 1px solid gray;
        position: relative;
        margin: 30px auto;
        --clip: '';
}
#mydiv::before {
        position: absolute;
        content: '';
        width: 100%;
        height: 100%;
        background: pink;
        clip-path: var(--clip);
}
#msgBox { display: none; }
</style>

<div id="mydiv"></div>
<p><button id="showCode" value="1">查看代码</button>
<div id="msgBox"></div>

<script>

let ww = parseInt(window.getComputedStyle(mydiv).getPropertyValue('width'));

let mkPercent = (num1, num2) => (num2 / num1 * 100).toFixed(2) + '%';

let toRect = (r,theta) => {
        let x = r * Math.cos(theta) + ww / 2,
                y = r * Math.sin(theta) + ww / 4;
        return (mkPercent(ww,x) + ' ' + mkPercent(ww,y));
}

let clipBox = (max,points) => {
        let arr = [];
        for(let i = 0; i < points; i ++) {
                let a = 360 / points * i;
                let r = max * (1 + Math.sin(a));
                arr.push(toRect(r,a));
        }
        return `polygon(${arr.join(', ')})`;
}

showCode.onclick = () => msgBox.style.display = 'block';

mydiv.style.setProperty('--clip',clipBox(ww / 3,3600));
msgBox.innerText = window.getComputedStyle(mydiv).getPropertyValue('--clip');

</script>

马黑黑 发表于 2023-6-20 22:42

本帖最后由 马黑黑 于 2023-6-20 23:16 编辑

心形曲线函数,用极坐标表示,可以是:

r=a(1+sinθ)

其中,r 在数学中通常表达为 ρ,指极径,即从原点 O 到任意一点 M 的线段长度;θ 指 OM 与 从原点往右的水平射线 OA 形成的角度,即 ∠MOA 的度数;a 是心形曲线与X轴交点到原点的距离。

心形曲线公式还可以是:

r=a(1-sinθ)
r=a(1+cosθ)
r=a(1-cosθ)

有了公式,我们还需要将极坐标转换为直角坐标系的xy坐标,其转换公式为:

x = r * cosθ
y = r * sinθ

本例使用的心形线函数是 r=a(1+sinθ) ,针对其特征,设 a 取正方形宽高 ww 的 ww/3,则 换算成xy坐标时,X坐标需要加上正方形元素宽高尺寸的 1/2,Y坐标加 1/4,这样生成的裁剪内区域才出现在较为中央处,使用其他公式需要另外调整加减数值。

以上是我个人对原始心形函数的理解,也许理解的不准确,有兴趣的朋友可以查阅相关高等数学知识。

马黑黑 发表于 2023-6-20 22:42

本帖最后由 马黑黑 于 2023-6-20 23:19 编辑

本例的心形形状,仅是心形中的一种,不收腰、底部没有尖点。它是经典的,所以先做这个。若有时间与兴趣,将来可能还会做其他形状的心形

梦缘 发表于 2023-6-20 22:48

问好老师,欣赏精彩分享,点赞!{:4_185:}

红影 发表于 2023-6-20 23:01

点开看到路径取了好多的点啊,那么长的。看到黑黑占楼了,等着看解说{:4_187:}

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

红影 发表于 2023-6-20 23:01
点开看到路径取了好多的点啊,那么长的。看到黑黑占楼了,等着看解说

3600个点,这样画出的心形边缘才比较平滑。

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

梦缘 发表于 2023-6-20 22:48
问好老师,欣赏精彩分享,点赞!

{:4_190:}

醉美水芙蓉 发表于 2023-6-20 23:28

马黑黑 发表于 2023-6-20 23:42

醉美水芙蓉 发表于 2023-6-20 23:28
刚开始我以为是苹果&#127822;呢!

苹果就是模仿心形长成那样纸的

樵歌 发表于 2023-6-21 07:13

好大一个红苹果{:4_189:}

马黑黑 发表于 2023-6-21 07:35

樵歌 发表于 2023-6-21 07:13
好大一个红苹果

嗯。

苹果为了诱惑人,将自己化身为心形。

——自《伊甸园》外传

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

心形线的定义之一:

心形线,简单来说就是有两个半径相同的圆,在一个动圆上固定点p(p的坐标有要求),然后这个动圆绕着另外一个定圆"外"侧转一周,p点形成的轨迹就是心形线。

红影 发表于 2023-6-21 19:16

马黑黑 发表于 2023-6-20 23:12
3600个点,这样画出的心形边缘才比较平滑。

嗯,以折代曲。这么密集的划分,看上去就像曲线一样呢。

马黑黑 发表于 2023-6-21 21:55

红影 发表于 2023-6-21 19:16
嗯,以折代曲。这么密集的划分,看上去就像曲线一样呢。

心形曲线相对变化大,需要那么多的坐标点,所以,css-doodle没有给出 @shape 心形

马黑黑 发表于 2023-6-21 22:06

桃子好像也是这个样纸

南无月 发表于 2023-6-22 13:17

裁三叶草的那个改成0.5也出现一个差不多的,不过方向不对

马黑黑 发表于 2023-6-22 15:06

南无月 发表于 2023-6-22 13:17
裁三叶草的那个改成0.5也出现一个差不多的,不过方向不对

方向对很容易的:transform: rotate(-90deg)

南无月 发表于 2023-6-22 17:30

马黑黑 发表于 2023-6-22 15:06
方向对很容易的:transform: rotate(-90deg)

好哒,我记得蝴蝶的时候教过。。应该举一反三的。。

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

南无月 发表于 2023-6-22 17:30
好哒,我记得蝴蝶的时候教过。。应该举一反三的。。

对的
页: [1] 2 3
查看完整版本: 用clip-path: polygon() 画心形