Skip to content

Commit 82d433f

Browse files
committed
jsbin sample
1 parent bc54e18 commit 82d433f

1 file changed

Lines changed: 184 additions & 0 deletions

File tree

jsbin-div-to-png-example.html

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6+
<title>layout2vector JSBin Demo</title>
7+
<style>
8+
:root {
9+
--bg: #f3f6fb;
10+
--card: #ffffff;
11+
--ink: #1b2333;
12+
--accent: #0f7cda;
13+
--muted: #6a7487;
14+
}
15+
16+
body {
17+
margin: 0;
18+
font-family: "Segoe UI", "Helvetica Neue", sans-serif;
19+
color: var(--ink);
20+
background: radial-gradient(circle at top right, #d9ebff 0%, var(--bg) 55%);
21+
}
22+
23+
.page {
24+
max-width: 920px;
25+
margin: 24px auto;
26+
padding: 0 16px;
27+
display: grid;
28+
gap: 16px;
29+
}
30+
31+
.panel {
32+
background: var(--card);
33+
border: 1px solid #dbe2ef;
34+
border-radius: 14px;
35+
padding: 16px;
36+
box-shadow: 0 8px 28px rgba(20, 34, 66, 0.08);
37+
}
38+
39+
h1 {
40+
margin: 0 0 10px;
41+
font-size: 22px;
42+
}
43+
44+
p {
45+
margin: 0;
46+
color: var(--muted);
47+
}
48+
49+
#capture {
50+
margin-top: 16px;
51+
width: min(620px, 100%);
52+
min-height: 180px;
53+
border-radius: 20px;
54+
padding: 18px;
55+
color: #0a1b2e;
56+
background:
57+
linear-gradient(135deg, rgba(255, 255, 255, 0.9), rgba(221, 236, 255, 0.95)),
58+
repeating-linear-gradient(-45deg, rgba(15, 124, 218, 0.08), rgba(15, 124, 218, 0.08) 12px, rgba(15, 124, 218, 0.02) 12px, rgba(15, 124, 218, 0.02) 24px);
59+
border: 2px solid rgba(15, 124, 218, 0.22);
60+
}
61+
62+
#capture h2 {
63+
margin: 0;
64+
font-size: 26px;
65+
}
66+
67+
#capture .badge {
68+
display: inline-block;
69+
margin-top: 10px;
70+
padding: 6px 10px;
71+
border-radius: 999px;
72+
background: #0f7cda;
73+
color: white;
74+
font-size: 12px;
75+
letter-spacing: 0.06em;
76+
text-transform: uppercase;
77+
}
78+
79+
#capture .note {
80+
margin-top: 10px;
81+
font-size: 15px;
82+
}
83+
84+
.controls {
85+
margin-top: 14px;
86+
display: flex;
87+
flex-wrap: wrap;
88+
gap: 10px;
89+
}
90+
91+
button {
92+
border: 0;
93+
border-radius: 10px;
94+
background: var(--accent);
95+
color: white;
96+
padding: 10px 14px;
97+
font-weight: 600;
98+
cursor: pointer;
99+
}
100+
101+
button:hover {
102+
filter: brightness(1.08);
103+
}
104+
105+
#status {
106+
margin-top: 10px;
107+
min-height: 1.3em;
108+
font-size: 14px;
109+
color: #274060;
110+
}
111+
112+
#result {
113+
margin-top: 16px;
114+
max-width: 100%;
115+
border-radius: 12px;
116+
border: 1px solid #cfd9ea;
117+
}
118+
</style>
119+
</head>
120+
<body>
121+
<div class="page">
122+
<div class="panel">
123+
<h1>Div to PNG using @node-projects/layout2vector</h1>
124+
<p>
125+
This demo initializes getBoxQuads polyfill first (for Chromium), then extracts
126+
the target div and renders it to a PNG data URL.
127+
</p>
128+
129+
<div id="capture">
130+
<h2>Hello JSBin</h2>
131+
<span class="badge">layout2vector</span>
132+
<p class="note">Export this card as PNG with gradients, text, and rounded corners.</p>
133+
</div>
134+
135+
<div class="controls">
136+
<button id="convertBtn" type="button">Convert #capture to PNG</button>
137+
</div>
138+
<div id="status"></div>
139+
<img id="result" alt="Generated PNG preview" />
140+
</div>
141+
</div>
142+
143+
<script type="module">
144+
import { addPolyfill } from "https://esm.sh/get-box-quads-polyfill@4";
145+
import { extractIR, renderIR, ImageWriter } from "https://esm.sh/@node-projects/layout2vector@5";
146+
147+
// Required in Chromium where getBoxQuads is missing.
148+
addPolyfill(window);
149+
150+
const convertBtn = document.getElementById("convertBtn");
151+
const capture = document.getElementById("capture");
152+
const status = document.getElementById("status");
153+
const result = document.getElementById("result");
154+
155+
convertBtn.addEventListener("click", async () => {
156+
status.textContent = "Converting...";
157+
158+
try {
159+
const bounds = capture.getBoundingClientRect();
160+
const ir = await extractIR(capture, {
161+
includeText: true,
162+
includeImages: true,
163+
});
164+
165+
const writer = new ImageWriter({
166+
width: Math.max(1, Math.ceil(bounds.width)),
167+
height: Math.max(1, Math.ceil(bounds.height)),
168+
scale: Math.min(window.devicePixelRatio || 1, 2),
169+
});
170+
171+
const pngResult = await renderIR(ir, writer);
172+
await pngResult.finalize();
173+
174+
const dataUrl = pngResult.toDataURL("image/png");
175+
result.src = dataUrl;
176+
status.textContent = "Done. PNG generated below.";
177+
} catch (error) {
178+
console.error(error);
179+
status.textContent = `Conversion failed: ${error?.message || error}`;
180+
}
181+
});
182+
</script>
183+
</body>
184+
</html>

0 commit comments

Comments
 (0)