用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: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 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 23:19 编辑
本例的心形形状,仅是心形中的一种,不收腰、底部没有尖点。它是经典的,所以先做这个。若有时间与兴趣,将来可能还会做其他形状的心形 问好老师,欣赏精彩分享,点赞!{:4_185:} 点开看到路径取了好多的点啊,那么长的。看到黑黑占楼了,等着看解说{:4_187:} 红影 发表于 2023-6-20 23:01
点开看到路径取了好多的点啊,那么长的。看到黑黑占楼了,等着看解说
3600个点,这样画出的心形边缘才比较平滑。 梦缘 发表于 2023-6-20 22:48
问好老师,欣赏精彩分享,点赞!
{:4_190:} 醉美水芙蓉 发表于 2023-6-20 23:28
刚开始我以为是苹果🍎呢!
苹果就是模仿心形长成那样纸的 好大一个红苹果{:4_189:} 樵歌 发表于 2023-6-21 07:13
好大一个红苹果
嗯。
苹果为了诱惑人,将自己化身为心形。
——自《伊甸园》外传 心形线的定义之一:
心形线,简单来说就是有两个半径相同的圆,在一个动圆上固定点p(p的坐标有要求),然后这个动圆绕着另外一个定圆"外"侧转一周,p点形成的轨迹就是心形线。 马黑黑 发表于 2023-6-20 23:12
3600个点,这样画出的心形边缘才比较平滑。
嗯,以折代曲。这么密集的划分,看上去就像曲线一样呢。 红影 发表于 2023-6-21 19:16
嗯,以折代曲。这么密集的划分,看上去就像曲线一样呢。
心形曲线相对变化大,需要那么多的坐标点,所以,css-doodle没有给出 @shape 心形 桃子好像也是这个样纸 裁三叶草的那个改成0.5也出现一个差不多的,不过方向不对 南无月 发表于 2023-6-22 13:17
裁三叶草的那个改成0.5也出现一个差不多的,不过方向不对
方向对很容易的:transform: rotate(-90deg) 马黑黑 发表于 2023-6-22 15:06
方向对很容易的:transform: rotate(-90deg)
好哒,我记得蝴蝶的时候教过。。应该举一反三的。。 南无月 发表于 2023-6-22 17:30
好哒,我记得蝴蝶的时候教过。。应该举一反三的。。
对的