svg+vue实现多种json转换可视化图表效果代码

代码语言:html

所属分类:图表

代码描述:svg+vue实现多种json转换可视化图表效果代码,适合通过ai将文本或文章转换成json格式数据生成多种类型的图表场景应用。

代码标签: svg vue 多种 json 转换 可视化 图表

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

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Vue + SVG 多布局信息图表生成器 )</title>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/vue.global.3.5.18.js"></script>
    <style>
        /* --- Global Styles --- */
        body {
            font-family: 'PingFang SC', 'Helvetica Neue', 'Microsoft YaHei', sans-serif;
            margin: 0; background-color: #f0f2f5; color: #333;
            display: flex; justify-content: center; align-items: center; height: 100vh;
            -webkit-font-smoothing: antialiased;
            -moz-osx-font-smoothing: grayscale;
        }
        .main-container {
            display: flex; width: 95vw; height: 95vh; max-width: 1700px;
            background: #fff; border-radius: 16px; box-shadow: 0 12px 40px rgba(0,0,0,0.08);
            overflow: hidden;
        }
        button { cursor: pointer; border: none; border-radius: 6px; padding: 8px 16px; transition: background-color 0.2s; }
        textarea {
            width: 100%; box-sizing: border-box; padding: 10px; border: 1px solid #dcdfe6;
            border-radius: 6px; font-family: 'Consolas', 'Monaco', monospace; font-size: 13px;
            line-height: 1.5; resize: vertical;
        }
        
        /* --- Layout --- */
        .sidebar { width: 240px; border-right: 1px solid #e8eaf0; display: flex; flex-direction: column; background: #fafbfc; }
        .main-content { flex: 1; display: flex; }
        .canvas-container { flex: 1; padding: 20px; display: flex; justify-content: center; align-items: center; }
        .editor-panel { width: 380px; border-left: 1px solid #e8eaf0; display: flex; flex-direction: column; padding: 20px; gap: 15px; background: #fff; }

        /* --- Sidebar Styles --- */
        .sidebar h2 { font-size: 18px; padding: 20px; margin: 0; border-bottom: 1px solid #e8eaf0; color: #333; }
        .layout-list { flex: 1; overflow-y: auto; }
        .layout-list button {
            display: block; width: 100%; text-align: left; background: none; font-size: 14px;
            padding: 15px 20px; border-bottom: 1px solid #e8eaf0;
        }
        .layout-list button:hover { background-color: #f0f2f5; }
        .layout-list button.active { background-color: #869AE8; color: white; font-weight: bold; }

        /* --- Editor Panel Styles --- */
        .editor-panel h3 { margin: 0; font-size: 16px; }
        #json-editor { min-height: 400px; }
        .btn-export { background-color: #28a745; color: white; font-weight: bold; }
        .btn-export:hover { background-color: #218838; }
        .btn-reset { background-color: #6c757d; color: white; }
        .btn-reset:hover { background-color: #5a6268; }

        /* --- Canvas Styles --- */
        .svg-wrapper {
            width: 100%; height: 100%;
            background-color: #F7F9FC;
            border-radius: 8px;
            display: flex; justify-content: center; align-items: center; padding:10px; box-sizing: border-box;
        }
        svg { max-width: 100%; max-height: 100%; }

        /* Helper for text wrapping in SVG foreignObject */
        .svg-text-wrap { margin: 0; padding-left: 1.1em; }
        .svg-text-wrap li { list-style-type: disc; margin-bottom: 8px; line-height: 1.6; }

        /* Utility: ensure middle baseline works consistently when set */
        /* Note: attributes are applied inline where needed, this is just a fallback */
        .svg-center-baseline {
            dominant-baseline: middle;
            alignment-baseline: middle;
        }
    </style>
</head>
<body>

<div id="app" class="main-container">
    <aside class="sidebar">
        <h2>图表类型</h2>
        <div class="layout-list">
            <button v-for="layout in layouts" :key="layout.id" :class="{ active: layout.id === selectedLayoutId }" @click="selectLayout(layout.id)">{{ layout.name }}</button>
        </div>
    </aside>

    <main class="main-content">
        <div class="canvas-container">
            <div class="svg-wrapper" id="svg-container">
                <component :is="activeComponent" :data="currentData" v-if="activeComponent && isDataValid"></component>
                <div v-else>JSON 数据格式错误或正在加载...</div>
            </div>
        </div>

        <aside class="editor-panel">
            <h3>JSON 数据编辑器</h3>
            <textarea id="json-editor" v-model="jsonDataString"></textarea>
            <button class="btn-export" @click="exportToPng">导出为 PNG</button>
            <button class="btn-reset" @click="resetData">重置当前图表数据</button>
            <p style="font-size:12px; color:#999;">直接修改上面的 JSON,图表会实时更新。如果格式错误,图表将不会渲染。</p>
        </aside>
    </main>
</div>

<script>
const { createApp, ref, computed, watch, shallowRef } = Vue;

// ===============================================================
//  定义所有图表组件(修复文字错位)
// ===============================================================

const SwotChart = {
  props: ['data'],
  template: `<svg viewBox="0 0 800 550" preserveAspectRatio="xMidYMid meet">
    <defs>
      <linearGradient id="swot-s" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#5C9AFF"/><stop offset="100%" stop-color="#427EEB"/></linearGradient>
      <linearGradient id="swot-w" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#4EE3B5"/><stop offset="100%" stop-color="#22C594"/></linearGradient>
      <linearGradient id="swot-o" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#FFD15B"/><stop offset="100%" stop-color="#F9B300"/></linearGradient>
      <linearGradient id="swot-t" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#FF8A8A"/><stop offset="100%" stop-color="#FC6D6D"/></linearGradient>
    </defs>

    <text x="400" y="45&quo.........完整代码请登录后点击上方下载按钮下载查看

网友评论0