找回密码
 立即注册
搜索
查看: 12|回复: 0

offset-path ray函数演示(二)转自马黑教程专版

[复制链接]

1490

主题

3178

回帖

1万

积分

管理员

积分
12789
发表于 昨天 14:52 | 显示全部楼层 |阅读模式

offset-path ray函数演示(一) 中,大家可能已经对 ray() 函数有了些许印象,本演示则需要了解更多:ray 函数的所有参数以及其它相关知识。

💡ray() 函数语法:

ray(<angle> && <size>? && contain? && [at <position>]?)
对应参数含义:射线角度、射线长度、块内包含、射线起点位置。参数顺序没有硬性规定。

💡ray()函数参数

序号 参数 说明
1 angle 必须参数,规范射线方向,角度值,0deg 向上,顺时针增加
2 size 可选参数,路径长度,即 offset-distance 0% 和 100% 之间的距离,相对于包含块。可选值有 closest-side(最近边,默认)、 farthest-side(最远边)、closest-corner(最近角)、farthest-corner(最远角)、sides(沿角度到容器边界)
3 contain 可选参数,元素全程不超出包含块缩短线段的长度(设计本意,算法或浏览器支持度待改进)
4 at position 可选参数,指定射线的起点以及元素在其包含块中的放置位置,缺省默认 at 50% 50%

💡主要配套CSS属性

offset-distance - 沿路径的位置(0% ~ 100%)
offset-position - 射线起点(默认 50% 50%)
offset-rotate - 元素朝向(auto:随路径转向,角度值:朝向固定)
offset-anchor - 元素锚点(默认元素中心点)

💡演示代码(支持预览):

以下示例设计为综合性演示,ray() 的四个参数一起用上。演示代码不理解没有关系,关键在于演示体验:不同的参数组合生成的射线路径各异,体验时慢慢领会。体验中通过调节不同参数的值、查看 movebox 元素的运动状态应该有助于理解射线路径形态。演示加入了 offset-distance 相抵路径动画效果,在调整射线角度后触发。体验当中注意观察动态生成的 offset-path 路径代码。

<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[name="size"]:checked').value;
        const pos = `${atX.value}% ${atY.value}%`;
        let ray = `${rangeSet.value}deg ${contain} ${size} at ${pos}`.replaceAll('  ', ' ');
        ray = `ray(${ray})`;
        return ray;
    }
</script>
    
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

协同嘉业科技有限公司 ( 京ICP备2024053108号-1 )

GMT+8, 2026-8-2 05:29 , Processed in 0.095855 second(s), 22 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表