vue3实现svg文本特效样式编辑风格选择生成svg和css代码

代码语言:html

所属分类:布局界面

代码描述:vue3实现svg文本特效样式编辑风格选择生成svg和css代码,输入文本,选择文本特效样式,就能预览效果,还能复制效果的css及svg代码,直接粘贴到html中就能用。

代码标签: vue svg 文本 特效 样式 编辑 风格 选择 生成 svg css 代码

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>SVG 文字特效编辑器</title>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/vue3.2.22.js"></script>
  <style>
    :root {
      --bg-color: #1a1a1a;
      --panel-bg: #242424;
      --text-color: #f0f0f0;
      --primary-color: #42b883;
      --border-color: #333;
      --input-bg: #333;
      --shadow-color: rgba(0, 0, 0, 0.5);
    }
    @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap');
    * {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }
    html, body {
      height: 100%;
      overflow: hidden;
    }
    body {
      font-family: 'Poppins', sans-serif;
      background-color: var(--bg-color);
      color: var(--text-color);
      display: flex;
      justify-content: center;
      align-items: center;
    }
    #app {
      display: grid;
      grid-template-columns: 320px 1fr;
      width: 100vw;
      height: 100vh;
      gap: 1px;
      background-color: var(--border-color);
    }
    .control-panel {
      background-color: var(--panel-bg);
      padding: 24px;
      display: flex;
      flex-direction: column;
      gap: 20px;
    }
    .control-panel h1 {
      font-size: 24px;
      color: var(--primary-color);
      text-align: center;
      margin-bottom: 10px;
      font-weight: 700;
    }
    .input-group label {
      display: block;
      margin-bottom: 8px;
      font-size: 14px;
      font-weight: 600;
      color: #aaa;
    }
    .input-group input {
      width: 100%;
      padding: 10px;
      background-color: var(--input-bg);
      border: 1px solid var(--border-color);
      border-radius: 6px;
      color: var(--text-color);
      font-size: 16px;
    }
    .input-group input:focus {
      outline: none;
      border-color: var(--primary-color);
    }
    .effects-list {
      flex-grow: 1;
      overflow-y: auto;
      padding-right: 10px;
      height: 100vh;
    }
    .effects-list::-webkit-scrollbar {
      width: 6px;
    }
    .effects-list::-webkit-scrollbar-thumb {
      background: var(--primary-color);
      border-radius: 3px;
    }
    .effect-item {
      padding: 12px;
      margin-bottom: 6px;
      border-radius: 6px;
      cursor: pointer;
      font-weight: 600;
    }
    .effect-item:hover {
      background-color: var(--input-bg);
    }
    .effect-item.active {
      background-color: var(--primary-color);
      color: var(--bg-color);
      font-weight: 700;
    }
    .preview-area {
      background-color: var(--bg-color);
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      padding: 40px;
      position: relative;
      overflow: hidden;
    }
    .preview-content {
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .preview-content svg {
      width: 90%;
      max-height: 90%;
      overflow: visible;
    }
    .copy-button {
      position: absolute;
      bottom: 30px;
      right: 30px;
      padding: 12px 24px;
      background-color: var(--primary-color);
      color: var(--bg-color);
      border: none;
      border-radius: 8px;
      font-size: 16px;
      font-weight: 700;
      cursor: pointer;
      box-shadow: 0 4px 15px var(--shadow-color);
    }
    .copy-button:hover {
      transform: translateY(-2px);
      box-shadow: 0 6px 20px var(--shadow-color);
    }
    .copy-button.copied {
      background-color: #28a745;
    }
  </style>
</head>
<body>
<div id="app">
  <div class="control-panel">
    <h1>SVG 文字特效编辑器</h1>
    <div class="input-group">
      <label for="text-input">编辑文本</label>
      <input id="text-input" type="text" v-model="text" />
    </div>
    <div class="input-group">
      <label>选择特效</label>
    </div>
    <div class="effects-list">
      <div
        v-for="effect in effects"
        :key="effect.id"
        class="effect-item"
        :class="{ active: selectedEffect && selectedEffect.id === effect.id }"
        @click="selectEffect(effect)"
      >
        {{ effect.name }}
      </div>
    </div>
  </div>

  <div class="preview-area">
    <div class="preview-content">
      <div v-if="selectedEffect" v-html="previewHtml"></div>
    </div>
    <button class="copy-button" :class="{ copied }" @click="copyCode">
      {{ copyButtonText }}
    </button>
  </div>
</div>

<script>
const { createApp, ref, computed, onMounted, watchEffect } = Vue;

createApp({
  setup() {
    const text = ref("Hello SVG");
    const effects = ref([]);
    const selectedEffect = ref(null);
    const copied = ref(false);

    const previewHtml = computed(() => {
      if (!selectedEffect.value) return "";
      return selectedEffect.value.svg(text.value);
    });

    const copyButtonText = computed(() =>
      copied.value ? "已复制!" : "复制代码"
    );

    const codeToCopy = computed(() => {
      if (!selectedEffect.value) return "";
      const { name, svg, css } = selectedEffect.value;
      const svgContent = svg(text.value);
      const cssContent = typeof css === "function" ? css(text.value) : css;
      return `<!-- ${name} 特效代码 -->\n${svgContent.trim()}\n<style>\n${cssContent.trim()}\n</style>`;
    });

    const selectEffect = (effect) => {
      selectedEffect.value = effect;
    };

    const copyCode = async () => {
      if (!navigator.clipboard) {
        alert("浏览器不支持 Clipboard API");
        return;
      }
      try {
        await navigator.clipboard.writeText(codeToCopy.value);
        copied.value = true;
        setTimeout(() => (copied.value = false), 2000);
      } catch (err) {
        alert("复制失败!");
      }
    };

    onMounted(() => {
      // 示例:只放一个特效,更多可继续加
      effects.value = [
       {
    id: 'gradient-fill',
    name: '多彩渐变填充',
    svg: (txt) => `<svg viewBox="0 0 800 200"><defs><linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" /><stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" /></linearGradient></defs><text class="effect-text" x="50%" y="50%" dominant-baseline="middle" text-anchor="middle">${txt}</text></svg>`,
    css: `.effect-text { font-size: 100px; font-weight: bold; fill: url(#grad1); }`
  },
  {
    id: 'neon-glow',
    name: '霓虹灯光',
    svg: (txt) => `<svg viewBox="0 0 800 200"><text class="effect-text" x="50%" y="50%" dominant-baseline="middle" text-anchor="middle">${txt}</text></svg>`,
    css: `.effect-text { font-size: 100px; font-weight: bold; fill: #fff; stroke: #f0f; stroke-width: 2px; text-shadow: 0 0 10px #f0f, 0 0 20px #f0f, 0 0 30px #f0f, 0 0 40px #f0f; }`
  },
  {
    id: 'simple-stroke',
    name: '简约描边',
    svg: (txt) => `<svg viewBox="0 0 800 200"><text class="effect-text" x="50%" y="50%" dominant-baseline="middle" text-anchor="middle">${txt}</text></svg>`,
    css: `.effect-text { font-size: 120px; font-weight: 900; fill: none; stroke: #42b883; stroke-width: 2; }`
  },
  {
    id: 'double-stroke',
    name: '双层描边',
    svg: (txt) => `<svg viewBox="0 0 800 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><symbol id="s-text"><text text-anchor="middle" x="50%" y=".........完整代码请登录后点击上方下载按钮下载查看

网友评论0