test

Inspire.js

Lean, hackable, extensible slide deck framework. Create basic slides by just writing HTML and CSS, do fancy custom stuff with JS, the sky is the limit!

Getting started

hfghfghfghfghhfghfg

CDN

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>加载动画生成器 - 动画速度修复版</title>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }
        
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            line-height: 1.6;
            color: #333;
            background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
            min-height: 100vh;
            padding: 20px;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
        }
        
        h1 {
            text-align: center;
            margin-bottom: 30px;
            color: #2c3e50;
        }
        
        h2 {
            margin: 25px 0 15px;
            color: #3498db;
            border-bottom: 1px solid #ddd;
            padding-bottom: 8px;
        }
        
        .templates {
            display: grid;
            grid-template-columns: repeat(5, 1fr);
            gap: 15px;
            margin-bottom: 30px;
        }
        
        @media (max-width: 1000px) {
            .templates {
                grid-template-columns: repeat(3, 1fr);
            }
        }
        
        @media (max-width: 600px) {
            .templates {
                grid-template-columns: repeat(2, 1fr);
            }
        }
        
        .template {
            background: white;
            border-radius: 8px;
            padding: 15px;
            box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);
            cursor: pointer;
            transition: all 0.3s;
            text-align: center;
        }
        
        .template:hover {
            transform: translateY(-5px);
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
        }
        
        .template.active {
            border: 2px solid #3498db;
            background: #e8f4fd;
        }
        
        .template-preview {
            height: 60px;
            display: flex;
            align-items: center;
            justify-content: center;
            margin-bottom: 10px;
        }
        
        .template-name {
            font-size: 14px;
            font-weight: 500;
        }
        
        .generator {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 20px;
        }
        
        @media (max-width: 900px) {
            .generator {
                grid-template-columns: 1fr;
            }
        }
        
        .panel {
            background: white;
            border-radius: 10px;
            padding: 25px;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
        }
        
        .preview-container {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            min-height: 200px;
            margin-bottom: 20px;
            border: 1px dashed #ccc;
            border-radius: 8px;
            padding: 20px;
        }
        
        .controls {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 15px;
        }
        
        .control-group {
            margin-bottom: 20px;
        }
        
        .control-group h3 {
            margin-bottom: 10px;
            font-size: 16px;
            color: #2c3e50;
        }
        
        .control-row {
            display: flex;
            align-items: center;
            margin-bottom: 10px;
        }
        
        label {
            flex: 1;
            font-weight: 500;
            font-size: 14px;
        }
        
        input[type="range"] {
            flex: 2;
            margin: 0 10px;
        }
        
        .value-display {
            width: 60px;
            text-align: center;
            font-family: monospace;
            font-size: 14px;
        }
        
        input[type="color"] {
            width: 40px;
            height: 30px;
            border: none;
            border-radius: 5px;
            cursor: pointer;
        }
        
        select {
            padding: 5px;
            border-radius: 5px;
            border: 1px solid #ddd;
        }
        
        .code-container {
            background: #2d2d2d;
            border-radius: 5px;
            padding: 15px;
            margin-top: 20px;
            overflow-x: auto;
        }
        
        pre {
            color: #f8f8f2;
            white-space: pre-wrap;
            font-family: 'Fira Code', monospace;
            font-size: 13px;
        }
        
        .comment { color: #75715e; }
        .selector { color: #a6e22e; }
        .property { color: #66d9ef; }
        .value { color: #ae81ff; }
        
        .export-btn {
            display: block;
            width: 100%;
            padding: 12px;
            background: #3498db;
            color: white;
            border: none;
            border-radius: 5px;
            font-size: 16px;
            cursor: pointer;
            margin-top: 20px;
            transition: background 0.3s;
        }
        
        .export-btn:hover {
            background: #2980b9;
        }
        
        /* 加载动画样式 */
        .loader {
            font-weight: bold;
            font-family: sans-serif;
            font-size: 20px;
        }
        
        .loader:before {
            content: "Loading...";
        }
        
        /* 方案1 */
        .loader-1 {
            animation: l1 1s linear infinite alternate;
        }
        @keyframes l1 {to{opacity: 0}}
        
        /* 方案2 */
        .loader-2 {
            width: fit-content;
            padding-bottom: 8px;
            background: linear-gradient(currentColor 0 0) 0 100%/0% 3px no-repeat;
            animation: l2 2s linear infinite;
        }
        @keyframes l2 {to{background-size: 100% 3px}}
        
        /* 方案3 */
        .loader-3 {
            width: fit-content;
            padding: 0 5px 8px 0;
            background: repeating-linear-gradient(90deg,currentColor 0 8%,#0000 0 10%) 200% 100%/200% 3px no-repeat;
            animation: l3 2s steps(6) infinite;
        }
        @keyframes l3 {to{background-position: 80% 100%}}
        
        /* 方案4 */
        .loader-4 {
            width: fit-content;
            font-family: monospace;
            clip-path: inset(0 3ch 0 0);
            animation: l4 1s steps(4) infinite;
        }
        @keyframes l4 {to{clip-path: inset(0 -1ch 0 0)}}
        
        /* 方案5 */
        .loader-5 {
            width: fit-content;
            font-family: monospace;
            clip-path: inset(0 100% 0 0);
            animation: l5 2s steps(11) infinite;
        }
        @keyframes l5 {to{clip-path: inset(0 -1ch 0 0)}}
        
        /* 方案6 */
        .loader-6 {
            --c:#000;
            width: fit-content;
            font-family: monospace;
            color: #0000;
            overflow: hidden;
            text-shadow: 0 0 var(--c),11ch 0 var(--c);
            animation: l6 2s infinite linear;
        }
        @keyframes l6 {to{text-shadow:-11ch 0 var(--c),0ch 0 var(--c)}}
        
        /* 方案7 */
        .loader-7 {
            width: fit-content;
            font-family: monospace;
            color: #0000;
            background: linear-gradient(90deg,#C02942 calc(50% + 0.5ch),#000 0) right/calc(200% + 1ch) 100%;
            -webkit-background-clip: text;
            background-clip: text;
            animation: l7 2s infinite steps(11);
        }
        @keyframes l7 {to{background-position: left}}
        
        /* 方案8 */
        .loader-8 {
            width: fit-content;
            font-family: monospace;
            color:#0000;
            background:linear-gradient(90deg,#000 calc(50% - 0.5ch),#C02942 0 calc(50% + 0.5ch),#000 0) right/calc(200% + 1ch) 100%;
            -webkit-background-clip:text;
            background-clip:text;
            animation: l8 2s infinite steps(11);
        }
        @keyframes l8 {to{background-position: left}}
        
        /* 方案9 */
        .loader-9 {
            width: fit-content;
            font-family: monospace;
            color :#0000;
            overflow: hidden;
            animation: l9 5s infinite cubic-bezier(0.3,1,0,1);
        }
        @keyframes l9 {
            0%  {text-shadow: 0 0 #000, 11ch 0 #8A9B0F, 22ch 0 #C02942, 33ch 0 #00A0B0,44ch 0 #000}
            25% {text-shadow:-11ch 0 #000, 0 0 #8A9B0F, 11ch 0 #C02942, 22ch 0 #00A0B0,33ch 0 #000}
            50% {text-shadow:-22ch 0 #000,-11ch 0 #8A9B0F, 0 0 #C02942, 11ch 0 #00A0B0,22ch 0 #000}
            75% {text-shadow:-33ch 0 #000,-22ch 0 #8A9B0F,-11ch 0 #C02942, 0 0 #00A0B0,11ch 0 #000}
            100%{text-shadow:-44ch 0 #000,-33ch 0 #8A9B0F,-22ch 0 #C02942,-11ch 0 #00A0B0,0 0 #000}
        }
        
        /* 方案10 */
        .loader-10 {
            width: fit-content;
            font-family: monospace;
            color:#0000;
            background: linear-gradient(90deg,#000 25%,#8A9B0F 0 50%,#C02942 0 75%,#00A0B0 0) 0 0/400% 100%;
            -webkit-background-clip:text;
            background-clip:text;
            animation:l10 5s infinite cubic-bezier(0.3,1,0,1);
        }
        @keyframes l10 {
            25% {background-position: calc(1*100%/3) 0}
            50% {background-position: calc(2*100%/3) 0}
            75% {background-position: calc(3*100%/3) 0}
            100%{background-position: calc(4*100%/3) 0}
        }
        
        /* 方案11 */
        .loader-11 {
            font-family: monospace;
            display: inline-grid;
        }
        .loader-11:before,
        .loader-11:after {
            content:"Loading...";
            grid-area: 1/1;
            -webkit-mask:linear-gradient(90deg,#000 50%,#0000 0) 0 50%/2ch 100%;
            animation: l11 1s infinite cubic-bezier(0.5,220,0.5,-220);
        }
        .loader-11:after {
            -webkit-mask-position:1ch 50%;
            --s:-1;
        }
        @keyframes l11 {100%{transform: translateY(calc(var(--s,1)*0.1%));}}
        
        /* 方案12 */
        .loader-12 {
            font-family: monospace;
            display: inline-grid;
            overflow: hidden;
        }
        .loader-12:before,
        .loader-12:after {
            content: "Loading...";
            grid-area: 1/1;
            clip-path: inset(0 -200% 50%);
            text-shadow: -10ch 0 0;
            animation: l12 1s infinite;
        }
        .loader-12:after {
            clip-path: inset(50% -200% 0%);
            text-shadow: 10ch 0 0;
            --s:-1;
        }
        @keyframes l12 {50%,100%{transform: translateX(calc(var(--s,1)*100%));}}
        
        /* 方案13 */
        .loader-13 {
            font-family: monospace;
            display: inline-grid;
            overflow: hidden;
        }
        .loader-13:before,
        .loader-13:after {
            content: "Loading...";
            grid-area: 1/1;
            clip-path: inset(0 -200% 50%);
            text-shadow: -10ch 0 0;
            animation: l13 2s infinite;
        }
        .loader-13:after {
            clip-path: inset(50% -200% 0%);
            text-shadow: 10ch 0 0;
            --s:-1;
            animation-delay: 1s;
        }
        @keyframes l13 {25%,100%{transform: translateX(calc(var(--s,1)*100%));}}
        
        /* 方案14 */
        .loader-14 {
            width: fit-content;
            padding-bottom: 5px;
            font-family: monospace;
            overflow: hidden;
            color: #0000;
            text-shadow: 0 0 0 #000,10ch 0 0 #000;
            background: linear-gradient(#000 0 0) bottom left/0% 3px no-repeat;
            animation: l14 1.5s infinite;
        }
        @keyframes l14 {
            80%  {text-shadow: 0 0 0 #000,10ch 0 0 #000;background-size:100% 3px}
            100% {text-shadow: -10ch 0 0 #000,0 0 0 #000}
        }
        
        /* 方案15 */
        .loader-15 {
            font-family: monospace;
            line-height: 1.2em;
            display: inline-grid;
        }
        .loader-15:before,
        .loader-15:after {
            content:"Loading...";
            grid-area: 1/1;
            -webkit-mask: linear-gradient(90deg,#000 50%,#0000 0) 0 50%/2ch 100%;
            color: #0000;
            text-shadow: 0 0 0 #000,0 calc(var(--s,1)*1.2em) 0 #000;
            animation: l15 1s infinite;
        }
        .loader-15:after {
            -webkit-mask-position: 1ch 50%;
            --s:-1;
        }
        @keyframes l15 {80%,100%{text-shadow:0 calc(var(--s,1)*-1.2em) 0 #000,0 0 0 #000}}
        
        /* 方案16 */
        .loader-16 {
            --w:10ch;
            font-family: monospace;
            letter-spacing: var(--w);
            width:var(--w);
            overflow: hidden;
            white-space: nowrap;
            text-shadow: 
                calc(-1*var(--w)) 0, 
                calc(-2*var(--w)) 0, 
                calc(-3*var(--w)) 0, 
                calc(-4*var(--w)) 0,
                calc(-5*var(--w)) 0, 
                calc(-6*var(--w)) 0, 
                calc(-7*var(--w)) 0, 
                calc(-8*var(--w)) 0, 
                calc(-9*var(--w)) 0;
            animation: l16 2s infinite;
        }
        @keyframes l16 {
            20% {text-shadow: 
                calc(-1*var(--w)) 0, 
                calc(-2*var(--w)) 0 red, 
                calc(-3*var(--w)) 0, 
                calc(-4*var(--w)) 0 #ffa516,
                calc(-5*var(--w)) 0 #63fff4, 
                calc(-6*var(--w)) 0, 
                calc(-7*var(--w)) 0, 
                calc(-8*var(--w)) 0 green, 
                calc(-9*var(--w)) 0;}
            40% {text-shadow: 
                calc(-1*var(--w)) 0, 
                calc(-2*var(--w)) 0 red, 
                calc(-3*var(--w)) 0 #e945e9, 
                calc(-4*var(--w)) 0,
                calc(-5*var(--w)) 0 green, 
                calc(-6*var(--w)) 0 orange, 
                calc(-7*var(--w)) 0, 
                calc(-8*var(--w)) 0 green, 
                calc(-9*var(--w)) 0;}
            60% {text-shadow: 
                calc(-1*var(--w)) 0 lightblue, 
                calc(-2*var(--w)) 0, 
                calc(-3*var(--w)) 0 #e945e9, 
                calc(-4*var(--w)) 0,
                calc(-5*var(--w)) 0 green, 
                calc(-6*var(--w)) 0, 
                calc(-7*var(--w)) 0 yellow, 
                calc(-8*var(--w)) 0 #ffa516, 
                calc(-9*var(--w)) 0 red;}
            80% {text-shadow: 
                calc(-1*var(--w)) 0 lightblue, 
                calc(-2*var(--w)) 0 yellow, 
                calc(-3*var(--w)) 0 #63fff4, 
                calc(-4*var(--w)) 0 #ffa516,
                calc(-5*var(--w)) 0 red, 
                calc(-6*var(--w)) 0, 
                calc(-7*var(--w)) 0 grey, 
                calc(-8*var(--w)) 0 #63fff4, 
                calc(-9*var(--w)) 0 ;}
        }
    </style>
</head>
<body>
    <h1>加载动画生成器 - 动画速度修复版</h1>
    
    <div class="container">
        <h2>选择加载动画模板</h2>
        <div class="templates" id="templates">
            <!-- 模板将通过JS动态生成 -->
        </div>
        
        <h2>自定义设置</h2>
        <div class="generator">
            <div class="panel">
                <div class="preview-container">
                    <div class="loader loader-1" id="previewLoader"></div>
                </div>
                
                <button class="export-btn" id="exportBtn">复制CSS代码</button>
                
                <div class="code-container">
                    <pre id="cssCode"><code><span class="comment">/* 生成的CSS代码 */</span>
<span class="selector">.loader</span> {
  <span class="property">font-weight</span>: <span class="value" id="code-font-weight">bold</span>;
  <span class="property">font-family</span>: <span class="value" id="code-font-family">sans-serif</span>;
  <span class="property">font-size</span>: <span class="value" id="code-font-size">30px</span>;
  <span class="property">animation</span>: <span class="value" id="code-animation">l1 1s linear infinite alternate</span>;
}

<span class="selector">.loader:before</span> {
  <span class="property">content</span>: <span class="value">"Loading..."</span>;
}

<span class="selector">@keyframes l1</span> {
  <span class="selector">to</span> { <span class="property">opacity</span>: <span class="value">0</span>; }
}</code></pre>
                </div>
            </div>
            
            <div class="panel">
                <h2>参数调整</h2>
                
                <div class="controls">
                    <div class="control-group">
                        <h3>基本设置</h3>
                        <div class="control-row">
                            <label for="fontSize">字体大小:</label>
                            <input type="range" id="fontSize" min="10" max="50" value="30">
                            <span class="value-display" id="fontSizeValue">30px</span>
                        </div>
                        <div class="control-row">
                            <label for="fontWeight">字体粗细:</label>
                            <select id="fontWeight">
                                <option value="normal">普通</option>
                                <option value="bold" selected>加粗</option>
                                <option value="bolder">更粗</option>
                                <option value="lighter">更细</option>
                            </select>
                        </div>
                        <div class="control-row">
                            <label for="fontFamily">字体:</label>
                            <select id="fontFamily">
                                <option value="sans-serif" selected>无衬线</option>
                                <option value="monospace">等宽</option>
                                <option value="serif">衬线</option>
                                <option value="cursive">手写</option>
                            </select>
                        </div>
                    </div>
                    
                    <div class="control-group">
                        <h3>颜色设置</h3>
                        <div class="control-row">
                            <label for="color">颜色:</label>
                            <input type="color" id="color" value="#000000">
                        </div>
                    </div>
                    
                    <div class="control-group">
                        <h3>动画设置</h3>
                        <div class="control-row">
                            <label for="speed">动画速度:</label>
                            <input type="range" id="speed" min="0.5" max="5" step="0.1" value="1">
                            <span class="value-display" id="speedValue">1s</span>
                        </div>
                        <div class="control-row">
                            <label for="timing">时间函数:</label>
                            <select id="timing">
                                <option value="linear" selected>linear</option>
                                <option value="ease">ease</option>
                                <option value="ease-in">ease-in</option>
                                <option value="ease-out">ease-out</option>
                                <option value="ease-in-out">ease-in-out</option>
                                <option value="steps(4)">steps(4)</option>
                                <option value="cubic-bezier(0.3,1,0,1)">cubic-bezier</option>
                            </select>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script>
        // 当前选中的加载器类型
        let currentLoaderType = 1;
        
        // 模板数据
        const templates = [
            { id: 1, name: "淡入淡出", class: "loader-1" },
            { id: 2, name: "下划线", class: "loader-2" },
            { id: 3, name: "点状下划线", class: "loader-3" },
            { id: 4, name: "打字效果1", class: "loader-4" },
            { id: 5, name: "打字效果2", class: "loader-5" },
            { id: 6, name: "滑动文本", class: "loader-6" },
            { id: 7, name: "渐变文本1", class: "loader-7" },
            { id: 8, name: "渐变文本2", class: "loader-8" },
            { id: 9, name: "多彩阴影", class: "loader-9" },
            { id: 10, name: "多彩渐变", class: "loader-10" },
            { id: 11, name: "弹跳效果", class: "loader-11" },
            { id: 12, name: "拆分滑动1", class: "loader-12" },
            { id: 13, name: "拆分滑动2", class: "loader-13" },
            { id: 14, name: "滑动下划线", class: "loader-14" },
            { id: 15, name: "上下跳动", class: "loader-15" },
            { id: 16, name: "多彩字母", class: "loader-16" }
        ];
        
        // 初始化模板
        function initTemplates() {
            const templatesContainer = document.getElementById('templates');
            
            templates.forEach(template => {
                const templateElement = document.createElement('div');
                templateElement.className = 'template';
                templateElement.dataset.id = template.id;
                
                templateElement.innerHTML = `
                    <div class="template-preview">
                        <div class="loader ${template.class}"></div>
                    </div>
                    <div class="template-name">${template.id}. ${template.name}</div>
                `;
                
                templateElement.addEventListener('click', () => {
                    setLoaderType(template.id);
                });
                
                templatesContainer.appendChild(templateElement);
            });
            
            // 默认选中第一个模板
            setLoaderType(1);
        }
        
        // 设置加载器类型
        function setLoaderType(type) {
            currentLoaderType = type;
            
            // 更新模板选中状态
            document.querySelectorAll('.template').forEach(template => {
                if (parseInt(template.dataset.id) === type) {
                    template.classList.add('active');
                } else {
                    template.classList.remove('active');
                }
            });
            
            // 更新预览
            updatePreview();
        }
        
        // 更新预览
        function updatePreview() {
            const previewLoader = document.getElementById('previewLoader');
            const fontSize = document.getElementById('fontSize').value;
            const fontWeight = document.getElementById('fontWeight').value;
            const fontFamily = document.getElementById('fontFamily').value;
            const color = document.getElementById('color').value;
            const speed = document.getElementById('speed').value;
            const timing = document.getElementById('timing').value;
            
            // 更新样式
            previewLoader.style.fontSize = fontSize + 'px';
            previewLoader.style.fontWeight = fontWeight;
            previewLoader.style.fontFamily = fontFamily;
            previewLoader.style.color = color;
            
            // 更新类名
            previewLoader.className = 'loader';
            previewLoader.classList.add(`loader-${currentLoaderType}`);
            
            // 创建动态样式来更新动画速度和时序函数
            const styleId = 'loaderAnimationStyle';
            let existingStyle = document.getElementById(styleId);
            if (existingStyle) {
                document.head.removeChild(existingStyle);
            }
            
            const style = document.createElement('style');
            style.id = styleId;
            
            // 为当前选定的加载器类型设置动画
            style.textContent = `
                #previewLoader {
                    animation: l${currentLoaderType} ${speed}s ${timing} infinite;
                }
            `;
            
            document.head.appendChild(style);
            
            // 更新代码显示
            updateCodeDisplay();
        }
        
        // 更新代码显示
        function updateCodeDisplay() {
            const fontSize = document.getElementById('fontSize').value;
            const fontWeight = document.getElementById('fontWeight').value;
            const fontFamily = document.getElementById('fontFamily').value;
            const speed = document.getElementById('speed').value;
            const timing = document.getElementById('timing').value;
            
            document.getElementById('code-font-size').textContent = `${fontSize}px`;
            document.getElementById('code-font-weight').textContent = fontWeight;
            document.getElementById('code-font-family').textContent = fontFamily;
            document.getElementById('code-animation').textContent = `l${currentLoaderType} ${speed}s ${timing} infinite`;
            
            // 根据不同的加载器类型更新代码
            updateKeyframesCode();
        }
        
        // 更新关键帧代码
        function updateKeyframesCode() {
            const keyframesElement = document.querySelector('#cssCode .value:last-child');
            if (!keyframesElement) return;
            
            // 根据当前选择的加载器类型显示相应的关键帧代码
            switch(currentLoaderType) {
                case 1:
                    keyframesElement.textContent = "to { opacity: 0; }";
                    break;
                case 2:
                    keyframesElement.textContent = "to { background-size: 100% 3px; }";
                    break;
                case 3:
                    keyframesElement.textContent = "to { background-position: 80% 100%; }";
                    break;
                case 4:
                    keyframesElement.textContent = "to { clip-path: inset(0 -1ch 0 0); }";
                    break;
                case 5:
                    keyframesElement.textContent = "to { clip-path: inset(0 -1ch 0 0); }";
                    break;
                case 6:
                    keyframesElement.textContent = "to { text-shadow: -11ch 0 var(--c), 0ch 0 var(--c); }";
                    break;
                case 7:
                    keyframesElement.textContent = "to { background-position: left; }";
                    break;
                case 8:
                    keyframesElement.textContent = "to { background-position: left; }";
                    break;
                case 9:
                    keyframesElement.textContent = "0% { text-shadow: 0 0 #000, 11ch 0 #8A9B0F, 22ch 0 #C02942, 33ch 0 #00A0B0, 44ch 0 #000; }\n  25% { text-shadow: -11ch 0 #000, 0 0 #8A9B0F, 11ch 0 #C02942, 22ch 0 #00A0B0, 33ch 0 #000; }\n  50% { text-shadow: -22ch 0 #000, -11ch 0 #8A9B0F, 0 0 #C02942, 11ch 0 #00A0B0, 22ch 0 #000; }\n  75% { text-shadow: -33ch 0 #000, -22ch 0 #8A9B0F, -11ch 0 #C02942, 0 0 #00A0B0, 11ch 0 #000; }\n  100% { text-shadow: -44ch 0 #000, -33ch 0 #8A9B0F, -22ch 0 #C02942, -11ch 0 #00A0B0, 0 0 #000; }";
                    break;
                case 10:
                    keyframesElement.textContent = "25% { background-position: calc(1*100%/3) 0; }\n  50% { background-position: calc(2*100%/3) 0; }\n  75% { background-position: calc(3*100%/3) 0; }\n  100% { background-position: calc(4*100%/3) 0; }";
                    break;
                case 11:
                    keyframesElement.textContent = "100% { transform: translateY(calc(var(--s,1)*0.1%)); }";
                    break;
                case 12:
                    keyframesElement.textContent = "50%, 100% { transform: translateX(calc(var(--s,1)*100%)); }";
                    break;
                case 13:
                    keyframesElement.textContent = "25%, 100% { transform: translateX(calc(var(--s,1)*100%)); }";
                    break;
                case 14:
                    keyframesElement.textContent = "80% { text-shadow: 0 0 0 #000, 10ch 0 0 #000; background-size: 100% 3px; }\n  100% { text-shadow: -10ch 0 0 #000, 0 0 0 #000; }";
                    break;
                case 15:
                    keyframesElement.textContent = "80%, 100% { text-shadow: 0 calc(var(--s,1)*-1.2em) 0 #000, 0 0 0 #000; }";
                    break;
                case 16:
                    keyframesElement.textContent = "20% { text-shadow: calc(-1*var(--w)) 0, calc(-2*var(--w)) 0 red, calc(-3*var(--w)) 0, calc(-4*var(--w)) 0 #ffa516, calc(-5*var(--w)) 0 #63fff4, calc(-6*var(--w)) 0, calc(-7*var(--w)) 0, calc(-8*var(--w)) 0 green, calc(-9*var(--w)) 0; }\n  40% { text-shadow: calc(-1*var(--w)) 0, calc(-2*var(--w)) 0 red, calc(-3*var(--w)) 0 #e945e9, calc(-4*var(--w)) 0, calc(-5*var(--w)) 0 green, calc(-6*var(--w)) 0 orange, calc(-7*var(--w)) 0, calc(-8*var(--w)) 0 green, calc(-9*var(--w)) 0; }\n  60% { text-shadow: calc(-1*var(--w)) 0 lightblue, calc(-2*var(--w)) 0, calc(-3*var(--w)) 0 #e945e9, calc(-4*var(--w)) 0, calc(-5*var(--w)) 0 green, calc(-6*var(--w)) 0, calc(-7*var(--w)) 0 yellow, calc(-8*var(--w)) 0 #ffa516, calc(-9*var(--w)) 0 red; }\n  80% { text-shadow: calc(-1*var(--w)) 0 lightblue, calc(-2*var(--w)) 0 yellow, calc(-3*var(--w)) 0 #63fff4, calc(-4*var(--w)) 0 #ffa516, calc(-5*var(--w)) 0 red, calc(-6*var(--w)) 0, calc(-7*var(--w)) 0 grey, calc(-8*var(--w)) 0 #63fff4, calc(-9*var(--w)) 0; }";
                    break;
            }
        }
        
        // 复制CSS代码
        function copyCSSCode() {
            const fontSize = document.getElementById('fontSize').value;
            const fontWeight = document.getElementById('fontWeight').value;
            const fontFamily = document.getElementById('fontFamily').value;
            const color = document.getElementById('color').value;
            const speed = document.getElementById('speed').value;
            const timing = document.getElementById('timing').value;
            
            let cssCode = `.loader {
  font-weight: ${fontWeight};
  font-family: ${fontFamily};
  font-size: ${fontSize}px;
  color: ${color};
  animation: l${currentLoaderType} ${speed}s ${timing} infinite;
}

.loader:before {
  content: "Loading...";
}

@keyframes l${currentLoaderType} {
  ${getKeyframesCode()}
}`;

            navigator.clipboard.writeText(cssCode).then(() => {
                const exportBtn = document.getElementById('exportBtn');
                exportBtn.textContent = '已复制到剪贴板!';
                setTimeout(() => {
                    exportBtn.textContent = '复制CSS代码';
                }, 2000);
            });
        }
        
        // 获取关键帧代码
        function getKeyframesCode() {
            switch(currentLoaderType) {
                case 1: return "to { opacity: 0; }";
                case 2: return "to { background-size: 100% 3px; }";
                case 3: return "to { background-position: 80% 100%; }";
                case 4: return "to { clip-path: inset(0 -1ch 0 0); }";
                case 5: return "to { clip-path: inset(0 -1ch 0 0); }";
                case 6: return "to { text-shadow: -11ch 0 var(--c), 0ch 0 var(--c); }";
                case 7: return "to { background-position: left; }";
                case 8: return "to { background-position: left; }";
                case 9: return "0% { text-shadow: 0 0 #000, 11ch 0 #8A9B0F, 22ch 0 #C02942, 33ch 0 #00A0B0, 44ch 0 #000; }\n  25% { text-shadow: -11ch 0 #000, 0 0 #8A9B0F, 11ch 0 #C02942, 22ch 0 #00A0B0, 33ch 0 #000; }\n  50% { text-shadow: -22ch 0 #000, -11ch 0 #8A9B0F, 0 0 #C02942, 11ch 0 #00A0B0, 22ch 0 #000; }\n  75% { text-shadow: -33ch 0 #000, -22ch 0 #8A9B0F, -11ch 0 #C02942, 0 0 #00A0B0, 11ch 0 #000; }\n  100% { text-shadow: -44ch 0 #000, -33ch 0 #8A9B0F, -22ch 0 #C02942, -11ch 0 #00A0B0, 0 0 #000; }";
                case 10: return "25% { background-position: calc(1*100%/3) 0; }\n  50% { background-position: calc(2*100%/3) 0; }\n  75% { background-position: calc(3*100%/3) 0; }\n  100% { background-position: calc(4*100%/3) 0; }";
                case 11: return "100% { transform: translateY(calc(var(--s,1)*0.1%)); }";
                case 12: return "50%, 100% { transform: translateX(calc(var(--s,1)*100%)); }";
                case 13: return "25%, 100% { transform: translateX(calc(var(--s,1)*100%)); }";
                case 14: return "80% { text-shadow: 0 0 0 #000, 10ch 0 0 #000; background-size: 100% 3px; }\n  100% { text-shadow: -10ch 0 0 #000, 0 0 0 #000; }";
                case 15: return "80%, 100% { text-shadow: 0 calc(var(--s,1)*-1.2em) 0 #000, 0 0 0 #000; }";
                case 16: return "20% { text-shadow: calc(-1*var(--w)) 0, calc(-2*var(--w)) 0 red, calc(-3*var(--w)) 0, calc(-4*var(--w)) 0 #ffa516, calc(-5*var(--w)) 0 #63fff4, calc(-6*var(--w)) 0, calc(-7*var(--w)) 0, calc(-8*var(--w)) 0 green, calc(-9*var(--w)) 0; }\n  40% { text-shadow: calc(-1*var(--w)) 0, calc(-2*var(--w)) 0 red, calc(-3*var(--w)) 0 #e945e9, calc(-4*var(--w)) 0, calc(-5*var(--w)) 0 green, calc(-6*var(--w)) 0 orange, calc(-7*var(--w)) 0, calc(-8*var(--w)) 0 green, calc(-9*var(--w)) 0; }\n  60% { text-shadow: calc(-1*var(--w)) 0 lightblue, calc(-2*var(--w)) 0, calc(-3*var(--w)) 0 #e945e9, calc(-4*var(--w)) 0, calc(-5*var(--w)) 0 green, calc(-6*var(--w)) 0, calc(-7*var(--w)) 0 yellow, calc(-8*var(--w)) 0 #ffa516, calc(-9*var(--w)) 0 red; }\n  80% { text-shadow: calc(-1*var(--w)) 0 lightblue, calc(-2*var(--w)) 0 yellow, calc(-3*var(--w)) 0 #63fff4, calc(-4*var(--w)) 0 #ffa516, calc(-5*var(--w)) 0 red, calc(-6*var(--w)) 0, calc(-7*var(--w)) 0 grey, calc(-8*var(--w)) 0 #63fff4, calc(-9*var(--w)) 0; }";
                default: return "to { opacity: 0; }";
            }
        }
        
        // 添加事件监听器
        document.getElementById('fontSize').addEventListener('input', () => {
            document.getElementById('fontSizeValue').textContent = document.getElementById('fontSize').value + 'px';
            updatePreview();
        });
        
        document.getElementById('fontWeight').addEventListener('change', updatePreview);
        document.getElementById('fontFamily').addEventListener('change', updatePreview);
        document.getElementById('color').addEventListener('input', updatePreview);
        document.getElementById('speed').addEventListener('input', () => {
            document.getElementById('speedValue').textContent = document.getElementById('speed').value + 's';
            updatePreview();
        });
        document.getElementById('timing').addEventListener('change', updatePreview);
        document.getElementById('exportBtn').addEventListener('click', copyCSSCode);
        
        // 初始化
        initTemplates();
    </script>
</body>
</html>

<script src="https://inspirejs.org/inspire.js"></script>

or

import Inspire from "https://inspirejs.org/inspire.mjs";

NPM

npm install inspirejs.org

then

<script src="node_modules/inspirejs.org/inspire.js"></script>

or

import Inspire from "node_modules/inspirejs.org/inspire.mjs";

or if you use a bundler:

import Inspire from "inspirejs.org";

Quick start

  • Copy (and rename) blank.html somewhere
  • Also copy talk.css, theme.css
  • Add Your Own Content
  • Add talk-specific styling to talk.css

Previously known as CSSS.

If you were using CSSS and would rather stay at it, run git checkout v1.0.0 and stay there.Migrating from CSSS

  • Almost all HTML syntax is the same! The same JS events are still fired. So, very little should break.
  • slideshow.css is now inspire.css
  • slideshow.js is now inspire.js
  • You don’t need to run JS to create a slideshow, it is created automatically.
  • The SlideShow JS class is now Inspire
  • The slideshow JS variable is now Inspire
  • Presenter view will not be loaded unless there is at least one class="presenter-notes" item.
  • The CSS Controls plugin is now gone. Use Mavo if you need this functionality.
  • The CSS Snippets plugin is now gone. We will soon add a much better one, extracted based on the live demo script in https://github.com/leaverou/talks.
  • Incrementable is no longer a plugin. Use the separate script from https://github.com/leaverou/incrementable.
  • reusable.css has now been merged into the default theme, theme.css.
  • data-import is now data-insert

API FAQ

Running code after any imports have loaded

await Inspire.importsLoaded;
// code to run after imports have loaded

Note that await needs to be inside an async function otherwise it will error. However, this could just be a self-executing async function.

Running code after a specific plugin has loaded

await Inspire.importsLoaded;
await Inspire.plugins.loaded.PLUGIN_ID.loaded;
// code to run after the plugin with id PLUGIN_ID has loaded and executed

or:

await Inspire.loadPlugin(PLUGIN_ID);
// code to run after the plugin with id PLUGIN_ID has loaded and executed

The second example would load the plugin if it hasn’t otherwise been loaded, but if it will never be loaded twice.

Running code when a specific slide is displayed

You can do this via the slidechange hook:

Inspire.hooks.add("slidechange", env => {
	if (Inspire.currentSlide.id === "slide-id") {
		// Code to run
	}
});

or, via an event:

document.addEventListener("slidechange", evt => {
	if (Inspire.currentSlide.id === "slide-id") {
		// Code to run
	}
});

Running code when a specific slide is displayed for the first time

You can do this via the slidechange hook:

Inspire.hooks.add("slidechange", env => {
	if (Inspire.currentSlide.id === "slide-id" && env.firstTime) {
		// Code to run
	}
});

or, via an event:

document.addEventListener("slidechange", evt => {
	if (Inspire.currentSlide.id === "slide-id" && evt.firstTime) {
		// Code to run
	}
});

or:

$("#slide-id").addEventListener("slidechange", evt => {
	// Code to run
}, {once: true});

Running code after a specific slide has been displayed

You can do this via the slidechange hook:

Inspire.hooks.add("slidechange", env => {
	if (env.prevSlide.id === "slide-id") {
		// Code to run
	}
});

or, via an event:

document.addEventListener("slidechange", evt => {
	if (evt.prevSlide.id === "slide-id") {
		// Code to run
	}
});
© 版权声明
THE END
点赞11 分享
Suggestion
评论 抢沙发

请登录后发表评论

    暂无评论内容