手记

SVG 图形引用、裁切和蒙版示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Star Sky</title>
    <style>
        html, body {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background: #001122;
            /*svg 标签是内联元素,防止撑满后会有滚动条出现*/
            line-height: 0;
            font-size: 0;
        }
    </style>
</head>
<body>
    <svg width="100%" height="100%" 
        viewBox="-400 -300 800 600"
        preserveAspectRatio="xMidYMid slice">

        <!-- 一颗星 -->
        <defs>
            <polygon id="star" points="0 -10 2 -2 10 0 2 2 0 10 -2 2 -10 0 -2 -2" fill="white"></polygon>
        </defs>

        <g id="real">

            <!-- 群星 -->
            <g id="star-group">
                <!-- 通过 JS 填充群星 -->
            </g>

            <!-- 月亮 -->
            <g id="moon-group" transform="translate(0 50)">
                <!-- 通过蒙版(mask)绘制弯月 -->
                <mask id="moon-mask">
                    <circle cx="-250" cy="-150" r="100" fill="white"></circle>
                    <circle cx="-200" cy="-200" r="100" fill="black"></circle>
                </mask>
                <circle cx="-250" cy="-150" r="100" fill="yellow" mask="url(#moon-mask)"></circle>
            </g>

            <!-- 灯塔 -->
            <g id="light-tower" transform="translate(250, 0)">
                <defs>
                    <linearGradient id="tower" x1="0" y1="0" x2="1" y2="0">
                        <stop offset="0" stop-color="#999"></stop>
                        <stop offset="1" stop-color="#333"></stop>
                    </linearGradient>
                    <radialGradient id="light" cx="0.5" cy="0.5" r="0.5">
                        <stop offset="0" stop-color="rgba(255, 255, 255, .8)"></stop>
                        <stop offset="1" stop-color="rgba(255, 255, 255, 0)"></stop>
                    </radialGradient>
                    <!-- 通过裁切(clipPath)绘制灯光 -->
                    <clipPath id="light-mask">
                        <polygon transform="rotate(10)" points="0 0 -300 -15 -300 15">
                            <animateTransform 
                                attributeName="transform"
                                attributeType="XML"
                                type="rotate"
                                from="0"
                                to="360"
                                dur="10s"
                                repeatCount="indefinite">
                            </animateTransform>
                        </polygon>
                        <circle cx="0" cy="0" r="2"></circle>
                    </clipPath>
                </defs>

                <!-- 塔柱 -->
                <polygon points="0 0 5 50 -5 50" fill="url(#tower)"></polygon>

                <!-- 灯光 -->
                <ellipse cx="0" cy="0" rx="300" ry="100" clip-path="url(#light-mask)" fill="url(#light)"></ellipse>
            </g>
        </g>

        <!-- 倒影 -->
        <g id="reflact" transform="translate(0 50)" mask="url(#reflact-mask)">
            <defs>
                <linearGradient id="gradient" x1="0" y1="0" x2="0" y2="1">
                    <stop offset="0" stop-color="rgba(255,255,255,.3)"></stop>
                    <stop offset="0.5" stop-color="rgba(255,255,255,0)"></stop>
                </linearGradient>
                <mask id="reflact-mask">
                    <rect x="-800" y="0" width="1600" height="400" fill="url(#gradient)"></rect>
                </mask>
            </defs>
            <use xlink:href="#real" transform="scale(1, -1) translate(0 -50)"></use>    
        </g>

        <!-- 地平线 -->
        <line x1="-400" y1="50" x2="400" y2="50" ></line>
    </svg>
</body>

<script>
    /* jshint browser: true */
    const SVG_NS = 'http://www.w3.org/2000/svg';
    const XLINK_NS = 'http://www.w3.org/1999/xlink';

    const paper = document.querySelector('svg');
    const defs = document.querySelector('svg defs');
    const starRef = document.getElementById('star');
    const starGroup = document.getElementById('star-group');
    let starCount = 500;

    renderStar();

    function use(origin) {
        const useTag = document.createElementNS(SVG_NS, 'use');
        useTag.setAttributeNS(XLINK_NS, 'xlink:href', '#' + origin.id);
        return useTag;
    }

    function random(min, max) {
        return min + (max - min) * Math.random();
    }

    function renderStar() {
        let opacitV, transV, scaleV;
        let star;

        while (starCount--) {
            opacitV = random(0.1, 0.4);
            transV = random(-400, 400) + ',' + random(-300, 50);
            scaleV = random(0.1, 0.6);
            star = use(starRef);

            star.setAttribute('opacity', opacitV);
            star.setAttribute('transform', 'translate(' + transV + ') scale(' + scaleV + ')');
            starGroup.appendChild(star);
        }
    }
</script>
</html>

Tips: 参考 techird 老师主讲的课程 《走进SVG 之 图形引用、裁切和蒙版示例》

0人推荐
随时随地看视频
慕课网APP