offset-path ray函数演示(二)
<style>.artBox { margin: 20px auto; font: normal 18px/26px sans-serif; max-width: 1200px; }
.artBox mark { padding: 2px 6px; background: #ccc; }
.artBox blockquote { padding: 14px; border: solid gray; border-width: 0 4px; border-radius: 10px; background: #ddd; }
.artBox p { margin: 10px 0; }
.artBox table { border-collapse: collapse; white-space: pre-wrap; box-sizing: border-box; margin: 10px 0; }
.artBox th, .artBox td { padding: 8px 10px; border: 1px solid #999; }
.artBox th { text-align: center; background: #eee; }
</style>
<div class="artBox">
<p>在 <a href="https://www.huachaowang.com/forum.php?mod=viewthread&tid=95004&extra=page%3D1" target="_blank">offset-path ray函数演示(一)</a> 中,大家可能已经对 ray() 函数有了些许印象,本演示则需要了解更多:ray 函数的所有参数以及其它相关知识。</p>
<h3>💡ray() 函数语法:</h3>
<blockquote>
ray(<angle> && <size>? && contain? && ?)<br>
对应参数含义:射线角度、射线长度、块内包含、射线起点位置。参数顺序没有硬性规定。
</blockquote>
<table>
<caption style="text-align: left"><h3>💡ray()函数参数</h3></caption>
<tr>
<th width="50">序号</th>
<th width="100">参数</th>
<th>说明</th>
</tr>
<tr>
<td>1</td>
<td>angle</td>
<td>必须参数,规范射线方向,角度值,0deg 向上,顺时针增加</td>
</tr>
<tr>
<td>2</td>
<td>size</td>
<td>可选参数,路径长度,即 offset-distance 0% 和 100% 之间的距离,相对于包含块。可选值有 closest-side(最近边,默认)、 farthest-side(最远边)、closest-corner(最近角)、farthest-corner(最远角)、sides(沿角度到容器边界)</td>
</tr>
<tr>
<td>3</td>
<td>contain</td>
<td>可选参数,元素全程不超出包含块缩短线段的长度(设计本意,算法或浏览器支持度待改进)</td>
</tr>
<tr>
<td>4</td>
<td>at position</td>
<td>可选参数,指定射线的起点以及元素在其包含块中的放置位置,缺省默认 at 50% 50%</td>
</tr>
</table>
<h3>💡主要配套CSS属性</h3>
<blockquote>
offset-distance - 沿路径的位置(0% ~ 100%)<br>
offset-position - 射线起点(默认 50% 50%)<br>
offset-rotate - 元素朝向(auto:随路径转向,角度值:朝向固定)<br>
offset-anchor - 元素锚点(默认元素中心点)
</blockquote>
<h3>💡演示代码(支持预览):</h3>
<p>以下示例设计为综合性演示,ray() 的四个参数一起用上。演示代码不理解没有关系,关键在于演示体验:不同的参数组合生成的射线路径各异,体验时慢慢领会。体验中通过调节不同参数的值、查看 movebox 元素的运动状态应该有助于理解射线路径形态。演示加入了 offset-distance 相抵路径动画效果,在调整射线角度后触发。体验当中注意观察动态生成的 offset-path 路径代码。</p>
<div class="hEdiv" data-prev="1"><pre class="hEpre">
<style>
@import 'https://638183.freep.cn/638183/web/css/hl.css';
h2 { text-align: center; }
.pa {
width: 800px;
height: 400px;
border: 1px solid gray;
position: relative;
margin: 30px auto 0;
}
.pa:nth-of-type(1)::before {
position: absolute;
content: attr(data-code);
width: 100%;
bottom: 10px;
text-align: center;
}
.pa:nth-of-type(2) {
border-width: 0;
}
.movebox {
padding: 0px;
font-size: 36px;
border: 1px solid gray;
position: absolute;
}
@keyframes move {
from { offset-distance: 0%; }
to { offset-distance: 100%; }
}
</style>
<h2>ray()函数综合演示</h2>
<div id="pa" class="pa hlCode" data-code="offset-path尚未生成">
<div class="movebox">➡️</div>
</div>
<div class="pa">
<p>
<label for="rangeSet">调整角度 :</label>
<input id="rangeSet" type="range" value="0" max="360" min="-360" step="5" />
<output id="outRes">0</output>
</p>
<p>
<label>路径长度:</label>
<input id="r1" type="radio" name="size" value="closest-side" checked />
<label for="r1">closest-side</label>
<input id="r2" type="radio" name="size" value="farthest-side" />
<label for="r2">farthest-side</label>
<input id="r3" type="radio" name="size" value="closest-corner" />
<label for="r3">closest-corner</label>
<input id="r4" type="radio" name="size" value="farthest-corner" />
<label for="r4">farthest-corner</label>
<input id="r5" type="radio" name="size" value="sides" />
<label for="r5">sides</label>
</p>
<p>
<label for="chkContain">contain :</label>
<input id="chkContain" type="checkbox" value="contain" checked />
</p>
<p>
<label for="atX">射线起点(x坐标):</label>
<input id="atX" type="range" max="100" min="0" value="50"/>
<output id="outX">50%</output>
</p>
<p>
<label for="atY">射线起点(y坐标):</label>
<input id="atY" type="range" max="100" min="0" value="50"/>
<output id="outY">50%</output>
</p>
<p><button onclick="location.reload()">全部重置</button></p>
</div>
<script>
const movebox = document.querySelector('.movebox');
movebox.onanimationend = () => rangeSet.disabled = false;
movebox.onanimationstart = () => rangeSet.disabled = true;
rangeSet.oninput = () => {
outRes.value = rangeSet.value + 'deg';
movebox.style.setProperty('offset-path', createRayPath());
}
rangeSet.onchange = () => {
const path = createRayPath();
movebox.style.animation = '';
pa.dataset.code = `offset-path: ${path};`;
setTimeout( () => {
movebox.style.setProperty('offset-path', `${path}`);
movebox.style.setProperty('animation', 'move linear 2s forwards');
}, 500);
};
atX.oninput = () => {
movebox.style.setProperty('offset-path', createRayPath());
outX.value = `${atX.value}%`;
};
atY.oninput = () => {
movebox.style.setProperty('offset-path', createRayPath());
outY.value = `${atY.value}%`;
};
function createRayPath() {
const contain = chkContain.checked ? 'contain' : '';
const size = document.querySelector('input:checked').value;
const pos = `${atX.value}% ${atY.value}%`;
let ray = `${rangeSet.value}deg ${contain} ${size} at ${pos}`.replaceAll('', ' ');
ray = `ray(${ray})`;
return ray;
}
</script>
</pre></div>
</div>
<script type="module">
import hl from 'https://638183.freep.cn/638183/web/js/hl.js';
const divs = document.querySelectorAll('.hEdiv');
const pres = document.querySelectorAll('.hEpre');
divs.forEach((div,idx) => hl.hl(div, pres));
</script> 马老师中午好!
这个我运行了一下,特别赞佩!喜欢这形式,我先抱走了。很感谢您的分享,辛苦了,祝您吉祥快乐!{:4_178:}{:4_199:}{:4_190:}{:4_204:}
去运行了一下,看着小方块按照指令滑行着,closest-side(最近边,默认)还有最远边等等的那几个设置没弄明白是什么意思呢{:4_204:} 小辣椒欣赏加学习{:4_187:} 小辣椒 发表于 2026-8-1 13:06
小辣椒欣赏加学习
{:4_190:} 红影 发表于 2026-8-1 12:56
去运行了一下,看着小方块按照指令滑行着,closest-side(最近边,默认)还有最远边等等的那几个设置没弄 ...
表格里关于 ray() 参数都有简要说明。
size 参数用来设置射线的长度,共有五个可选值,都是基于包含块(容器)的边界、从起点到指定边的距离:
① 最近边,射线长度按从起点到最近边的距离计算(缺省默认);
② 最远边,射线长度按从起点到最远边的距离计算;
③ 最近角,射线长度按从起点到最近角的距离计算;
④ 最远角,射线长度按从起点到最远角的距离计算;
⑤ sides(边界),射线长度按从起点到射线延长线与容器相交的边的距离计算。 谢谢马老师精彩讲解 ray函数四个参数的直观效果。另:contain作为可选参数,默认值是什么? 马黑黑 发表于 2026-8-1 15:09
表格里关于 ray() 参数都有简要说明。
size 参数用来设置射线的长度,共有五个可选值,都是基于包含块 ...
所以,我不明白的是,最近边和最远边到底是什么呢? 红影 发表于 2026-8-2 09:18
所以,我不明白的是,最近边和最远边到底是什么呢?
射线都有起点,假设是 a(40% 20%)。
因为角度,射线有了方向,假设是 0deg,射线朝上(正上方向)。
射线的长度依据 size 参数设定,假设设为最近边(closest-side),那么,射线的长度按 a 点到四个边中的最近的那一个计。这条边不论是哪一边,不一定是射线指向的边,仅用作距离参照,即点 a 到这个边的垂直距离。
所以,这条射线,起点在点 a、方向指向正北、长度是点 a 到最近边的距离。 杨帆 发表于 2026-8-1 22:23
谢谢马老师精彩讲解 ray函数四个参数的直观效果。另:contain作为可选参数,默认值是什么?
contain 参数缺省默认就是没有 contain,所以,contain 有就有,没有就没有 马黑黑 发表于 2026-8-2 12:25
contain 参数缺省默认就是没有 contain,所以,contain 有就有,没有就没有
谢谢老师答疑解惑~{:4_190:} 杨帆 发表于 2026-8-2 13:18
谢谢老师答疑解惑~
{:4_190:} 马黑黑 发表于 2026-8-2 12:22
射线都有起点,假设是 a(40% 20%)。
因为角度,射线有了方向,假设是 0deg,射线朝上(正上方向)。
我的天,刚发现,这个概念居然这么奇特,还是头一次知道呢,怪不的前面怎么都想不明白。 红影 发表于 2026-8-2 21:39
我的天,刚发现,这个概念居然这么奇特,还是头一次知道呢,怪不的前面怎么都想不明白。
CSS中,最近边、最远边和最近角、最远角是常用的距离概念
页:
[1]