Files
havline-native/app-src/docs/havline-logo-v2-preview.html
T

906 lines
27 KiB
HTML
Raw Normal View History

<!doctype html>
<html lang="zh-CN" data-theme="dark">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="color-scheme" content="dark light">
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3C/svg%3E">
<title>Havline Logo V2 概念预览</title>
<style>
:root {
--page: #06121e;
--panel: #0b1c2b;
--panel-soft: #10283a;
--text: #f2fbfa;
--muted: #8daab6;
--line: rgba(235, 255, 252, 0.13);
--line-strong: rgba(235, 255, 252, 0.24);
--blue: #2fa9ff;
--mint: #63f0d0;
--gold: #ffb15a;
--radius: 8px;
--shadow: 0 22px 70px rgba(0, 0, 0, 0.28);
--font: "Segoe UI", "Microsoft YaHei", "PingFang SC", system-ui, sans-serif;
--mono: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
}
html[data-theme="light"] {
--page: #eef5f6;
--panel: #ffffff;
--panel-soft: #e4f0f1;
--text: #0a2535;
--muted: #58717b;
--line: rgba(10, 37, 53, 0.12);
--line-strong: rgba(10, 37, 53, 0.21);
--shadow: 0 22px 70px rgba(20, 55, 70, 0.13);
}
* {
box-sizing: border-box;
}
body {
margin: 0;
background: var(--page);
color: var(--text);
font-family: var(--font);
line-height: 1.6;
}
button {
cursor: pointer;
font: inherit;
}
.sprite {
position: absolute;
width: 0;
height: 0;
overflow: hidden;
}
.topbar {
position: sticky;
top: 0;
z-index: 5;
display: flex;
align-items: center;
justify-content: space-between;
gap: 18px;
min-height: 70px;
padding: 14px clamp(18px, 4vw, 56px);
background: color-mix(in srgb, var(--page) 92%, transparent);
border-bottom: 1px solid var(--line);
backdrop-filter: blur(18px);
}
.topbar__brand,
.topbar__actions,
.inline-row {
display: flex;
align-items: center;
gap: 12px;
flex-wrap: wrap;
}
.topbar__mark {
width: 34px;
height: 34px;
}
.topbar__title {
display: grid;
line-height: 1.15;
}
.topbar__title strong {
font-size: 17px;
}
.topbar__title span {
color: var(--muted);
font-family: var(--mono);
font-size: 11px;
letter-spacing: 0.12em;
text-transform: uppercase;
}
.control {
min-height: 38px;
padding: 0 14px;
color: var(--text);
background: transparent;
border: 1px solid var(--line-strong);
border-radius: var(--radius);
}
.control:hover,
.control[aria-pressed="true"] {
background: var(--panel-soft);
}
.control--primary {
color: #04131d;
background: linear-gradient(135deg, var(--blue), var(--mint));
border-color: transparent;
font-weight: 700;
}
.wrap {
width: min(1160px, calc(100% - 36px));
margin: 0 auto;
}
.hero {
display: grid;
grid-template-columns: minmax(0, 0.92fr) minmax(380px, 1.08fr);
gap: clamp(28px, 5vw, 72px);
align-items: center;
min-height: calc(100vh - 70px);
padding: 70px 0;
}
.eyebrow {
margin: 0 0 14px;
color: var(--mint);
font-family: var(--mono);
font-size: 12px;
letter-spacing: 0.15em;
text-transform: uppercase;
}
h1,
h2,
h3,
p {
margin-top: 0;
}
h1 {
margin-bottom: 12px;
font-size: clamp(52px, 8vw, 92px);
line-height: 0.94;
letter-spacing: -0.02em;
}
.lead {
margin-bottom: 18px;
font-size: clamp(19px, 2.3vw, 29px);
font-weight: 600;
line-height: 1.28;
}
.copy {
max-width: 620px;
margin-bottom: 22px;
color: var(--muted);
font-size: 15px;
}
.pill {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 7px 10px;
color: var(--mint);
background: color-mix(in srgb, var(--mint) 12%, transparent);
border: 1px solid color-mix(in srgb, var(--mint) 28%, transparent);
border-radius: 999px;
font-family: var(--mono);
font-size: 11px;
letter-spacing: 0.08em;
}
.stage {
position: relative;
display: grid;
place-items: center;
min-height: 560px;
padding: 48px;
overflow: hidden;
background:
linear-gradient(to right, color-mix(in srgb, var(--line) 62%, transparent) 1px, transparent 1px) 0 0 / 36px 36px,
linear-gradient(to bottom, color-mix(in srgb, var(--line) 62%, transparent) 1px, transparent 1px) 0 0 / 36px 36px,
color-mix(in srgb, var(--panel) 95%, #071a29);
border: 1px solid var(--line);
border-radius: var(--radius);
box-shadow: var(--shadow);
}
.stage::after {
content: "";
position: absolute;
inset: 18px;
border: 1px solid color-mix(in srgb, var(--mint) 17%, transparent);
border-radius: var(--radius);
pointer-events: none;
}
.hero-lockup {
position: relative;
z-index: 1;
width: min(100%, 570px);
color: var(--text);
}
.section {
padding: 82px 0;
border-top: 1px solid var(--line);
}
.section__head {
display: grid;
grid-template-columns: minmax(0, 0.7fr) minmax(0, 1.3fr);
gap: 28px;
margin-bottom: 30px;
}
.section__head h2 {
margin-bottom: 0;
font-size: clamp(27px, 4vw, 44px);
line-height: 1.08;
}
.section__head p {
max-width: 680px;
margin-bottom: 0;
color: var(--muted);
}
.fix-grid,
.concept-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 16px;
}
.fix-card,
.concept-card,
.preview-card {
background: var(--panel);
border: 1px solid var(--line);
border-radius: var(--radius);
}
.fix-card {
min-height: 200px;
padding: 22px;
}
.fix-card__index {
display: block;
margin-bottom: 42px;
color: var(--mint);
font-family: var(--mono);
font-size: 12px;
letter-spacing: 0.12em;
}
.fix-card h3 {
margin-bottom: 8px;
font-size: 17px;
}
.fix-card p {
margin-bottom: 0;
color: var(--muted);
font-size: 14px;
}
.compare {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
gap: 16px;
}
.compare-card {
display: grid;
place-items: center;
min-height: 360px;
padding: 34px;
background: #f4fbfb;
border: 1px solid rgba(7, 34, 50, 0.12);
border-radius: var(--radius);
color: #092638;
}
.compare-card--dark {
color: var(--text);
background: #071a29;
border-color: var(--line);
}
.compare-card__label {
align-self: end;
margin-top: 22px;
color: inherit;
font-family: var(--mono);
font-size: 11px;
letter-spacing: 0.1em;
opacity: 0.62;
text-transform: uppercase;
}
.mark-large {
width: min(100%, 190px);
height: auto;
}
.concept-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.concept-card {
display: grid;
place-items: center;
min-height: 340px;
padding: 30px;
}
.concept-card__mark {
width: 140px;
height: 140px;
}
.concept-card__copy {
align-self: end;
margin-top: 22px;
text-align: center;
}
.concept-card__copy h3 {
margin-bottom: 5px;
font-size: 17px;
}
.concept-card__copy p {
margin-bottom: 0;
color: var(--muted);
font-size: 14px;
}
.concept-card--recommended {
border-color: color-mix(in srgb, var(--mint) 42%, transparent);
box-shadow: 0 0 0 1px color-mix(in srgb, var(--mint) 12%, transparent);
}
.sidebar-preview {
display: grid;
grid-template-columns: 300px minmax(0, 1fr);
gap: 16px;
}
.sidebar-card {
width: 300px;
padding: 18px 0;
color: #0b2735;
background: #ffffff;
border: 1px solid rgba(12, 43, 58, 0.13);
border-radius: var(--radius);
box-shadow: var(--shadow);
}
.sidebar-brand {
display: flex;
align-items: center;
gap: 12px;
padding: 0 18px 18px;
border-bottom: 1px solid rgba(12, 43, 58, 0.1);
}
.sidebar-brand__mark {
width: 40px;
height: 40px;
flex: 0 0 auto;
}
.sidebar-brand__name {
font-size: 18px;
font-weight: 700;
line-height: 1.2;
}
.sidebar-brand__tagline {
color: #66808b;
font-size: 11px;
line-height: 1.35;
}
.sidebar-item {
display: flex;
align-items: center;
gap: 12px;
margin: 10px 12px 0;
padding: 10px 14px;
color: #2a4a57;
font-size: 14px;
border-radius: 8px;
}
.sidebar-item--active {
color: #168f75;
background: #e5f6f1;
font-weight: 600;
}
.sidebar-dot {
width: 17px;
height: 17px;
border: 2px solid currentColor;
border-radius: 5px;
opacity: 0.82;
}
.sidebar-note {
display: grid;
align-content: center;
padding: 34px;
background: var(--panel);
border: 1px solid var(--line);
border-radius: var(--radius);
}
.sidebar-note h3 {
margin-bottom: 8px;
font-size: 21px;
}
.sidebar-note p {
margin-bottom: 0;
color: var(--muted);
}
.size-row {
display: flex;
align-items: end;
gap: 28px;
flex-wrap: wrap;
padding: 34px;
background: var(--panel);
border: 1px solid var(--line);
border-radius: var(--radius);
}
.size-sample {
display: grid;
gap: 10px;
justify-items: center;
color: var(--muted);
font-family: var(--mono);
font-size: 11px;
}
.size-sample svg {
width: var(--size);
height: var(--size);
}
.source {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
gap: 14px;
align-items: start;
padding: 18px;
background: #04101a;
border: 1px solid var(--line);
border-radius: var(--radius);
overflow: hidden;
}
pre {
max-height: 430px;
margin: 0;
overflow: auto;
color: #b9dbe7;
font-family: var(--mono);
font-size: 12px;
line-height: 1.6;
white-space: pre;
}
.footnote {
padding: 34px 0 56px;
color: var(--muted);
font-size: 13px;
}
@media (max-width: 980px) {
.hero,
.section__head,
.sidebar-preview {
grid-template-columns: 1fr;
}
.hero {
min-height: auto;
}
.fix-grid,
.concept-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 650px) {
.topbar {
align-items: flex-start;
flex-direction: column;
}
.topbar__actions {
width: 100%;
}
.control {
flex: 1 1 auto;
}
.stage {
min-height: 390px;
padding: 28px;
}
.fix-grid,
.concept-grid,
.compare {
grid-template-columns: 1fr;
}
.sidebar-card {
width: 100%;
}
.source {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<svg class="sprite" aria-hidden="true" focusable="false">
<defs>
<linearGradient id="v2-bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#0f506d"></stop>
<stop offset="1" stop-color="#061827"></stop>
</linearGradient>
<linearGradient id="v2-ink" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#f6fffd"></stop>
<stop offset="1" stop-color="#c9f5ed"></stop>
</linearGradient>
<linearGradient id="v2-line" x1="0" y1="1" x2="1" y2="0">
<stop offset="0" stop-color="#299cff"></stop>
<stop offset="1" stop-color="#68f3d2"></stop>
</linearGradient>
<symbol id="mark-v2" viewBox="0 0 96 96">
<rect x="4" y="4" width="88" height="88" rx="22" fill="url(#v2-bg)"></rect>
<rect x="4.8" y="4.8" width="86.4" height="86.4" rx="21.2" fill="none" stroke="rgba(242,255,252,.14)" stroke-width="1.6"></rect>
<path d="M17 62C29 52 37 68 47 58C57 48 66 52 79 43" stroke="url(#v2-line)" stroke-width="6.5" fill="none" stroke-linecap="round"></path>
<rect x="28" y="24" width="11" height="48" rx="5.5" fill="url(#v2-ink)"></rect>
<rect x="57" y="24" width="11" height="48" rx="5.5" fill="url(#v2-ink)"></rect>
</symbol>
<symbol id="mark-gate" viewBox="0 0 96 96">
<rect x="4" y="4" width="88" height="88" rx="22" fill="url(#v2-bg)"></rect>
<rect x="4.8" y="4.8" width="86.4" height="86.4" rx="21.2" fill="none" stroke="rgba(242,255,252,.14)" stroke-width="1.6"></rect>
<path d="M40 24C32 24 28 31 28 48C28 65 32 72 40 72" stroke="url(#v2-ink)" stroke-width="10" fill="none" stroke-linecap="round"></path>
<path d="M56 24C64 24 68 31 68 48C68 65 64 72 56 72" stroke="url(#v2-ink)" stroke-width="10" fill="none" stroke-linecap="round"></path>
<path d="M34 59C43 51 54 45 63 37" stroke="url(#v2-line)" stroke-width="7" fill="none" stroke-linecap="round"></path>
</symbol>
<symbol id="mark-lower" viewBox="0 0 96 96">
<rect x="4" y="4" width="88" height="88" rx="22" fill="url(#v2-bg)"></rect>
<rect x="4.8" y="4.8" width="86.4" height="86.4" rx="21.2" fill="none" stroke="rgba(242,255,252,.14)" stroke-width="1.6"></rect>
<path d="M31 23V73" stroke="url(#v2-ink)" stroke-width="11" stroke-linecap="round"></path>
<path d="M31 51C31 36 40 29 50 29C60 29 66 37 66 51V73" stroke="url(#v2-ink)" stroke-width="11" fill="none" stroke-linecap="round"></path>
<circle cx="49" cy="51" r="5" fill="#68f3d2"></circle>
<path d="M39 62C44 55 54 55 58 62" stroke="url(#v2-line)" stroke-width="5" fill="none" stroke-linecap="round"></path>
</symbol>
</defs>
</svg>
<header class="topbar">
<div class="topbar__brand">
<svg class="topbar__mark" viewBox="0 0 96 96" aria-label="Havline V2 标志">
<use href="#mark-v2"></use>
</svg>
<div class="topbar__title">
<strong>Havline V2</strong>
<span>Refined mark / harbor gate</span>
</div>
</div>
<div class="topbar__actions">
<button class="control" type="button" data-theme-set="dark" aria-pressed="true">深海</button>
<button class="control" type="button" data-theme-set="light" aria-pressed="false">白昼</button>
<button class="control control--primary" type="button" id="download-v2">下载 SVG</button>
</div>
</header>
<main>
<section class="wrap hero">
<div>
<p class="eyebrow">Logo evolution / 02</p>
<h1>Havline</h1>
<p class="lead">从“一个 H”变成“一个港湾入口”。</p>
<p class="copy">V2 保留 H 的识别骨架,但不再用两个端点圆点做连接。线路改为从 H 后方穿过的连续波浪,视觉上像一条服务路径穿过港湾入口,也更适合侧栏的小尺寸使用。</p>
<div class="inline-row">
<span class="pill">NO EYES / CONTINUOUS ROUTE</span>
<span class="pill">40PX SIDEBAR SAFE</span>
</div>
</div>
<div class="stage">
<div class="hero-lockup">
<svg viewBox="0 0 560 140" role="img" aria-labelledby="hero-v2-title hero-v2-desc">
<title id="hero-v2-title">Havline V2 横向标志</title>
<desc id="hero-v2-desc">左侧为 Havline V2 标志,右侧为 havline 字体组合。</desc>
<use href="#mark-v2" x="0" y="10" width="120" height="120"></use>
<text x="146" y="67" fill="currentColor" font-family="Segoe UI, Microsoft YaHei, sans-serif" font-size="49" font-weight="700" letter-spacing="0.4">havline</text>
<text x="148" y="94" fill="currentColor" font-family="SFMono-Regular, Consolas, monospace" font-size="12" letter-spacing="1.5" opacity="0.62">SAFE LINE FOR EVERY SERVICE</text>
<line x1="148" y1="110" x2="525" y2="110" stroke="currentColor" stroke-width="1" opacity="0.16"></line>
</svg>
</div>
</div>
</section>
<section class="section">
<div class="wrap">
<div class="section__head">
<h2>这版改了什么</h2>
<p>问题不在 H,而在连接方式。旧版的端点圆点在 40px 侧栏里会形成类似“眼睛”的视觉焦点,抢掉了 H 和线路的主次关系。V2 让线路后退,保留一个干净的入口。</p>
</div>
<div class="fix-grid">
<article class="fix-card">
<span class="fix-card__index">01 / REMOVE</span>
<h3>去掉端点圆点</h3>
<p>不再在左右立柱上放节点,避免小尺寸下像双眼或天线,让 H 的主体轮廓更干净。</p>
</article>
<article class="fix-card">
<span class="fix-card__index">02 / LAYER</span>
<h3>线路退到 H 后方</h3>
<p>波浪线路从双柱背后穿过,只在中间形成连接,保留“服务穿过港湾入口”的叙事。</p>
</article>
<article class="fix-card">
<span class="fix-card__index">03 / FLOW</span>
<h3>改用连续波浪</h3>
<p>斜线改成更平滑的水波路径,既有链路感,也接近港湾与水面意象。</p>
</article>
<article class="fix-card">
<span class="fix-card__index">04 / SIDEBAR</span>
<h3>为 40px 优化</h3>
<p>主结构只保留两根立柱和一条线路,缩放后仍能读出 H,不依赖额外细节。</p>
</article>
</div>
</div>
</section>
<section class="section">
<div class="wrap">
<div class="section__head">
<h2>前后对比</h2>
<p>左侧是上一版,右侧是 V2。对比重点不是“更复杂”,而是让标志在侧栏尺寸下更稳定、更耐看。</p>
</div>
<div class="compare">
<article class="compare-card">
<svg class="mark-large" viewBox="0 0 96 96" aria-label="旧版 Havline 标志">
<rect x="4" y="4" width="88" height="88" rx="22" fill="url(#v2-bg)"></rect>
<rect x="4.8" y="4.8" width="86.4" height="86.4" rx="21.2" fill="none" stroke="rgba(242,255,252,.13)" stroke-width="1.6"></rect>
<path d="M31 25.5V70.5" stroke="#f2fffc" stroke-width="11" stroke-linecap="round"></path>
<path d="M65 25.5V70.5" stroke="#f2fffc" stroke-width="11" stroke-linecap="round"></path>
<path d="M31 59C39 59 42.5 49 49.5 49C56.5 49 57.5 37 65 37" stroke="url(#v2-line)" stroke-width="7" fill="none" stroke-linecap="round" stroke-linejoin="round"></path>
<circle cx="31" cy="59" r="5" fill="#2fa9ff" stroke="#061827" stroke-width="2.2"></circle>
<circle cx="65" cy="37" r="5" fill="#63f0d0" stroke="#061827" stroke-width="2.2"></circle>
</svg>
<span class="compare-card__label">V1 / endpoint nodes</span>
</article>
<article class="compare-card compare-card--dark">
<svg class="mark-large" viewBox="0 0 96 96" aria-label="新版 Havline V2 标志">
<use href="#mark-v2"></use>
</svg>
<span class="compare-card__label">V2 / continuous route</span>
</article>
</div>
</div>
</section>
<section class="section">
<div class="wrap">
<div class="section__head">
<h2>三个方向</h2>
<p>推荐主案是左侧的“连续路线 H”。另外两个方向可以用于周边、活动或后续品牌迭代,不适合直接替代主标志。</p>
</div>
<div class="concept-grid">
<article class="concept-card concept-card--recommended">
<svg class="concept-card__mark" viewBox="0 0 96 96" aria-label="连续路线 H">
<use href="#mark-v2"></use>
</svg>
<div class="concept-card__copy">
<h3>连续路线 H</h3>
<p>推荐主案</p>
</div>
</article>
<article class="concept-card">
<svg class="concept-card__mark" viewBox="0 0 96 96" aria-label="港湾拱门">
<use href="#mark-gate"></use>
</svg>
<div class="concept-card__copy">
<h3>港湾拱门</h3>
<p>更抽象、画面感更强</p>
</div>
</article>
<article class="concept-card">
<svg class="concept-card__mark" viewBox="0 0 96 96" aria-label="小写 h 路线">
<use href="#mark-lower"></use>
</svg>
<div class="concept-card__copy">
<h3>小写 h 路线</h3>
<p>更亲和、更偏产品化</p>
</div>
</article>
</div>
</div>
</section>
<section class="section">
<div class="wrap">
<div class="section__head">
<h2>侧栏模拟</h2>
<p>在当前的 40px 品牌区里,V2 不再出现两个高亮圆点,视觉重心重新回到 H 和品牌名称上。</p>
</div>
<div class="sidebar-preview">
<div class="sidebar-card">
<div class="sidebar-brand">
<svg class="sidebar-brand__mark" viewBox="0 0 96 96" aria-label="Havline V2 侧栏标志">
<use href="#mark-v2"></use>
</svg>
<div>
<div class="sidebar-brand__name">Havline</div>
<div class="sidebar-brand__tagline">让 NAS 访问更简单</div>
</div>
</div>
<div class="sidebar-item sidebar-item--active">
<span class="sidebar-dot"></span>
仪表盘
</div>
<div class="sidebar-item">
<span class="sidebar-dot"></span>
DDNS
</div>
<div class="sidebar-item">
<span class="sidebar-dot"></span>
证书管理
</div>
<div class="sidebar-item">
<span class="sidebar-dot"></span>
反向代理
</div>
</div>
<div class="sidebar-note">
<h3>更像“连接”,不像“表情”</h3>
<p>旧版的两个端点圆点在侧栏压缩后过于醒目。V2 取消了端点节点,把线路收进 H 的结构里,因此远看是一个稳定的入口符号,近看才读到服务路径。</p>
</div>
</div>
</div>
</section>
<section class="section">
<div class="wrap">
<div class="section__head">
<h2>尺寸检查</h2>
<p>主标志建议最小使用 16px。侧栏品牌区 40px,应用图标 64px,登录页主标志 120px 以上。</p>
</div>
<div class="size-row">
<span class="size-sample" style="--size:16px">
<svg viewBox="0 0 96 96"><use href="#mark-v2"></use></svg>
16
</span>
<span class="size-sample" style="--size:24px">
<svg viewBox="0 0 96 96"><use href="#mark-v2"></use></svg>
24
</span>
<span class="size-sample" style="--size:40px">
<svg viewBox="0 0 96 96"><use href="#mark-v2"></use></svg>
40
</span>
<span class="size-sample" style="--size:64px">
<svg viewBox="0 0 96 96"><use href="#mark-v2"></use></svg>
64
</span>
<span class="size-sample" style="--size:96px">
<svg viewBox="0 0 96 96"><use href="#mark-v2"></use></svg>
96
</span>
</div>
</div>
</section>
<section class="section">
<div class="wrap">
<div class="section__head">
<h2>SVG 源文件</h2>
<p>这是 V2 主案的可下载 SVG,后续可以直接替换侧栏中的现有标志,不需要再调整图片尺寸。</p>
</div>
<div class="source">
<pre id="v2-code"></pre>
<div class="inline-row">
<button class="control control--primary" type="button" id="copy-v2">复制 SVG</button>
<button class="control" type="button" id="download-v2-2">下载 SVG</button>
</div>
</div>
</div>
</section>
</main>
<footer class="wrap footnote">
Havline V2 · 主案:连续路线 H · 设计目标:更干净、更有港湾入口感、在 40px 侧栏里不产生“表情”错觉。
</footer>
<script>
const root = document.documentElement;
const themeButtons = document.querySelectorAll("[data-theme-set]");
function setTheme(theme) {
root.dataset.theme = theme;
themeButtons.forEach((button) => {
button.setAttribute("aria-pressed", String(button.dataset.themeSet === theme));
});
}
themeButtons.forEach((button) => {
button.addEventListener("click", () => setTheme(button.dataset.themeSet));
});
const exportSvg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 96" role="img" aria-label="Havline logo v2">
<defs>
<linearGradient id="havline-v2-bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#0f506d"/>
<stop offset="1" stop-color="#061827"/>
</linearGradient>
<linearGradient id="havline-v2-ink" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#f6fffd"/>
<stop offset="1" stop-color="#c9f5ed"/>
</linearGradient>
<linearGradient id="havline-v2-line" x1="0" y1="1" x2="1" y2="0">
<stop offset="0" stop-color="#299cff"/>
<stop offset="1" stop-color="#68f3d2"/>
</linearGradient>
</defs>
<rect x="4" y="4" width="88" height="88" rx="22" fill="url(#havline-v2-bg)"/>
<rect x="4.8" y="4.8" width="86.4" height="86.4" rx="21.2" fill="none" stroke="rgba(242,255,252,.14)" stroke-width="1.6"/>
<path d="M17 62C29 52 37 68 47 58C57 48 66 52 79 43" stroke="url(#havline-v2-line)" stroke-width="6.5" fill="none" stroke-linecap="round"/>
<rect x="28" y="24" width="11" height="48" rx="5.5" fill="url(#havline-v2-ink)"/>
<rect x="57" y="24" width="11" height="48" rx="5.5" fill="url(#havline-v2-ink)"/>
</svg>`;
document.getElementById("v2-code").textContent = exportSvg;
function downloadV2() {
const blob = new Blob([exportSvg], { type: "image/svg+xml;charset=utf-8" });
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = "havline-logo-v2.svg";
document.body.appendChild(link);
link.click();
link.remove();
URL.revokeObjectURL(url);
}
document.getElementById("download-v2").addEventListener("click", downloadV2);
document.getElementById("download-v2-2").addEventListener("click", downloadV2);
document.getElementById("copy-v2").addEventListener("click", async (event) => {
try {
await navigator.clipboard.writeText(exportSvg);
event.currentTarget.textContent = "已复制";
setTimeout(() => {
event.currentTarget.textContent = "复制 SVG";
}, 1400);
} catch {
event.currentTarget.textContent = "复制失败";
setTimeout(() => {
event.currentTarget.textContent = "复制 SVG";
}, 1400);
}
});
</script>
</body>
</html>