富文本编辑器edit icon

作者:
邓朝元
Fork(复制)
下载
嵌入
BUG反馈
index.html
现在支持上传本地图片了!
index.html
            
            <!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>高级富文本编辑器</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
      background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
      min-height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
      padding: 20px;
    }

    .editor-container {
      width: 90%;
      max-width: 1000px;
      background-color: white;
      border-radius: 12px;
      box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
      overflow: hidden;
    }

    .editor-header {
      background: linear-gradient(to right, #4b6cb7, #182848);
      color: white;
      padding: 20px;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    .editor-title {
      font-size: 1.8rem;
      font-weight: 600;
    }

    .theme-selector {
      display: flex;
      gap: 10px;
      align-items: center;
    }

    .theme-btn {
      width: 24px;
      height: 24px;
      border-radius: 50%;
      border: 2px solid white;
      cursor: pointer;
      transition: transform 0.2s;
    }

    .theme-btn:hover {
      transform: scale(1.1);
    }

    .theme-btn.active {
      transform: scale(1.2);
      box-shadow: 0 0 0 2px #333;
    }

    .toolbar {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
      padding: 15px;
      background-color: #f8f9fa;
      border-bottom: 1px solid #e0e0e0;
    }

    .toolbar-group {
      display: flex;
      gap: 5px;
      padding: 0 10px;
      border-right: 1px solid #e0e0e0;
    }

    .toolbar-group:last-child {
      border-right: none;
    }

    .toolbar-btn {
      background-color: #f0f0f0;
      border: 1px solid #ddd;
      padding: 8px 12px;
      cursor: pointer;
      font-size: 14px;
      border-radius: 4px;
      display: flex;
      align-items: center;
      gap: 5px;
      transition: all 0.2s;
    }

    .toolbar-btn:hover {
      background-color: #e0e0e0;
      transform: translateY(-2px);
    }

    .toolbar-btn.active {
      background-color: #4b6cb7;
      color: white;
    }

    .font-selector {
      display: flex;
      align-items: center;
      gap: 5px;
    }

    .font-selector select,
    .font-selector input {
      padding: 6px 10px;
      border: 1px solid #ddd;
      border-radius: 4px;
      font-size: 14px;
    }

    .editor {
      min-height: 400px;
      padding: 20px;
      border: none;
      font-family: Arial, sans-serif;
      font-size: 16px;
      line-height: 1.6;
      outline: none;
      overflow-y: auto;
      max-height: 500px;
    }

    .editor:focus {
      box-shadow: inset 0 0 0 2px #4b6cb7;
      border-radius: 4px;
    }

    .download-options {
      padding: 20px;
      background-color: #f8f9fa;
      display: flex;
      justify-content: flex-end;
      gap: 15px;
      border-top: 1px solid #e0e0e0;
    }

    .download-btn {
      padding: 12px 24px;
      background: linear-gradient(to right, #4b6cb7, #182848);
      color: white;
      border: none;
      border-radius: 6px;
      cursor: pointer;
      font-size: 16px;
      font-weight: 500;
      display: flex;
      align-items: center;
      gap: 8px;
      transition: all 0.3s;
    }

    .download-btn:hover {
      transform: translateY(-3px);
      box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
    }

    .status-bar {
      padding: 10px 20px;
      background-color: #f8f9fa;
      border-top: 1px solid #e0e0e0;
      font-size: 14px;
      color: #666;
      display: flex;
      justify-content: space-between;
    }

    .theme-light {
      --bg-color: #ffffff;
      --text-color: #333333;
      --toolbar-bg: #f8f9fa;
      --border-color: #e0e0e0;
    }

    .theme-dark {
      --bg-color: #2c3e50;
      --text-color: #ecf0f1;
      --toolbar-bg: #34495e;
      --border-color: #4a5f7a;
    }

    .theme-sepia {
      --bg-color: #fdf6e3;
      --text-color: #586e75;
      --toolbar-bg: #eee8d5;
      --border-color: #d6d0c3;
    }

    .theme-mono {
      --bg-color: #000000;
      --text-color: #00ff00;
      --toolbar-bg: #111111;
      --border-color: #333333;
    }

    .theme-dark .editor-container,
    .theme-sepia .editor-container,
    .theme-mono .editor-container {
      background-color: var(--bg-color);
      color: var(--text-color);
    }

    .theme-dark .toolbar,
    .theme-sepia .toolbar,
    .theme-mono .toolbar {
      background-color: var(--toolbar-bg);
      border-bottom: 1px solid var(--border-color);
    }

    .theme-dark .download-options,
    .theme-sepia .download-options,
    .theme-mono .download-options {
      background-color: var(--toolbar-bg);
      border-top: 1px solid var(--border-color);
    }

    .theme-dark .status-bar,
    .theme-sepia .status-bar,
    .theme-mono .status-bar {
      background-color: var(--toolbar-bg);
      border-top: 1px solid var(--border-color);
    }

    .theme-dark .toolbar-btn,
    .theme-sepia .toolbar-btn,
    .theme-mono .toolbar-btn {
      background-color: var(--toolbar-bg);
      border: 1px solid var(--border-color);
      color: var(--text-color);
    }

    .theme-dark .toolbar-btn:hover,
    .theme-sepia .toolbar-btn:hover,
    .theme-mono .toolbar-btn:hover {
      background-color: var(--border-color);
    }

    .theme-dark .editor,
    .theme-sepia .editor,
    .theme-mono .editor {
      color: var(--text-color);
    }

    .theme-dark .editor:focus,
    .theme-sepia .editor:focus,
    .theme-mono .editor:focus {
      box-shadow: inset 0 0 0 2px #4b6cb7;
    }

    .theme-dark .download-btn,
    .theme-sepia .download-btn,
    .theme-mono .download-btn {
      background: linear-gradient(to right, #4b6cb7, #182848);
    }

    .color-picker {
      display: flex;
      align-items: center;
      gap: 5px;
    }

    .color-input {
      width: 30px;
      height: 30px;
      border: none;
      border-radius: 4px;
      cursor: pointer;
    }

    @media (max-width: 768px) {
      .toolbar {
        flex-direction: column;
      }
      
      .toolbar-group {
        border-right: none;
        border-bottom: 1px solid #e0e0e0;
        padding-bottom: 10px;
      }
      
      .editor-header {
        flex-direction: column;
        gap: 15px;
        text-align: center;
      }
      
      .theme-selector {
        justify-content: center;
      }
    }
  </style>
</head>
<body>
  <div class="editor-container theme-light">
    <div class="editor-header">
      <h1 class="editor-title"><i class="fas fa-edit"></i> 高级富文本编辑器</h1>
      <div class="theme-selector">
        <div class="theme-btn active" style="background-color: #ffffff;" data-theme="light" title="明亮主题"></div>
        <div class="theme-btn" style="background-color: #2c3e50;" data-theme="dark" title="暗黑主题"></div>
        <div class="theme-btn" style="background-color: #fdf6e3;" data-theme="sepia" title="护眼主题"></div>
        <div class="theme-btn" style="background-color: #000000;" data-theme="mono" title="代码主题"></div>
      </div>
    </div>
    
    <div class="toolbar">
      <div class="toolbar-group">
        <button class="toolbar-btn" onclick="execCommand('undo')" title="撤销">
          <i class="fas fa-undo"></i>
        </button>
        <button class="toolbar-btn" onclick="execCommand('redo')" title="重做">
          <i class="fas fa-redo"></i>
        </button>
      </div>
      
      <div class="toolbar-group">
        <button class="toolbar-btn" onclick="execCommand('bold')" title="粗体">
          <i class="fas fa-bold"></i>
        </button>
        <button class="toolbar-btn" onclick="execCommand('italic')" title="斜体">
          <i class="fas fa-italic"></i>
        </button>
        <button class="toolbar-btn" onclick="execCommand('underline')" title="下划线">
          <i class="fas fa-underline"></i>
        </button>
      </div>
      
      <div class="toolbar-group">
        <div class="font-selector">
          <select class="toolbar-btn" onchange="execCommand('fontName', this.value)" title="字体">
            <option value="Arial">Arial</option>
            <option value="Helvetica">Helvetica</option>
            <option value="Times New Roman">Times New Roman</option>
            <option value="Courier New">Courier New</option>
            <option value="Georgia">Georgia</option>
            <option value="Verdana">Verdana</option>
            <option value="Comic Sans MS">Comic Sans MS</option>
            <option value="Impact">Impact</option>
          </select>
        </div>
        
        <div class="font-selector">
          <select class="toolbar-btn" onchange="execCommand('fontSize', this.value)" title="字体大小">
            <option value="1">8px</option>
            <option value="2">10px</option>
            <option value="3">12px</option>
            <option value="4" selected>14px</option>
            <option value="5">16px</option>
            <option value="6">18px</option>
            <option value="7">20px</option>
          </select>
        </div>
        
        <div class="color-picker">
          <label for="text-color" title="文字颜色"><i class="fas fa-palette"></i></label>
          <input type="color" id="text-color" class="color-input" value="#000000" onchange="execCommand('foreColor', this.value)">
        </div>
        
        <div class="color-picker">
          <label for="bg-color" title="背景色"><i class="fas fa-fill-drip"></i></label>
          <input type="color" id="bg-color" class="color-input" value="#ffffff" onchange="execCommand('backColor', this.value)">
        </div>
      </div>
      
      <div class="toolbar-group">
        <button class="toolbar-btn" onclick="execCommand('insertOrderedList')" title="编号列表">
          <i class="fas fa-list-ol"></i>
        </button>
        <button class="toolbar-btn" onclick="execCommand('insertUnorderedList')" title="项目符号">
          <i class="fas fa-list-ul"></i>
        </button>
      </div>
      
      <div class="toolbar-group">
        <button class="toolbar-btn" onclick="execCommand('justifyLeft')" title="左对齐">
          <i class="fas fa-align-left"></i>
        </button>
        <button class="toolbar-btn" onclick="execCommand('justifyCenter')" title="居中">
          <i class="fas fa-align-center"></i>
        </button>
        <button class="toolbar-btn" onclick="execCommand('justifyRight')" title="右对齐">
          <i class="fas fa-align-right"></i>
        </button>
        <button class="toolbar-btn" onclick="execCommand('justifyFull')" title="两端对齐">
          <i class="fas fa-align-justify"></i>
        </button>
      </div>
      
      <div class="toolbar-group">
        <button class="toolbar-btn" onclick="execCommand('createLink')" title="插入链接">
          <i class="fas fa-link"></i>
        </button>
        <button class="toolbar-btn" onclick="execCommand('insertImage')" title="插入图片">
          <i class="fas fa-image"></i>
        </button>
        <button class="toolbar-btn" onclick="execCommand('insertHorizontalRule')" title="插入分割线">
          <i class="fas fa-grip-lines"></i>
        </button>
      </div>
    </div>
    
    <div class="editor" contenteditable="true">
      <h2>欢迎使用高级富文本编辑器</h2>
      <p>这是一个功能强大的富文本编辑器,支持以下功能:</p>
      <ul>
        <li>选中特定文字进行格式修改</li>
        <li>多种主题切换(明亮、暗黑、护眼、代码)</li>
        <li>丰富的字体和颜色选择</li>
        <li>列表、对齐等格式化功能</li>
        <li>下载文本或HTML格式文件</li>
      </ul>
      <p>您可以选中这段文字,然后使用工具栏对选中的文字进行格式化。</p>
      <p>试试看吧!</p>
    </div>

    <div class="status-bar">
      <div class="word-count">字数: <span id="count">0</span></div>
      <div class="theme-info">当前主题: <span id="theme-name">明亮</span></div>
    </div>
    
    <div class="download-options">
      <button class="download-btn" onclick="downloadText()">
        <i class="fas fa-file-alt"></i> 下载文本
      </button>
      <button class="download-btn" onclick="downloadHTML()">
        <i class="fas fa-code"></i> 下载HTML
      </button>
    </div>
  </div>

  <script>
    // 主题切换功能
    const themeButtons = document.querySelectorAll('.theme-btn');
    const editorContainer = document.querySelector('.editor-container');
    const themeName = document.getElementById('theme-name');
    
    themeButtons.forEach(button => {
      button.addEventListener('click', () => {
        // 移除所有活动状态
        themeButtons.forEach(btn => btn.classList.remove('active'));
        
        // 添加当前选中状态
        button.classList.add('active');
        
        // 获取主题值
        const theme = button.getAttribute('data-theme');
        
        // 应用主题
        editorContainer.className = 'editor-container theme-' + theme;
        
        // 更新状态栏
        const themeDisplayNames = {
          'light': '明亮',
          'dark': '暗黑',
          'sepia': '护眼',
          'mono': '代码'
        };
        themeName.textContent = themeDisplayNames[theme];
      });
    });
    
    // 执行编辑命令
    function execCommand(command, value = null) {
      document.execCommand(command, false, value);
      document.querySelector('.editor').focus();
    }
    
    // 下载纯文本文件
    function downloadText() {
      const content = document.querySelector('.editor').innerText;
      const blob = new Blob([content], { type: 'text/plain' });
      const link = document.createElement('a');
      link.href = URL.createObjectURL(blob);
      link.download = 'document.txt';
      link.click();
    }
    
    // 下载HTML文件
    function downloadHTML() {
      const content = document.querySelector('.editor').innerHTML;
      const blob = new Blob([`<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>文档</title>
  <style>
    body { font-family: Arial, sans-serif; }
  </style>
</head>
<body>
  ${content}
</body>
</html>`], { type: 'text/html' });
      const link = document.createElement('a');
      link.href = URL.createObjectURL(blob);
      link.download = 'document.html';
      link.click();
    }
    
    // 实时更新字数
    const editor = document.querySelector('.editor');
    const wordCount = document.getElementById('count');
    
    editor.addEventListener('input', updateWordCount);
    
    function updateWordCount() {
      const text = editor.innerText || editor.textContent;
      wordCount.textContent = text.length;
    }
    
    // 初始化字数
    updateWordCount();
    
    // 防止某些命令导致编辑器失去焦点
    document.querySelectorAll('.toolbar-btn').forEach(button => {
      button.addEventListener('mousedown', function(e) {
        e.preventDefault();
      });
    });
    
    // 模拟插入图片功能(实际项目中需要实现文件上传)
    document.querySelector('[title="插入图片"]').addEventListener('click', function() {
      const url = prompt('请输入图片URL:', 'https://via.placeholder.com/300x200.png');
      if (url) {
        execCommand('insertImage', url);
      }
    });
    
    // 模拟插入链接功能
    document.querySelector('[title="插入链接"]').addEventListener('click', function() {
      const url = prompt('请输入链接地址:', 'https://example.com');
      if (url) {
        execCommand('createLink', url);
      }
    });
  </script>
</body>
</html>
        
编辑器加载中
预览
控制台