sync
50
examples/app_hub/assets/continents-meta.json
Normal file
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"source": "mercator-source.jpg",
|
||||
"size": [
|
||||
800,
|
||||
519
|
||||
],
|
||||
"components": 8,
|
||||
"layers": {
|
||||
"vertical_snapshot": {
|
||||
"translate": [
|
||||
0.0,
|
||||
238.0
|
||||
],
|
||||
"scale": [
|
||||
1.2408477842003853,
|
||||
1.2408477842003853
|
||||
]
|
||||
},
|
||||
"inner": {
|
||||
"translate": [
|
||||
223.66088631984587,
|
||||
238.0
|
||||
],
|
||||
"scale": [
|
||||
1.2408477842003853,
|
||||
1.2408477842003853
|
||||
]
|
||||
},
|
||||
"outer": {
|
||||
"scale": [
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"pivot": [
|
||||
720.0,
|
||||
560.0
|
||||
]
|
||||
},
|
||||
"areas_top10": [
|
||||
78439,
|
||||
42423,
|
||||
21849,
|
||||
5520,
|
||||
5428,
|
||||
3434,
|
||||
546,
|
||||
540
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Extract red land polygons from Mercator reference image -> SVG paths."""
|
||||
"""Extract red land polygons from Mercator reference image -> layered SVG paths."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -14,10 +14,17 @@ from PIL import Image
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
SRC = ROOT / "mercator-source.jpg"
|
||||
OUT_FLAT = ROOT / "hub-logo-continents-mercator-flat.svg"
|
||||
OUT_GLOBE = ROOT / "hub-logo-continents-mercator-globe.svg"
|
||||
OUT_GLOBE_SNAP_VERTICAL = ROOT / "hub-logo-continents-mercator-globe.snapshot-vertical.svg"
|
||||
OUT_META = ROOT / "continents-meta.json"
|
||||
|
||||
# Source image is 800x519 Mercator-style plate.
|
||||
W, H = 800, 519
|
||||
# Globe framing in 1920x1080 logo scene.
|
||||
GLOBE_CX = 720.0
|
||||
GLOBE_CY = 560.0
|
||||
GLOBE_R = 322.0
|
||||
# Orthographic center (visible hemisphere).
|
||||
CENTER_LAT = 18.0
|
||||
CENTER_LON = 12.0
|
||||
|
||||
|
||||
def red_mask(rgb: np.ndarray) -> np.ndarray:
|
||||
@@ -26,7 +33,6 @@ def red_mask(rgb: np.ndarray) -> np.ndarray:
|
||||
|
||||
|
||||
def dilate(mask: np.ndarray, radius: int = 3) -> np.ndarray:
|
||||
"""Bridge thin white grid lines between red land cells."""
|
||||
h, w = mask.shape
|
||||
out = mask.copy()
|
||||
ys, xs = np.where(mask)
|
||||
@@ -61,18 +67,15 @@ def label_components(mask: np.ndarray) -> tuple[np.ndarray, int]:
|
||||
|
||||
|
||||
def trace_boundary(labels: np.ndarray, label_id: int) -> list[tuple[int, int]]:
|
||||
"""Moore-neighbor contour for one connected component."""
|
||||
h, w = labels.shape
|
||||
comp = labels == label_id
|
||||
if not comp.any():
|
||||
return []
|
||||
|
||||
# Start at topmost-leftmost pixel of component.
|
||||
ys, xs = np.where(comp)
|
||||
start = (int(xs[0]), int(ys[0]))
|
||||
x, y = start
|
||||
path = [start]
|
||||
# Directions: E, SE, S, SW, W, NW, N, NE
|
||||
dirs = [(1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -1)]
|
||||
dir_idx = 0
|
||||
|
||||
@@ -123,35 +126,30 @@ def path_d(points: list[tuple[float, float]]) -> str:
|
||||
|
||||
|
||||
def mercator_y_to_lat(y: float, h: float) -> float:
|
||||
# Map top->north, bottom->south; clamp to avoid infinities at poles.
|
||||
t = 1.0 - (y / h)
|
||||
t = min(max(t, 0.02), 0.98)
|
||||
return math.degrees(math.atan(math.sinh(math.pi * (2 * t - 1))))
|
||||
|
||||
|
||||
def lat_lon_to_globe(lat: float, lon: float, cx: float, cy: float, r: float) -> tuple[float, float]:
|
||||
"""Simple orthographic-ish placement on visible globe disk."""
|
||||
def lat_lon_to_globe(lat: float, lon: float) -> tuple[float, float]:
|
||||
lat_r = math.radians(lat)
|
||||
lon_r = math.radians(lon)
|
||||
# Visible hemisphere centered around lon 20, lat 20 for this logo framing.
|
||||
lon0 = math.radians(20.0)
|
||||
lat0 = math.radians(15.0)
|
||||
# Rotate lon relative to center.
|
||||
lon0 = math.radians(CENTER_LON)
|
||||
dlon = lon_r - lon0
|
||||
x = cx + r * math.cos(lat_r) * math.sin(dlon)
|
||||
y = cy - r * math.sin(lat_r)
|
||||
x = GLOBE_CX + GLOBE_R * math.cos(lat_r) * math.sin(dlon)
|
||||
y = GLOBE_CY - GLOBE_R * math.sin(lat_r)
|
||||
return x, y
|
||||
|
||||
|
||||
def map_to_globe(points: list[tuple[int, int]], w: int, h: int) -> list[tuple[float, float]]:
|
||||
out: list[tuple[float, float]] = []
|
||||
cx, cy, r = 720.0, 560.0, 318.0
|
||||
def map_to_globe(points: list[tuple[int, int]], w: int, h: int) -> str:
|
||||
mapped: list[tuple[float, float]] = []
|
||||
for x, y in points:
|
||||
lon = (x / w) * 360.0 - 180.0
|
||||
lat = mercator_y_to_lat(float(y), float(h))
|
||||
gx, gy = lat_lon_to_globe(lat, lon, cx, cy, r)
|
||||
out.append((gx, gy))
|
||||
return out
|
||||
mapped.append(lat_lon_to_globe(lat, lon))
|
||||
if len(mapped) < 3:
|
||||
return ""
|
||||
return path_d(mapped)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
@@ -164,31 +162,34 @@ def main() -> None:
|
||||
components: list[dict] = []
|
||||
for label_id in range(1, n + 1):
|
||||
area = int((labels == label_id).sum())
|
||||
if area < 500: # drop tiny noise / watermark specks
|
||||
if area < 500:
|
||||
continue
|
||||
boundary = trace_boundary(labels, label_id)
|
||||
if len(boundary) < 20:
|
||||
continue
|
||||
boundary = simplify(boundary, min_dist=3.5)
|
||||
flat = path_d([(float(x), float(y)) for x, y in boundary])
|
||||
globe = map_to_globe(boundary, w, h)
|
||||
if not flat:
|
||||
continue
|
||||
ys, xs = np.where(labels == label_id)
|
||||
bbox = [int(xs.min()), int(ys.min()), int(xs.max()), int(ys.max())]
|
||||
components.append(
|
||||
{
|
||||
"id": label_id,
|
||||
"area": area,
|
||||
"bbox": bbox,
|
||||
"flat": path_d([(float(x), float(y)) for x, y in boundary]),
|
||||
"globe": path_d(map_to_globe(boundary, w, h)),
|
||||
"bbox": [int(xs.min()), int(ys.min()), int(xs.max()), int(ys.max())],
|
||||
"flat": flat,
|
||||
"globe": globe,
|
||||
}
|
||||
)
|
||||
|
||||
components.sort(key=lambda c: c["area"], reverse=True)
|
||||
|
||||
flat_paths = "\n ".join(
|
||||
flat_paths = "\n ".join(
|
||||
f'<path id="continent-{c["id"]}" data-area="{c["area"]}" d="{c["flat"]}"/>'
|
||||
for c in components
|
||||
)
|
||||
globe_paths = "\n ".join(
|
||||
globe_paths = "\n ".join(
|
||||
f'<path id="continent-{c["id"]}" data-area="{c["area"]}" d="{c["globe"]}"/>'
|
||||
for c in components
|
||||
)
|
||||
@@ -196,7 +197,7 @@ def main() -> None:
|
||||
OUT_FLAT.write_text(
|
||||
f"""<svg xmlns="http://www.w3.org/2000/svg" width="{w}" height="{h}" viewBox="0 0 {w} {h}" role="img" aria-label="Extracted continents (flat Mercator plate)">
|
||||
<rect width="100%" height="100%" fill="#b8d4e8"/>
|
||||
<g id="continents-extracted" fill="#c41e1a" fill-opacity="0.92" stroke="#8f1410" stroke-width="0.8">
|
||||
<g id="continents-inner-layer" fill="#9ab3cc" fill-opacity="0.82" stroke="#dce8f6" stroke-opacity="0.78" stroke-width="1.1">
|
||||
{flat_paths}
|
||||
</g>
|
||||
</svg>
|
||||
@@ -204,17 +205,73 @@ def main() -> None:
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
globe_svg = ROOT.parent.parent / "examples" / "app_hub" / "assets" / "hub-logo-continents-mercator-globe.svg"
|
||||
globe_svg.write_text(
|
||||
f"""<svg xmlns="http://www.w3.org/2000/svg" width="1920" height="1080" viewBox="0 0 1920 1080" preserveAspectRatio="xMidYMid slice" role="img" aria-label="Extracted continents mapped to globe viewBox">
|
||||
# Two-step alignment:
|
||||
# 1) Vertical fit: Mercator north/south poles match globe top/bottom.
|
||||
# 2) Horizontal fit: layer centers/pivots match at globe center.
|
||||
globe_diameter = GLOBE_R * 2
|
||||
inner_sy = globe_diameter / h
|
||||
inner_sx = inner_sy
|
||||
inner_ty = GLOBE_CY - GLOBE_R
|
||||
inner_tx_vertical = 0.0
|
||||
inner_tx = GLOBE_CX - (w * inner_sx) / 2
|
||||
outer_sx = 1.0
|
||||
outer_sy = 1.0
|
||||
|
||||
def globe_svg(
|
||||
inner_tx_val: float,
|
||||
inner_ty_val: float,
|
||||
inner_sx_val: float,
|
||||
inner_sy_val: float,
|
||||
outer_sx_val: float,
|
||||
outer_sy_val: float,
|
||||
label: str,
|
||||
) -> str:
|
||||
return f"""<svg xmlns="http://www.w3.org/2000/svg" width="1920" height="1080" viewBox="0 0 1920 1080" preserveAspectRatio="xMidYMid slice" role="img" aria-label="{label}">
|
||||
<defs>
|
||||
<clipPath id="globeClip"><circle cx="720" cy="560" r="322"/></clipPath>
|
||||
<clipPath id="globeClip"><circle cx="{GLOBE_CX:.0f}" cy="{GLOBE_CY:.0f}" r="{GLOBE_R:.0f}"/></clipPath>
|
||||
<radialGradient id="continentRelief" cx="34%" cy="22%" r="78%">
|
||||
<stop offset="0%" stop-color="#dbe7f6" stop-opacity="0.45"/>
|
||||
<stop offset="58%" stop-color="#9ab3cc" stop-opacity="0.22"/>
|
||||
<stop offset="100%" stop-color="#6a7f97" stop-opacity="0.18"/>
|
||||
</radialGradient>
|
||||
<filter id="continentDepth" x="-30%" y="-30%" width="160%" height="160%">
|
||||
<feDropShadow dx="-4" dy="-6" stdDeviation="3" flood-color="#f4fbff" flood-opacity="0.2"/>
|
||||
<feDropShadow dx="4" dy="6" stdDeviation="4" flood-color="#0a1220" flood-opacity="0.28"/>
|
||||
</filter>
|
||||
</defs>
|
||||
<g id="continents-globe" clip-path="url(#globeClip)" fill="#7287a1" fill-opacity="0.88" stroke="#a8b8cc" stroke-opacity="0.45" stroke-width="1">
|
||||
{globe_paths}
|
||||
<g id="continents-outer-layer" clip-path="url(#globeClip)" transform="translate({GLOBE_CX:.0f} {GLOBE_CY:.0f}) scale({outer_sx_val:.3f} {outer_sy_val:.3f}) translate(-{GLOBE_CX:.0f} -{GLOBE_CY:.0f})">
|
||||
<g id="continents-inner-layer" transform="translate({inner_tx_val:.2f} {inner_ty_val:.2f}) scale({inner_sx_val:.4f} {inner_sy_val:.4f})">
|
||||
<g id="continents-flat" fill="url(#continentRelief)" fill-opacity="0.9" stroke="#dce8f6" stroke-opacity="0.78" stroke-width="1.2" filter="url(#continentDepth)">
|
||||
{flat_paths}
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
""",
|
||||
"""
|
||||
|
||||
OUT_GLOBE_SNAP_VERTICAL.write_text(
|
||||
globe_svg(
|
||||
inner_tx_vertical,
|
||||
inner_ty,
|
||||
inner_sx,
|
||||
inner_sy,
|
||||
outer_sx,
|
||||
outer_sy,
|
||||
"Continents vertical-fit snapshot",
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
OUT_GLOBE.write_text(
|
||||
globe_svg(
|
||||
inner_tx,
|
||||
inner_ty,
|
||||
inner_sx,
|
||||
inner_sy,
|
||||
outer_sx,
|
||||
outer_sy,
|
||||
"Continents layered Mercator overlay",
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
@@ -224,6 +281,15 @@ def main() -> None:
|
||||
"source": str(SRC.name),
|
||||
"size": [w, h],
|
||||
"components": len(components),
|
||||
"layers": {
|
||||
"vertical_snapshot": {
|
||||
"translate": [inner_tx_vertical, inner_ty],
|
||||
"scale": [inner_sx, inner_sy],
|
||||
},
|
||||
"inner": {"translate": [inner_tx, inner_ty], "scale": [inner_sx, inner_sy]},
|
||||
"outer": {"scale": [outer_sx, outer_sy]},
|
||||
"pivot": [GLOBE_CX, GLOBE_CY],
|
||||
},
|
||||
"areas_top10": [c["area"] for c in components[:10]],
|
||||
},
|
||||
indent=2,
|
||||
@@ -233,7 +299,7 @@ def main() -> None:
|
||||
|
||||
print(f"components={len(components)}")
|
||||
print(f"wrote {OUT_FLAT}")
|
||||
print(f"wrote {globe_svg}")
|
||||
print(f"wrote {OUT_GLOBE}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
14
examples/app_hub/assets/hub-logo-fragment-compass.svg
Normal file
@@ -0,0 +1,14 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1920" height="1080" viewBox="0 0 1920 1080" preserveAspectRatio="xMidYMid slice" role="img" aria-label="Compass layer">
|
||||
<g id="globe-compass" transform="translate(1050 820)">
|
||||
<circle cx="0" cy="0" r="52" fill="#0a0e14" fill-opacity="0.42" stroke="#c7d3e1" stroke-opacity="0.52" stroke-width="2"/>
|
||||
<circle cx="0" cy="0" r="40" fill="none" stroke="#dbe5f1" stroke-opacity="0.64" stroke-width="1.5"/>
|
||||
<path d="M 0 -38 L 9 0 L 0 38 L -9 0 Z" fill="#e7ecf3" fill-opacity="0.9"/>
|
||||
<path d="M -38 0 L 0 -9 L 38 0 L 0 9 Z" fill="#8ea1b9" fill-opacity="0.86"/>
|
||||
<path d="M 0 -28 L 6 0 L 0 28 L -6 0 Z" fill="#223246" fill-opacity="0.9"/>
|
||||
<circle cx="0" cy="0" r="4.2" fill="#e7ecf3" fill-opacity="0.92"/>
|
||||
<text x="0" y="-56" text-anchor="middle" fill="#e7ecf3" fill-opacity="0.72" font-size="12" font-family="Segoe UI, sans-serif">N</text>
|
||||
<text x="0" y="68" text-anchor="middle" fill="#a9bbce" fill-opacity="0.68" font-size="12" font-family="Segoe UI, sans-serif">S</text>
|
||||
<text x="-66" y="4" text-anchor="middle" fill="#a9bbce" fill-opacity="0.68" font-size="12" font-family="Segoe UI, sans-serif">W</text>
|
||||
<text x="66" y="4" text-anchor="middle" fill="#a9bbce" fill-opacity="0.68" font-size="12" font-family="Segoe UI, sans-serif">E</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -31,18 +31,4 @@
|
||||
<ellipse id="globe-south-pole" cx="720" cy="728" rx="260" ry="39" stroke="url(#gradSouthPole)" stroke-width="7.5"/>
|
||||
</g>
|
||||
|
||||
<g id="globe-compass" transform="translate(1050 820)">
|
||||
<circle cx="0" cy="0" r="52" fill="#0a0e14" fill-opacity="0.42" stroke="#c7d3e1" stroke-opacity="0.52" stroke-width="2"/>
|
||||
<circle cx="0" cy="0" r="40" fill="none" stroke="#dbe5f1" stroke-opacity="0.64" stroke-width="1.5"/>
|
||||
<path d="M 0 -38 L 9 0 L 0 38 L -9 0 Z" fill="#e7ecf3" fill-opacity="0.9"/>
|
||||
<path d="M -38 0 L 0 -9 L 38 0 L 0 9 Z" fill="#8ea1b9" fill-opacity="0.86"/>
|
||||
<path d="M 0 -28 L 6 0 L 0 28 L -6 0 Z" fill="#223246" fill-opacity="0.9"/>
|
||||
<circle cx="0" cy="0" r="4.2" fill="#e7ecf3" fill-opacity="0.92"/>
|
||||
<text x="0" y="-56" text-anchor="middle" fill="#e7ecf3" fill-opacity="0.72" font-size="12" font-family="Segoe UI, sans-serif">N</text>
|
||||
<text x="0" y="68" text-anchor="middle" fill="#a9bbce" fill-opacity="0.68" font-size="12" font-family="Segoe UI, sans-serif">S</text>
|
||||
<text x="-66" y="4" text-anchor="middle" fill="#a9bbce" fill-opacity="0.68" font-size="12" font-family="Segoe UI, sans-serif">W</text>
|
||||
<text x="66" y="4" text-anchor="middle" fill="#a9bbce" fill-opacity="0.68" font-size="12" font-family="Segoe UI, sans-serif">E</text>
|
||||
</g>
|
||||
|
||||
<circle id="globe-border" cx="720" cy="560" r="330" fill="none" stroke="#e7ecf3" stroke-width="15"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 2.4 KiB |
@@ -27,6 +27,14 @@
|
||||
<stop offset="52%" stop-color="#d7e0ec" stop-opacity="0.78"/>
|
||||
<stop offset="100%" stop-color="#4f6178" stop-opacity="0.92"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="sunRim" x1="390" y1="560" x2="1050" y2="560" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0%" stop-color="#f5f8ff" stop-opacity="0.98"/>
|
||||
<stop offset="38%" stop-color="#dce7f5" stop-opacity="0.82"/>
|
||||
<stop offset="100%" stop-color="#4a5c72" stop-opacity="0.7"/>
|
||||
</linearGradient>
|
||||
<filter id="sunRimGlow" x="-20%" y="-20%" width="140%" height="140%">
|
||||
<feGaussianBlur stdDeviation="3.2"/>
|
||||
</filter>
|
||||
|
||||
<clipPath id="gridClip"><circle cx="720" cy="560" r="322"/></clipPath>
|
||||
</defs>
|
||||
@@ -45,18 +53,6 @@
|
||||
<ellipse id="globe-south-pole" cx="720" cy="728" rx="260" ry="39" stroke="url(#gradSouthPole)" stroke-width="7.5"/>
|
||||
</g>
|
||||
|
||||
<g id="globe-compass" transform="translate(1050 820)">
|
||||
<circle cx="0" cy="0" r="52" fill="#0a0e14" fill-opacity="0.42" stroke="#c7d3e1" stroke-opacity="0.52" stroke-width="2"/>
|
||||
<circle cx="0" cy="0" r="40" fill="none" stroke="#dbe5f1" stroke-opacity="0.64" stroke-width="1.5"/>
|
||||
<path d="M 0 -38 L 9 0 L 0 38 L -9 0 Z" fill="#e7ecf3" fill-opacity="0.9"/>
|
||||
<path d="M -38 0 L 0 -9 L 38 0 L 0 9 Z" fill="#8ea1b9" fill-opacity="0.86"/>
|
||||
<path d="M 0 -28 L 6 0 L 0 28 L -6 0 Z" fill="#223246" fill-opacity="0.9"/>
|
||||
<circle cx="0" cy="0" r="4.2" fill="#e7ecf3" fill-opacity="0.92"/>
|
||||
<text x="0" y="-56" text-anchor="middle" fill="#e7ecf3" fill-opacity="0.72" font-size="12" font-family="Segoe UI, sans-serif">N</text>
|
||||
<text x="0" y="68" text-anchor="middle" fill="#a9bbce" fill-opacity="0.68" font-size="12" font-family="Segoe UI, sans-serif">S</text>
|
||||
<text x="-66" y="4" text-anchor="middle" fill="#a9bbce" fill-opacity="0.68" font-size="12" font-family="Segoe UI, sans-serif">W</text>
|
||||
<text x="66" y="4" text-anchor="middle" fill="#a9bbce" fill-opacity="0.68" font-size="12" font-family="Segoe UI, sans-serif">E</text>
|
||||
</g>
|
||||
|
||||
<circle id="globe-border" cx="720" cy="560" r="330" fill="none" stroke="#e7ecf3" stroke-width="15"/>
|
||||
<circle id="globe-border-glow" cx="720" cy="560" r="330" fill="none" stroke="url(#sunRim)" stroke-opacity="0.75" stroke-width="20" filter="url(#sunRimGlow)"/>
|
||||
<circle id="globe-border" cx="720" cy="560" r="330" fill="none" stroke="url(#sunRim)" stroke-width="14"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 3.5 KiB |
@@ -1,22 +1,14 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="340" height="46" viewBox="0 0 340 46" role="img" aria-label="Thunder schematic underline">
|
||||
<defs>
|
||||
<linearGradient id="thunderCore" x1="0%" y1="50%" x2="100%" y2="50%">
|
||||
<stop offset="0%" stop-color="#7dd3fc" stop-opacity="0.15"/>
|
||||
<stop offset="15%" stop-color="#bae6fd" stop-opacity="0.95"/>
|
||||
<stop offset="48%" stop-color="#ffffff" stop-opacity="1"/>
|
||||
<stop offset="82%" stop-color="#bae6fd" stop-opacity="0.95"/>
|
||||
<stop offset="100%" stop-color="#7dd3fc" stop-opacity="0.15"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="thunderEdge" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" stop-color="#9ddcff" stop-opacity="0"/>
|
||||
<stop offset="24%" stop-color="#9ddcff" stop-opacity="0.8"/>
|
||||
<stop offset="76%" stop-color="#9ddcff" stop-opacity="0.8"/>
|
||||
<stop offset="100%" stop-color="#9ddcff" stop-opacity="0"/>
|
||||
<linearGradient id="thunderFill" x1="0%" y1="50%" x2="100%" y2="50%">
|
||||
<stop offset="0%" stop-color="#8ecfff" stop-opacity="0.22"/>
|
||||
<stop offset="18%" stop-color="#c9ecff" stop-opacity="0.98"/>
|
||||
<stop offset="50%" stop-color="#ffffff" stop-opacity="1"/>
|
||||
<stop offset="82%" stop-color="#c9ecff" stop-opacity="0.98"/>
|
||||
<stop offset="100%" stop-color="#8ecfff" stop-opacity="0.22"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<path d="M 12 24 L 86 24 L 98 16 L 126 31 L 154 13 L 178 28 L 210 11 L 236 27 L 262 17 L 286 25 L 328 25"
|
||||
fill="none" stroke="url(#thunderCore)" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M 12 24 L 86 24 L 98 16 L 126 31 L 154 13 L 178 28 L 210 11 L 236 27 L 262 17 L 286 25 L 328 25"
|
||||
fill="none" stroke="url(#thunderEdge)" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M 10 9 L 196 9" fill="none" stroke="url(#thunderFill)" stroke-width="5.5" stroke-linecap="round"/>
|
||||
<path d="M 196 9 L 248 31" fill="none" stroke="url(#thunderFill)" stroke-width="5.5" stroke-linecap="round"/>
|
||||
<path d="M 248 31 L 330 31" fill="none" stroke="url(#thunderFill)" stroke-width="5.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 932 B |
7
examples/app_hub/assets/hub-widget-resize-arrow.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 45.279 45.279" aria-hidden="true">
|
||||
<symbol id="resizeArrow" viewBox="0 0 45.279 45.279">
|
||||
<path d="M44.106,42.943H3.987L44.933,1.995c0.456-0.455,0.456-1.196,0-1.651c-0.452-0.455-1.195-0.455-1.651,0L2.336,41.292V1.168
|
||||
C2.336,0.524,1.81,0,1.168,0C0.523,0,0,0.524,0,1.168v44.111h44.111c0.644,0,1.168-0.522,1.168-1.168
|
||||
C45.279,43.469,44.755,42.943,44.106,42.943z"/>
|
||||
</symbol>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 451 B |
22
examples/app_hub/assets/overtime-01-alphabet.svg
Normal file
@@ -0,0 +1,22 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" style="position:absolute;width:0;height:0;overflow:hidden">
|
||||
<!-- Overtime 01 alphabet: 7-segment LCD glyphs for hub primary clock -->
|
||||
<defs>
|
||||
<symbol id="ot-0" viewBox="0 0 20 32"><rect x="3" y="1" width="14" height="3" rx="1"/><rect x="16" y="4" width="3" height="11" rx="1"/><rect x="16" y="17" width="3" height="11" rx="1"/><rect x="3" y="28" width="14" height="3" rx="1"/><rect x="1" y="17" width="3" height="11" rx="1"/><rect x="1" y="4" width="3" height="11" rx="1"/></symbol>
|
||||
<symbol id="ot-1" viewBox="0 0 20 32"><rect x="16" y="4" width="3" height="11" rx="1"/><rect x="16" y="17" width="3" height="11" rx="1"/></symbol>
|
||||
<symbol id="ot-2" viewBox="0 0 20 32"><rect x="3" y="1" width="14" height="3" rx="1"/><rect x="16" y="4" width="3" height="11" rx="1"/><rect x="3" y="15" width="14" height="3" rx="1"/><rect x="1" y="17" width="3" height="11" rx="1"/><rect x="3" y="28" width="14" height="3" rx="1"/></symbol>
|
||||
<symbol id="ot-3" viewBox="0 0 20 32"><rect x="3" y="1" width="14" height="3" rx="1"/><rect x="16" y="4" width="3" height="11" rx="1"/><rect x="3" y="15" width="14" height="3" rx="1"/><rect x="16" y="17" width="3" height="11" rx="1"/><rect x="3" y="28" width="14" height="3" rx="1"/></symbol>
|
||||
<symbol id="ot-4" viewBox="0 0 20 32"><rect x="1" y="4" width="3" height="11" rx="1"/><rect x="3" y="15" width="14" height="3" rx="1"/><rect x="16" y="4" width="3" height="11" rx="1"/><rect x="16" y="17" width="3" height="11" rx="1"/></symbol>
|
||||
<symbol id="ot-5" viewBox="0 0 20 32"><rect x="3" y="1" width="14" height="3" rx="1"/><rect x="1" y="4" width="3" height="11" rx="1"/><rect x="3" y="15" width="14" height="3" rx="1"/><rect x="16" y="17" width="3" height="11" rx="1"/><rect x="3" y="28" width="14" height="3" rx="1"/></symbol>
|
||||
<symbol id="ot-6" viewBox="0 0 20 32"><rect x="3" y="1" width="14" height="3" rx="1"/><rect x="1" y="4" width="3" height="11" rx="1"/><rect x="3" y="15" width="14" height="3" rx="1"/><rect x="1" y="17" width="3" height="11" rx="1"/><rect x="16" y="17" width="3" height="11" rx="1"/><rect x="3" y="28" width="14" height="3" rx="1"/></symbol>
|
||||
<symbol id="ot-7" viewBox="0 0 20 32"><rect x="3" y="1" width="14" height="3" rx="1"/><rect x="16" y="4" width="3" height="11" rx="1"/><rect x="16" y="17" width="3" height="11" rx="1"/></symbol>
|
||||
<symbol id="ot-8" viewBox="0 0 20 32"><rect x="3" y="1" width="14" height="3" rx="1"/><rect x="1" y="4" width="3" height="11" rx="1"/><rect x="16" y="4" width="3" height="11" rx="1"/><rect x="3" y="15" width="14" height="3" rx="1"/><rect x="1" y="17" width="3" height="11" rx="1"/><rect x="16" y="17" width="3" height="11" rx="1"/><rect x="3" y="28" width="14" height="3" rx="1"/></symbol>
|
||||
<symbol id="ot-9" viewBox="0 0 20 32"><rect x="3" y="1" width="14" height="3" rx="1"/><rect x="1" y="4" width="3" height="11" rx="1"/><rect x="3" y="15" width="14" height="3" rx="1"/><rect x="16" y="4" width="3" height="11" rx="1"/><rect x="16" y="17" width="3" height="11" rx="1"/><rect x="3" y="28" width="14" height="3" rx="1"/></symbol>
|
||||
<symbol id="ot-colon" viewBox="0 0 12 32"><rect x="4" y="10" width="4" height="4" rx="1"/><rect x="4" y="20" width="4" height="4" rx="1"/></symbol>
|
||||
<symbol id="ot-plus" viewBox="0 0 16 32"><rect x="6" y="8" width="4" height="16" rx="1"/><rect x="2" y="14" width="12" height="4" rx="1"/></symbol>
|
||||
<symbol id="ot-minus" viewBox="0 0 16 32"><rect x="2" y="14" width="12" height="4" rx="1"/></symbol>
|
||||
<symbol id="ot-space" viewBox="0 0 8 32"></symbol>
|
||||
<symbol id="ot-G" viewBox="0 0 20 32"><rect x="3" y="1" width="14" height="3" rx="1"/><rect x="1" y="4" width="3" height="11" rx="1"/><rect x="1" y="17" width="3" height="11" rx="1"/><rect x="3" y="28" width="14" height="3" rx="1"/><rect x="16" y="17" width="3" height="11" rx="1"/><rect x="10" y="15" width="9" height="3" rx="1"/></symbol>
|
||||
<symbol id="ot-M" viewBox="0 0 24 32"><rect x="1" y="4" width="3" height="24" rx="1"/><rect x="20" y="4" width="3" height="24" rx="1"/><rect x="7.1" y="5" width="2.6" height="13.2" rx="1" transform="rotate(28 8.4 11.6)"/><rect x="14.3" y="5" width="2.6" height="13.2" rx="1" transform="rotate(-28 15.6 11.6)"/></symbol>
|
||||
<symbol id="ot-T" viewBox="0 0 20 32"><rect x="3" y="1" width="14" height="3" rx="1"/><rect x="8" y="4" width="4" height="24" rx="1"/></symbol>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.3 KiB |