分享身边的点滴趣事
回复
头像
ejsoon
一枝独秀
帖子: 6360
注册时间: 2022年 11月 18日 17:36
联系:

一個新的遊戲創意

帖子 ejsoon »

寫一個html+js,當一個四邊形的內角為36,72,144,108度時,有三種順序組合。在這三種情況中,當最長邊與最短邊之差最小時,給出每種情況的四條邊邊長之比,並畫出三種svg四邊形。

gemini 3.1 pro

代码: 全选

這是一個非常有趣的幾何最佳化問題!四邊形的四個內角一旦固定,形狀便有了一個自由度(類似於可以被「拉伸」)。透過將其放置在座標系中並解出閉合條件($x, y$ 軸的投影總和為 0),我們可以將四條邊長參數化,進而找出使「最長邊與最短邊差異最小」(即最接近等邊)的邊長比例。

令黃金比例 $\phi = \frac{1+\sqrt{5}}{2} \approx 1.618$。在所有情況下,當剩餘的兩個自由邊長**相等**時,最長邊與最短邊之差會達到最小。

以下是三種內角順序組合的邊長比例解析:

### **三種組合的邊長比例**

1. **情況 1:內角順序 $36^\circ, 72^\circ, 108^\circ, 144^\circ$**
* 當差異最小時,對應這四個角之間的邊長比例為:

$$\phi^2 : 1 : 1 : \phi$$



*(約為 $2.618 : 1 : 1 : 1.618$)*
* **說明**:連結 $144^\circ$ 與 $36^\circ$ 的邊最長,介於 $72^\circ$ 與 $108^\circ$ 之間的兩條邊最短且相等。


2. **情況 2:內角順序 $36^\circ, 72^\circ, 144^\circ, 108^\circ$**
* 當差異最小時,邊長比例為:

$$2\phi : 1 : 1 : \phi^2$$



*(約為 $3.236 : 1 : 1 : 2.618$)*
* **說明**:連結 $108^\circ$ 與 $36^\circ$ 的邊最長,介於 $36^\circ, 72^\circ, 144^\circ$ 之間的兩條邊最短且相等。


3. **情況 3:內角順序 $36^\circ, 108^\circ, 72^\circ, 144^\circ$**
* 當差異最小時,邊長比例為:

$$2 : 1 : 1 : \phi$$



*(約為 $2 : 1 : 1 : 1.618$)*
* **說明**:連結 $144^\circ$ 與 $36^\circ$ 的邊最長(為 $2$),介於 $36^\circ, 108^\circ, 72^\circ$ 之間的兩邊等長且最短。



---

### **HTML + JavaScript + SVG 實作**

請將以下程式碼存成 `.html` 檔案並在瀏覽器中開啟。這支程式會根據上述求出的最佳化邊長比例,自動計算頂點座標並繪製出三個精確的 SVG 四邊形。

```html
<!DOCTYPE html>
<html lang="zh-TW">
<head>
    <meta charset="UTF-8">
    <title>特定內角四邊形最佳化比例</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background-color: #f8f9fa;
            color: #333;
            display: flex;
            flex-direction: column;
            align-items: center;
            padding: 20px;
        }
        h1 {
            color: #2c3e50;
            margin-bottom: 30px;
        }
        .container {
            display: flex;
            flex-wrap: wrap;
            gap: 25px;
            justify-content: center;
            max-width: 1000px;
        }
        .card {
            background: white;
            border-radius: 12px;
            padding: 20px;
            box-shadow: 0 4px 15px rgba(0,0,0,0.05);
            text-align: center;
            width: 280px;
        }
        .card h3 {
            margin-top: 0;
            color: #34495e;
            font-size: 1.1em;
        }
        .ratio-text {
            background: #eef2f5;
            padding: 8px;
            border-radius: 6px;
            font-weight: bold;
            color: #2980b9;
            margin-bottom: 15px;
            font-family: monospace;
            font-size: 1.2em;
        }
        svg {
            width: 100%;
            height: 250px;
            border: 1px dashed #dcdde1;
            border-radius: 8px;
            background-color: #ffffff;
        }
        polygon {
            fill: rgba(52, 152, 219, 0.15);
            stroke: #2980b9;
            stroke-width: 2.5;
            stroke-linejoin: round;
        }
        text.label {
            font-size: 14px;
            fill: #c0392b;
            font-weight: bold;
            text-anchor: middle;
            user-select: none;
        }
    </style>
</head>
<body>

    <h1>四邊形極值邊長比例與圖形</h1>
    <div class="container" id="svg-container"></div>

    <script>
        const phi = (1 + Math.sqrt(5)) / 2;
        const phi2 = phi * phi;

        // 參數定義:angles 為四個頂點的內角(順序), sides 為對應順序的邊長比例
        const data = [
            {
                name: "情況 1: 36°, 72°, 108°, 144°",
                angles: [36, 72, 108, 144],
                sides: [phi2, 1, 1, phi],
                ratioText: "φ² : 1 : 1 : φ"
            },
            {
                name: "情況 2: 36°, 72°, 144°, 108°",
                angles: [36, 72, 144, 108],
                sides: [2 * phi, 1, 1, phi2],
                ratioText: "2φ : 1 : 1 : φ²"
            },
            {
                name: "情況 3: 36°, 108°, 72°, 144°",
                angles: [36, 108, 72, 144],
                sides: [2, 1, 1, phi],
                ratioText: "2 : 1 : 1 : φ"
            }
        ];

        const container = document.getElementById('svg-container');
        const deg2rad = Math.PI / 180;

        data.forEach(item => {
            let pts = [{x: 0, y: 0}];
            let currentAngle = 0; 
            
            // 依據邊長和偏轉角(180 - 內角)計算頂點座標
            for(let i = 0; i < 3; i++) {
                let p = pts[pts.length - 1];
                let nx = p.x + item.sides[i] * Math.cos(currentAngle);
                // SVG 的 Y 軸是向下的,所以要減去 sin 保持幾何直覺(逆時針建構)
                let ny = p.y - item.sides[i] * Math.sin(currentAngle);
                pts.push({x: nx, y: ny});
                
                // 下一個轉向角度
                currentAngle += (180 - item.angles[i + 1]) * deg2rad;
            }

            // 計算 Bounding box 來設定 viewBox
            let minX = Math.min(...pts.map(p => p.x));
            let maxX = Math.max(...pts.map(p => p.x));
            let minY = Math.min(...pts.map(p => p.y));
            let maxY = Math.max(...pts.map(p => p.y));

            let width = maxX - minX;
            let height = maxY - minY;
            let pad = Math.max(width, height) * 0.25; // 邊距

            // 計算幾何中心以協助放置角度文字標籤
            let cx = (minX + maxX) / 2;
            let cy = (minY + maxY) / 2;

            let labels = "";
            pts.forEach((p, i) => {
                let dx = p.x - cx;
                let dy = p.y - cy;
                let len = Math.sqrt(dx*dx + dy*dy);
                // 將文字沿著中心向外推
                let lx = p.x + (dx/len) * (pad * 0.5);
                let ly = p.y + (dy/len) * (pad * 0.5) + 5; 
                labels += `<text x="${lx}" y="${ly}" class="label" dominant-baseline="middle">${item.angles[i]}°</text>`;
            });

            let polyPts = pts.map(p => `${p.x},${p.y}`).join(" ");
            let viewBox = `${minX - pad} ${minY - pad} ${width + 2*pad} ${height + 2*pad}`;

            // 生成 Card UI
            let card = document.createElement('div');
            card.className = 'card';
            card.innerHTML = `
                <h3>${item.name}</h3>
                <div class="ratio-text">${item.ratioText}</div>
                <svg viewBox="${viewBox}">
                    <polygon points="${polyPts}" />
                    ${labels}
                </svg>
            `;
            container.appendChild(card);
        });
    </script>
</body>
</html>

```
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
BobMaster
锋芒初露
帖子: 1462
注册时间: 2020年 12月 7日 08:05
来自: 神秘的东方
我的状态: 🎯
联系:

Re: 一個新的遊戲創意

帖子 BobMaster »

用你的提示词问了一下,GPT 5.6 Sol Max

代码: 全选

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="referrer" content="no-referrer">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'unsafe-inline' 'unsafe-eval' 'wasm-unsafe-eval' blob: data: https://cdnjs.cloudflare.com https://cdn.jsdelivr.net https://esm.sh https://fonts.bunny.net https://fonts.googleapis.com https://fonts.gstatic.com https://unpkg.com; style-src 'unsafe-inline' blob: data: https://cdnjs.cloudflare.com https://cdn.jsdelivr.net https://esm.sh https://fonts.bunny.net https://fonts.googleapis.com https://fonts.gstatic.com https://unpkg.com; img-src blob: data: https://cdnjs.cloudflare.com https://cdn.jsdelivr.net https://esm.sh https://fonts.bunny.net https://fonts.googleapis.com https://fonts.gstatic.com https://unpkg.com; font-src blob: data: https://cdnjs.cloudflare.com https://cdn.jsdelivr.net https://esm.sh https://fonts.bunny.net https://fonts.googleapis.com https://fonts.gstatic.com https://unpkg.com; media-src blob: data: https://cdnjs.cloudflare.com https://cdn.jsdelivr.net https://esm.sh https://fonts.bunny.net https://fonts.googleapis.com https://fonts.gstatic.com https://unpkg.com; worker-src blob:; connect-src blob: data:; frame-src 'self'; object-src 'none'; base-uri 'none'; form-action 'none'">
<title>Balanced Quadrilaterals</title>
<style>:root{color-scheme:light dark;background:light-dark(rgb(255 255 255), rgb(24 24 24))}html,body{margin:0}body{box-sizing:border-box;padding:1rem;background:inherit}iframe{display:block;width:100%;height:calc(100vh - 2rem);margin:0 auto;border:0}</style>
</head>
<body>
<iframe sandbox="allow-scripts" referrerpolicy="no-referrer" title="Balanced Quadrilaterals" srcdoc="&lt;!doctype html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
&lt;meta charset=&quot;utf-8&quot;&gt;
&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;
&lt;meta name=&quot;referrer&quot; content=&quot;no-referrer&quot;&gt;
&lt;meta http-equiv=&quot;Content-Security-Policy&quot; content=&quot;default-src &#x27;none&#x27;; script-src &#x27;unsafe-inline&#x27; &#x27;unsafe-eval&#x27; &#x27;wasm-unsafe-eval&#x27; blob: data: https://cdnjs.cloudflare.com https://cdn.jsdelivr.net https://esm.sh https://fonts.bunny.net https://fonts.googleapis.com https://fonts.gstatic.com https://unpkg.com; style-src &#x27;unsafe-inline&#x27; blob: data: https://cdnjs.cloudflare.com https://cdn.jsdelivr.net https://esm.sh https://fonts.bunny.net https://fonts.googleapis.com https://fonts.gstatic.com https://unpkg.com; img-src blob: data: https://cdnjs.cloudflare.com https://cdn.jsdelivr.net https://esm.sh https://fonts.bunny.net https://fonts.googleapis.com https://fonts.gstatic.com https://unpkg.com; font-src blob: data: https://cdnjs.cloudflare.com https://cdn.jsdelivr.net https://esm.sh https://fonts.bunny.net https://fonts.googleapis.com https://fonts.gstatic.com https://unpkg.com; media-src blob: data: https://cdnjs.cloudflare.com https://cdn.jsdelivr.net https://esm.sh https://fonts.bunny.net https://fonts.googleapis.com https://fonts.gstatic.com https://unpkg.com; worker-src blob:; connect-src blob: data:; frame-src &#x27;none&#x27;; object-src &#x27;none&#x27;; base-uri &#x27;none&#x27;; form-action &#x27;none&#x27;&quot;&gt;
&lt;title&gt;Balanced Quadrilaterals&lt;/title&gt;
&lt;style&gt;:root {
  color-scheme: light dark;
  background-color: var(
    --background,
    var(--color-background-primary, light-dark(rgb(255 255 255), rgb(24 24 24)))
  ) !important;

  /* Agent-facing contract; keep in sync with SKILL.md. */
  --background: var(
    --color-background-primary,
    light-dark(rgb(255 255 255), rgb(24 24 24))
  );
  --foreground: var(
    --color-text-primary,
    light-dark(rgb(26 28 31), rgb(255 255 255))
  );
  --card: color-mix(in oklab, var(--foreground) 5%, transparent);
  --card-foreground: var(
    --color-text-primary,
    light-dark(rgb(26 28 31), rgb(255 255 255))
  );
  --popover: var(
    --color-background-secondary,
    light-dark(rgb(255 255 255), rgb(45 45 45))
  );
  --popover-foreground: var(
    --color-text-primary,
    light-dark(rgb(26 28 31), rgb(255 255 255))
  );
  --primary: var(
    --color-text-info,
    light-dark(rgb(51 156 255), rgb(131 195 255))
  );
  --primary-foreground: var(
    --color-text-inverse,
    light-dark(rgb(255 255 255), rgb(13 13 13))
  );
  --secondary: var(
    --color-background-secondary,
    light-dark(rgb(255 255 255 / 96%), rgb(54 54 54 / 96%))
  );
  --secondary-foreground: var(
    --color-text-primary,
    light-dark(rgb(26 28 31), rgb(255 255 255))
  );
  --muted: color-mix(in srgb, var(--foreground) 10%, transparent);
  --muted-foreground: var(
    --color-text-secondary,
    light-dark(rgb(26 28 31 / 49.4%), rgb(255 255 255 / 49.8%))
  );
  --accent: var(
    --color-background-info,
    light-dark(rgb(229 242 255), rgb(13 39 63))
  );
  --accent-foreground: var(
    --color-text-info,
    light-dark(rgb(51 156 255), rgb(131 195 255))
  );
  --destructive: var(
    --color-text-warning,
    light-dark(rgb(226 85 7), rgb(255 133 73))
  );
  --border: var(
    --color-border-secondary,
    light-dark(rgb(26 28 31 / 8%), rgb(255 255 255 / 8.2%))
  );
  --input: var(
    --color-border-primary,
    light-dark(
      rgb(26 28 31 / 11.8%),
      color-mix(in oklab, rgb(0 0 0) 10%, transparent)
    )
  );
  --ring: var(
    --color-ring-primary,
    light-dark(rgb(51 156 255), rgb(131 195 255 / 76%))
  );
  --font-size-base: var(--font-text-md-size, 14px);
  --red: light-dark(rgb(186 38 35), rgb(250 66 62));
  --green: light-dark(rgb(0 162 64), rgb(64 201 119));
  --viz-series-1: var(--primary);
  --viz-series-2: light-dark(rgb(243 136 59), rgb(245 154 86));
  --viz-series-3: light-dark(rgb(93 201 119), rgb(116 213 139));
  --viz-series-4: light-dark(rgb(235 119 177), rgb(240 143 192));
  --viz-series-5: light-dark(rgb(155 121 236), rgb(170 145 239));
  --viz-series-6: light-dark(rgb(58 185 177), rgb(90 203 194));

  /* Internal implementation variables; not part of the agent contract. */
  --font-sans: -apple-system, system-ui, &quot;Segoe UI&quot;, sans-serif;
  --font-mono:
    ui-monospace, SFMono-Regular, &quot;SF Mono&quot;, Menlo, Consolas, &quot;Liberation Mono&quot;,
    monospace;
  --font-size-normal: max(11px, var(--font-size-base));
  --font-size-tooltip: calc(var(--font-size-base) - 1px);
  --font-size-small: max(11px, calc(var(--font-size-base) - 2px));
  --font-size-h1: calc(var(--font-size-normal) * 1.7142857143);
  --font-size-h2: calc(var(--font-size-normal) * 1.4285714286);
  --font-size-h3: calc(var(--font-size-normal) * 1.2857142857);
  --font-weight-normal: 430;
  --font-weight-medium: 500;
  --line-height-normal: calc(var(--font-size-normal) * 1.5);
  --line-height-tooltip: calc(var(--font-size-tooltip) * 1.4285714286);
  --line-height-small: calc(var(--font-size-small) + 4px);
  --radius: var(--border-radius-lg, 12.5px);
  --radius-sm: calc(var(--radius) * 0.6);
  --radius-md: calc(var(--radius) * 0.8);
  --radius-lg: var(--radius);
  --radius-2xl: calc(var(--radius) * 1.6);
  --radius-full: 9999px;
  --shadow-sm: 0 1px 2px -1px rgb(0 0 0 / 8%);
  --checkmark-image: url(&quot;data:image/svg+xml,%3Csvg xmlns=&#x27;http://www.w3.org/2000/svg&#x27; viewBox=&#x27;0 0 17 17&#x27;%3E%3Cpath d=&#x27;M12.8961 3.64101C13.1297 3.41418 13.4984 3.37523 13.7779 3.56581C14.0571 3.75635 14.1554 4.11331 14.0299 4.41347L13.9615 4.53847L7.71151 13.7045C7.59411 13.8767 7.4063 13.9877 7.19881 14.0072C6.99136 14.0267 6.78564 13.9533 6.63826 13.806L2.88826 10.056L2.79842 9.9457C2.6192 9.67407 2.64927 9.30496 2.88826 9.06581C3.12738 8.82669 3.49647 8.79676 3.76815 8.97597L3.8785 9.06581L7.03084 12.2182L12.8053 3.74941L12.8961 3.64101Z&#x27;/%3E%3C/svg%3E&quot;);

  /* Legacy aliases; not part of the current agent contract. */
  --viz-bg: transparent;
  --viz-panel: var(--card);
  --viz-border: var(--border);
  --viz-text: var(--foreground);
  --viz-muted: var(--muted-foreground);
  --viz-accent: var(--primary);
  --viz-accent-text: var(--primary-foreground);
  --viz-accent-bg: var(--accent);
  --viz-font-size: var(--font-size-base);
  --viz-warning: var(--destructive);
}

:root[data-theme=&quot;light&quot;] {
  color-scheme: light;
}

:root[data-theme=&quot;dark&quot;] {
  color-scheme: dark;
}

* {
  box-sizing: border-box;
}

html &gt; body {
  /* Preserve MCP aliases for older inline renderers without creating :root cycles. */
  --color-background-primary: var(
    --background,
    light-dark(rgb(255 255 255), rgb(24 24 24))
  );
  --color-text-primary: var(
    --foreground,
    light-dark(rgb(26 28 31), rgb(255 255 255))
  );
  --color-border-secondary: var(
    --border,
    light-dark(rgb(26 28 31 / 8%), rgb(255 255 255 / 8.2%))
  );

  margin: 0;
  padding: 5px;
  color: var(--foreground);
  background: transparent !important;
  font-family: var(--font-sans);
  font-size: var(--font-size-normal);
  font-weight: var(--font-weight-normal);
  line-height: var(--line-height-normal);
}

a {
  color: color-mix(in srgb, var(--viz-accent) 80%, var(--viz-text) 20%);
  cursor: pointer;
  font-weight: var(--font-weight-medium, 500);
  text-decoration: none;
  text-underline-offset: 2px;
}

a:is(:hover, :focus-visible) {
  text-decoration-line: underline;
  text-decoration-style: dashed;
  text-decoration-thickness: 0.5px;
}

h1,
h2,
h3,
h4,
h5,
h6,
p {
  margin-block: 0;
}

h1 {
  font-size: var(--font-size-h1);
  font-weight: var(--font-weight-medium);
  line-height: 1.25;
}

h2 {
  font-size: var(--font-size-h2);
  font-weight: var(--font-weight-medium);
  line-height: 1.25;
}

h3,
h4,
h5,
h6 {
  font-size: var(--font-size-h3);
  font-weight: var(--font-weight-medium);
  line-height: 1.3;
}

b,
strong,
th {
  font-weight: var(--font-weight-medium);
}

code:not(pre code) {
  display: inline;
  padding: 1px 6px;
  border-radius: var(--radius-sm);
  corner-shape: superellipse(1.5);
  background: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.92em;
  overflow-wrap: anywhere;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  word-break: break-word;
}

.table-responsive {
  width: 100%;
  overflow-x: auto;
  scrollbar-width: thin;
}

.table {
  width: 100%;
  border-collapse: collapse;
  color: var(--foreground);
  font: inherit;
  text-align: start;
}

.table :is(th, td) {
  padding-block: 10px;
  padding-inline: 0 24px;
  overflow-wrap: anywhere;
  border-bottom: 1px solid var(--border);
  text-align: start;
  vertical-align: top;
}

.table-responsive &gt; .table :is(th, td) {
  overflow-wrap: break-word;
}

.table :is(th, td):last-child {
  padding-inline-end: 0;
}

.table :is(caption, thead th) {
  font-weight: 600;
}

.table thead th {
  padding-block: 8px;
  border-bottom-color: color-mix(in srgb, var(--foreground) 16%, transparent);
}

.table tbody tr:last-child :is(th, td) {
  border-bottom: 0;
}

.table.table-sm :is(th, td) {
  padding-block: 6px;
}

.table.table-sm :is(th, td):not(:last-child) {
  padding-inline-end: 16px;
}

.table :is(.text-end, [align=&quot;right&quot;]) {
  text-align: end;
  font-variant-numeric: tabular-nums;
}

.table :is(.text-center, [align=&quot;center&quot;]) {
  text-align: center;
}

.table .text-nowrap {
  white-space: nowrap;
}

#widget {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
  padding: 0;
  background: transparent !important;
}

.card {
  min-width: 0;
  padding: 12px;
  overflow: hidden;
  overflow-wrap: break-word;
  border-radius: var(--radius-2xl);
  corner-shape: superellipse(1.5);
  color: var(--card-foreground);
  background: var(--card);
}

#widget &gt; :not(.card) {
  width: 100% !important;
  max-width: none !important;
  margin: 0 !important;
  padding: 0 !important;
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  box-shadow: none !important;
}

.tooltip {
  position: fixed;
  z-index: 50;
  top: 0;
  left: 0;
  width: max-content;
  max-width: min(
    20rem,
    var(--tooltip-available-width, calc(100vw - 10px)),
    calc(100vw - 10px)
  );
  max-height: min(
    var(--tooltip-available-height, calc(100vh - 10px)),
    calc(100vh - 10px)
  );
  padding: 4px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  corner-shape: superellipse(1.5);
  color: var(--popover-foreground);
  background: var(--popover);
  box-shadow: none;
  font-size: var(--font-size-tooltip);
  line-height: var(--line-height-tooltip);
  overflow-wrap: break-word;
  white-space: normal;
  pointer-events: none;
  user-select: none;
}

.viz-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(max(180px, 24%), 1fr));
  gap: 10px;
}

.viz-stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.viz-stat-value {
  font-size: var(--font-size-h2);
  font-weight: var(--font-weight-medium);
  line-height: 1.25;
}

.viz-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.viz-badge {
  padding: 3px 8px;
  border-radius: var(--radius-full);
  color: var(--accent-foreground);
  background: var(--accent);
  font-weight: var(--font-weight-medium);
}

small,
.text-small,
.viz-badge {
  font-size: var(--font-size-small);
  line-height: var(--line-height-small);
}

.text-muted {
  color: var(--muted-foreground);
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.viz-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.viz-controls &gt; .form-label {
  display: grid;
  min-width: min(100%, 260px);
  flex: 1 1 280px;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 2px 12px;
  margin-bottom: 0;
}

.viz-controls &gt; .form-label &gt; :is(.form-control, .form-range, .form-select) {
  grid-column: 1 / -1;
}

.btn,
.form-check-input,
.form-control,
.form-range,
.form-select {
  font: inherit;
}

.btn {
  appearance: button;
  display: inline-flex;
  inline-size: fit-content;
  max-inline-size: 100%;
  min-height: 28px;
  align-items: center;
  justify-content: center;
  gap: 4px;
  margin: 0;
  padding: 0 8px;
  -webkit-app-region: no-drag;
  border: 1px solid var(--input);
  border-radius: var(--radius-lg);
  corner-shape: superellipse(1.5);
  color: var(--secondary-foreground);
  background: var(--secondary);
  cursor: var(--cursor-interaction, pointer);
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  user-select: none;
  -webkit-font-smoothing: antialiased;
}

.btn:is(.btn-block, .viz-tile) {
  inline-size: 100%;
}

.btn.viz-tile {
  min-width: 0;
  overflow-wrap: anywhere;
  white-space: normal;
}

a.btn {
  cursor: pointer;
  text-decoration: none;
}

.btn:not(:disabled):hover {
  background: color-mix(in srgb, var(--foreground) 6%, var(--secondary));
}

.btn-primary {
  border-color: transparent;
  color: var(--primary-foreground);
  background: var(--foreground);
  background-clip: padding-box;
}

.btn-primary .text-muted {
  color: color-mix(in srgb, var(--primary-foreground) 50%, transparent);
}

.btn-primary:not(:disabled):hover {
  background: color-mix(in srgb, var(--foreground) 80%, transparent);
  background-clip: padding-box;
}

.btn-ghost {
  border-color: transparent;
  color: var(--muted-foreground);
  background: transparent;
}

.btn-ghost:not(:disabled):hover {
  color: var(--foreground);
  background: color-mix(in srgb, var(--foreground) 6%, var(--secondary));
}

.btn:disabled {
  cursor: not-allowed;
  opacity: 0.4;
}

[data-lucide] {
  stroke-width: 1.6;
}

.form-label {
  display: block;
  margin-bottom: 6px;
  color: var(--foreground);
}

.form-control {
  display: block;
  width: 100%;
  min-height: 28px;
  padding: 0 8px;
  outline: none;
  border: 1px solid var(--input);
  border-radius: var(--radius-lg);
  corner-shape: superellipse(1.5);
  color: var(--foreground);
  background: var(--secondary);
}

.form-control::placeholder {
  color: var(--muted-foreground);
}

.form-control[type=&quot;file&quot;] {
  padding: 0;
  overflow: hidden;
  cursor: var(--cursor-interaction, pointer);
}

.form-control[type=&quot;file&quot;]::file-selector-button {
  min-height: 26px;
  margin-right: 8px;
  padding: 0 8px;
  border: 0;
  border-right: 1px solid var(--input);
  color: var(--secondary-foreground);
  background: var(--secondary);
  cursor: inherit;
  font: inherit;
}

.form-control[type=&quot;file&quot;]:not(:disabled):hover::file-selector-button {
  background: color-mix(in srgb, var(--foreground) 6%, var(--secondary));
}

.form-control-color[type=&quot;color&quot;] {
  width: 40px;
  height: 28px;
  padding: 3px;
  cursor: var(--cursor-interaction, pointer);
}

.form-control-color[type=&quot;color&quot;]::-webkit-color-swatch-wrapper {
  padding: 0;
}

.form-control-color[type=&quot;color&quot;]::-webkit-color-swatch {
  border: 0;
  border-radius: calc(var(--radius-lg) - 4px);
  corner-shape: superellipse(1.5);
}

textarea.form-control {
  height: auto;
  min-height: 72px;
  padding: 8px 10px;
  resize: vertical;
}

.form-control:focus-visible {
  border-color: var(--ring);
  box-shadow: inset 0 0 0 1px var(--ring);
}

.form-control:disabled,
.form-select:disabled {
  cursor: not-allowed;
  opacity: 0.4;
}

.form-select {
  appearance: none;
  display: block;
  width: 100%;
  min-height: 28px;
  margin: 0;
  padding: 0 32px 0 8px;
  outline: none;
  border: 1px solid var(--input);
  border-radius: var(--radius-lg);
  corner-shape: superellipse(1.5);
  color: var(--foreground);
  background-color: var(--secondary);
  background-image:
    linear-gradient(45deg, transparent 50%, var(--muted-foreground) 50%),
    linear-gradient(135deg, var(--muted-foreground) 50%, transparent 50%);
  background-position:
    calc(100% - 14px) 50%,
    calc(100% - 10px) 50%;
  background-repeat: no-repeat;
  background-size: 4px 4px;
  cursor: var(--cursor-interaction, default);
}

.form-select:not(:disabled):hover {
  background-color: color-mix(in srgb, var(--foreground) 6%, var(--secondary));
}

.form-select:focus-visible {
  border-color: var(--ring);
  box-shadow: inset 0 0 0 1px var(--ring);
}

.form-check {
  display: flex;
  min-height: 20px;
  align-items: center;
  gap: 6px;
}

.form-check-input {
  appearance: none;
  width: 14px;
  height: 14px;
  flex: 0 0 auto;
  margin: 0;
  border: 1px solid var(--input);
  color: var(--primary-foreground);
  background-color: transparent;
  cursor: var(--cursor-interaction, default);
  transition:
    background-color 150ms,
    border-color 150ms,
    box-shadow 150ms;
}

.form-check:not(.form-switch) .form-check-input[type=&quot;checkbox&quot;] {
  border-color: var(--input);
  border-radius: var(--radius-sm);
  corner-shape: superellipse(1.5);
  background-color: var(--secondary);
  box-shadow: var(--shadow-sm);
}

.form-check:not(.form-switch)
  .form-check-input:not(:disabled):not(:checked):hover {
  background-color: var(--card);
}

.form-check:not(.form-switch) .form-check-input[type=&quot;checkbox&quot;]:checked {
  border-color: var(--primary);
  background-color: var(--primary);
}

.form-check:not(.form-switch)
  .form-check-input[type=&quot;checkbox&quot;]:checked::before {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--primary-foreground);
  content: &quot;&quot;;
  mask: var(--checkmark-image) center / 12px 12px no-repeat;
}

.form-check-input[type=&quot;radio&quot;] {
  width: 14px;
  height: 14px;
  border-radius: var(--radius-full);
}

.form-check-input[type=&quot;radio&quot;]:checked {
  border: 2px solid var(--primary);
  background:
    radial-gradient(circle, var(--primary-foreground) 0 2.5px, transparent 3px),
    var(--primary);
}

.form-check:not(.form-switch) .form-check-input:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

.form-check:not(.form-switch) .form-check-input:disabled {
  cursor: not-allowed;
  pointer-events: none;
}

.form-check:not(.form-switch) .form-check-input:disabled + .form-check-label {
  cursor: not-allowed;
}

.form-switch .form-check-input:disabled,
.form-switch .form-check-input:disabled + .form-check-label {
  cursor: not-allowed;
  opacity: 0.6;
}

.form-check-label {
  color: var(--foreground);
  cursor: var(--cursor-interaction, default);
}

.form-switch .form-check-input {
  position: relative;
  width: 32px;
  height: 20px;
  border: 0;
  border-radius: var(--radius-full);
  background: var(--muted);
  box-shadow: none;
  transition: background-color 200ms cubic-bezier(0, 0, 0.2, 1);
}

.form-switch .form-check-input::before {
  position: absolute;
  top: 50%;
  left: 0;
  width: 16px;
  height: 16px;
  box-sizing: border-box;
  border: 1px solid light-dark(var(--primary-foreground), var(--foreground));
  border-radius: var(--radius-full);
  background: light-dark(var(--primary-foreground), var(--foreground));
  box-shadow: var(--shadow-sm);
  content: &quot;&quot;;
  transform: translate(2px, -50%);
  transition: transform 200ms cubic-bezier(0, 0, 0.2, 1);
}

.form-switch .form-check-input:checked {
  background: var(--primary);
}

.form-switch .form-check-input:checked::before {
  transform: translate(14px, -50%);
}

.form-switch .form-check-input:focus-visible {
  box-shadow: 0 0 0 2px var(--ring);
}

.form-range {
  appearance: none;
  display: block;
  width: 100%;
  height: 28px;
  flex: 1;
  margin: 0;
  padding: 0;
  outline: none;
  border: 0;
  accent-color: var(--primary);
  background: linear-gradient(
      color-mix(in srgb, var(--foreground) 7%, transparent),
      color-mix(in srgb, var(--foreground) 7%, transparent)
    )
    center / 100% 2px no-repeat;
}

.form-range::-webkit-slider-runnable-track {
  height: 28px;
  background: transparent;
}

.form-range::-webkit-slider-thumb {
  appearance: none;
  width: 20px;
  height: 20px;
  margin-top: 4px;
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  background: light-dark(var(--primary-foreground), var(--foreground));
}

.form-range:focus-visible::-webkit-slider-thumb {
  border-color: var(--ring);
  box-shadow: inset 0 0 0 1px var(--ring);
}

.form-range::-moz-range-track {
  height: 28px;
  background: transparent;
}

.form-range::-moz-range-thumb {
  width: 20px;
  height: 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  background: light-dark(var(--primary-foreground), var(--foreground));
}

.form-range:focus-visible::-moz-range-thumb {
  border-color: var(--ring);
  box-shadow: inset 0 0 0 1px var(--ring);
}

.form-range:disabled {
  cursor: not-allowed;
  opacity: 0.4;
}

.btn:not(.btn-primary, .viz-tile):is(
    [aria-pressed=&quot;true&quot;],
    [aria-selected=&quot;true&quot;],
    .is-selected
  ) {
  border-color: var(--primary);
  color: var(--primary-foreground);
  background: var(--primary);
}

.btn.viz-tile:is([aria-pressed=&quot;true&quot;], [aria-selected=&quot;true&quot;], .is-selected) {
  border-color: var(--primary);
  box-shadow: inset 0 0 0 1px var(--primary);
}

.btn:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

svg {
  display: block;
  max-width: 100%;
  height: auto;
}

#widget &gt; svg {
  width: 100%;
}

.text-warning,
.text-destructive {
  color: var(--destructive);
}

html&gt;body{padding:0}&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div id=&quot;balanced-quadrilaterals&quot;&gt;
  &lt;div class=&quot;viz-controls&quot; role=&quot;group&quot; aria-label=&quot;Choose the scale used for side labels&quot;&gt;
    &lt;span class=&quot;text-muted&quot;&gt;Side-label scale&lt;/span&gt;
    &lt;button type=&quot;button&quot; class=&quot;btn btn-primary&quot; data-label-mode=&quot;ratio&quot; aria-pressed=&quot;true&quot;&gt;
      Shortest = 1
    &lt;/button&gt;
    &lt;button type=&quot;button&quot; class=&quot;btn&quot; data-label-mode=&quot;perimeter&quot; aria-pressed=&quot;false&quot;&gt;
      Perimeter = 4
    &lt;/button&gt;
    &lt;span class=&quot;text-muted&quot;&gt;φ = (1 + √5) / 2 ≈ 1.618&lt;/span&gt;
  &lt;/div&gt;

  &lt;div class=&quot;bq-grid&quot;&gt;
    &lt;figure class=&quot;bq-case&quot; data-case-index=&quot;0&quot;&gt;
      &lt;figcaption class=&quot;bq-caption&quot;&gt;
        &lt;h3&gt;Case I&lt;/h3&gt;
        &lt;span class=&quot;text-muted&quot;&gt;A–B–C–D: 36° · 72° · 144° · 108°&lt;/span&gt;
      &lt;/figcaption&gt;
      &lt;svg viewBox=&quot;0 0 300 230&quot; role=&quot;img&quot; aria-labelledby=&quot;bq-title-1 bq-desc-1&quot;&gt;
        &lt;title id=&quot;bq-title-1&quot;&gt;Case I balanced quadrilateral&lt;/title&gt;
        &lt;desc id=&quot;bq-desc-1&quot;&gt;Angles 36, 72, 144, and 108 degrees in order. Side ratio AB to BC to CD to DA is 2 phi to 1 to 1 to phi squared.&lt;/desc&gt;
        &lt;g class=&quot;bq-drawing&quot;&gt;&lt;/g&gt;
      &lt;/svg&gt;
      &lt;div class=&quot;bq-ratio&quot;&gt;
        &lt;span class=&quot;text-muted&quot;&gt;AB : BC : CD : DA&lt;/span&gt;
        &lt;strong&gt;2φ : 1 : 1 : φ²&lt;/strong&gt;
      &lt;/div&gt;
    &lt;/figure&gt;

    &lt;figure class=&quot;bq-case&quot; data-case-index=&quot;1&quot;&gt;
      &lt;figcaption class=&quot;bq-caption&quot;&gt;
        &lt;h3&gt;Case II&lt;/h3&gt;
        &lt;span class=&quot;text-muted&quot;&gt;A–B–C–D: 36° · 72° · 108° · 144°&lt;/span&gt;
      &lt;/figcaption&gt;
      &lt;svg viewBox=&quot;0 0 300 230&quot; role=&quot;img&quot; aria-labelledby=&quot;bq-title-2 bq-desc-2&quot;&gt;
        &lt;title id=&quot;bq-title-2&quot;&gt;Case II balanced quadrilateral&lt;/title&gt;
        &lt;desc id=&quot;bq-desc-2&quot;&gt;Angles 36, 72, 108, and 144 degrees in order. Side ratio AB to BC to CD to DA is phi squared to 1 to 1 to phi.&lt;/desc&gt;
        &lt;g class=&quot;bq-drawing&quot;&gt;&lt;/g&gt;
      &lt;/svg&gt;
      &lt;div class=&quot;bq-ratio&quot;&gt;
        &lt;span class=&quot;text-muted&quot;&gt;AB : BC : CD : DA&lt;/span&gt;
        &lt;strong&gt;φ² : 1 : 1 : φ&lt;/strong&gt;
      &lt;/div&gt;
    &lt;/figure&gt;

    &lt;figure class=&quot;bq-case&quot; data-case-index=&quot;2&quot;&gt;
      &lt;figcaption class=&quot;bq-caption&quot;&gt;
        &lt;h3&gt;Case III&lt;/h3&gt;
        &lt;span class=&quot;text-muted&quot;&gt;A–B–C–D: 36° · 144° · 72° · 108°&lt;/span&gt;
      &lt;/figcaption&gt;
      &lt;svg viewBox=&quot;0 0 300 230&quot; role=&quot;img&quot; aria-labelledby=&quot;bq-title-3 bq-desc-3&quot;&gt;
        &lt;title id=&quot;bq-title-3&quot;&gt;Case III balanced quadrilateral&lt;/title&gt;
        &lt;desc id=&quot;bq-desc-3&quot;&gt;Angles 36, 144, 72, and 108 degrees in order. Side ratio AB to BC to CD to DA is phi to 1 to 1 to 2.&lt;/desc&gt;
        &lt;g class=&quot;bq-drawing&quot;&gt;&lt;/g&gt;
      &lt;/svg&gt;
      &lt;div class=&quot;bq-ratio&quot;&gt;
        &lt;span class=&quot;text-muted&quot;&gt;AB : BC : CD : DA&lt;/span&gt;
        &lt;strong&gt;φ : 1 : 1 : 2&lt;/strong&gt;
      &lt;/div&gt;
    &lt;/figure&gt;
  &lt;/div&gt;

  &lt;p class=&quot;sr-only&quot; id=&quot;bq-scale-status&quot; aria-live=&quot;polite&quot;&gt;Side labels are ratios with the shortest side equal to 1.&lt;/p&gt;
&lt;/div&gt;

&lt;style&gt;
  #balanced-quadrilaterals {
    width: 100%;
    color: var(--foreground);
  }

  #balanced-quadrilaterals .viz-controls {
    margin-bottom: 16px;
  }

  #balanced-quadrilaterals .bq-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 18px;
  }

  #balanced-quadrilaterals .bq-case {
    min-width: 0;
    margin: 0;
  }

  #balanced-quadrilaterals .bq-caption {
    min-height: 52px;
  }

  #balanced-quadrilaterals .bq-caption h3 {
    margin: 0 0 4px;
  }

  #balanced-quadrilaterals .bq-caption span {
    display: block;
  }

  #balanced-quadrilaterals .bq-case svg {
    display: block;
    width: 100%;
    height: auto;
    overflow: visible;
  }

  #balanced-quadrilaterals .bq-polygon {
    stroke: none;
    fill: color-mix(in srgb, var(--case-color) 15%, transparent);
  }

  #balanced-quadrilaterals .bq-edge {
    stroke: var(--case-color);
    stroke-width: 2;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke;
  }

  #balanced-quadrilaterals .bq-vertex {
    fill: var(--case-color);
  }

  #balanced-quadrilaterals .bq-angle-arc {
    fill: none;
    stroke: color-mix(in srgb, var(--case-color) 65%, var(--foreground));
    stroke-width: 1.5;
    vector-effect: non-scaling-stroke;
  }

  #balanced-quadrilaterals .bq-side-label,
  #balanced-quadrilaterals .bq-angle-label {
    fill: var(--foreground);
    font-size: var(--font-size-base);
    font-weight: 500;
    text-anchor: middle;
    dominant-baseline: central;
  }

  #balanced-quadrilaterals .bq-side-label {
    paint-order: stroke;
    stroke: var(--background);
    stroke-width: 4;
    stroke-linejoin: round;
  }

  #balanced-quadrilaterals .bq-angle-label {
    font-weight: 400;
  }

  #balanced-quadrilaterals .bq-ratio {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 4px 10px;
    padding-top: 4px;
  }

  #balanced-quadrilaterals .bq-ratio strong {
    font-weight: 500;
    white-space: nowrap;
  }

  @media (max-width: 640px) {
    #balanced-quadrilaterals .bq-grid {
      grid-template-columns: 1fr;
      gap: 22px;
    }

    #balanced-quadrilaterals .bq-caption {
      min-height: 0;
    }
  }
&lt;/style&gt;

&lt;script&gt;
  (() =&gt; {
    const root = document.getElementById(&#x27;balanced-quadrilaterals&#x27;);
    if (!root) return;

    const phi = (1 + Math.sqrt(5)) / 2;
    const sideNames = [&#x27;AB&#x27;, &#x27;BC&#x27;, &#x27;CD&#x27;, &#x27;DA&#x27;];
    const cases = [
      {
        angles: [36, 72, 144, 108],
        lengths: [2 * phi, 1, 1, phi * phi],
        exact: [&#x27;2φ&#x27;, &#x27;1&#x27;, &#x27;1&#x27;, &#x27;φ²&#x27;],
        color: &#x27;var(--viz-series-1)&#x27;
      },
      {
        angles: [36, 72, 108, 144],
        lengths: [phi * phi, 1, 1, phi],
        exact: [&#x27;φ²&#x27;, &#x27;1&#x27;, &#x27;1&#x27;, &#x27;φ&#x27;],
        color: &#x27;var(--viz-series-2)&#x27;
      },
      {
        angles: [36, 144, 72, 108],
        lengths: [phi, 1, 1, 2],
        exact: [&#x27;φ&#x27;, &#x27;1&#x27;, &#x27;1&#x27;, &#x27;2&#x27;],
        color: &#x27;var(--viz-series-3)&#x27;
      }
    ];

    const svgNS = &#x27;http://www.w3.org/2000/svg&#x27;;
    let labelMode = &#x27;ratio&#x27;;

    function svgElement(name, attributes = {}) {
      const element = document.createElementNS(svgNS, name);
      Object.entries(attributes).forEach(([key, value]) =&gt; element.setAttribute(key, value));
      return element;
    }

    function degreesToRadians(value) {
      return value * Math.PI / 180;
    }

    function constructVertices(item) {
      const directions = [
        0,
        180 - item.angles[1],
        360 - item.angles[1] - item.angles[2],
        180 + item.angles[0]
      ];
      const vertices = [{ x: 0, y: 0 }];
      for (let index = 0; index &lt; 3; index += 1) {
        const direction = degreesToRadians(directions[index]);
        const previous = vertices[vertices.length - 1];
        vertices.push({
          x: previous.x + item.lengths[index] * Math.cos(direction),
          y: previous.y + item.lengths[index] * Math.sin(direction)
        });
      }
      return { vertices, directions };
    }

    function makeProjector(vertices) {
      const xs = vertices.map((point) =&gt; point.x);
      const ys = vertices.map((point) =&gt; point.y);
      const minX = Math.min(...xs);
      const maxX = Math.max(...xs);
      const minY = Math.min(...ys);
      const maxY = Math.max(...ys);
      const width = Math.max(maxX - minX, 0.001);
      const height = Math.max(maxY - minY, 0.001);
      const scale = Math.min(194 / width, 112 / height);
      const centerX = (minX + maxX) / 2;
      const centerY = (minY + maxY) / 2;
      return (point) =&gt; ({
        x: 150 + (point.x - centerX) * scale,
        y: 123 - (point.y - centerY) * scale
      });
    }

    function sideLabel(item, index) {
      if (labelMode === &#x27;ratio&#x27;) return `${sideNames[index]}  ${item.exact[index]}`;
      const perimeter = item.lengths.reduce((sum, value) =&gt; sum + value, 0);
      return `${sideNames[index]}  ${(4 * item.lengths[index] / perimeter).toFixed(3)}`;
    }

    function drawCase(figure, item) {
      const drawing = figure.querySelector(&#x27;.bq-drawing&#x27;);
      drawing.replaceChildren();
      figure.style.setProperty(&#x27;--case-color&#x27;, item.color);

      const { vertices, directions } = constructVertices(item);
      const project = makeProjector(vertices);
      const screenPoints = vertices.map(project);
      const pointString = screenPoints.map((point) =&gt; `${point.x},${point.y}`).join(&#x27; &#x27;);
      drawing.appendChild(svgElement(&#x27;polygon&#x27;, {
        class: &#x27;bq-polygon&#x27;,
        points: pointString
      }));

      screenPoints.forEach((start, index) =&gt; {
        const end = screenPoints[(index + 1) % 4];
        drawing.appendChild(svgElement(&#x27;line&#x27;, {
          class: &#x27;bq-edge&#x27;,
          x1: start.x,
          y1: start.y,
          x2: end.x,
          y2: end.y
        }));

        const mathStart = vertices[index];
        const mathEnd = vertices[(index + 1) % 4];
        const dx = mathEnd.x - mathStart.x;
        const dy = mathEnd.y - mathStart.y;
        const magnitude = Math.hypot(dx, dy);
        const outwardX = dy / magnitude;
        const outwardY = -dx / magnitude;
        const midpoint = {
          x: (start.x + end.x) / 2,
          y: (start.y + end.y) / 2
        };
        const label = svgElement(&#x27;text&#x27;, {
          class: &#x27;bq-side-label&#x27;,
          x: midpoint.x + outwardX * 17,
          y: midpoint.y - outwardY * 17
        });
        label.textContent = sideLabel(item, index);
        drawing.appendChild(label);
      });

      screenPoints.forEach((point, index) =&gt; {
        const outgoingDirection = degreesToRadians(directions[index]);
        const angle = degreesToRadians(item.angles[index]);
        const arcRadius = item.angles[index] &lt;= 40 ? 23 : 18;
        const arcSamples = 14;
        const arcPoints = [];
        for (let sample = 0; sample &lt;= arcSamples; sample += 1) {
          const theta = outgoingDirection + angle * sample / arcSamples;
          arcPoints.push({
            x: point.x + arcRadius * Math.cos(theta),
            y: point.y - arcRadius * Math.sin(theta)
          });
        }
        const arcPath = arcPoints
          .map((arcPoint, sample) =&gt; `${sample === 0 ? &#x27;M&#x27; : &#x27;L&#x27;} ${arcPoint.x} ${arcPoint.y}`)
          .join(&#x27; &#x27;);
        drawing.appendChild(svgElement(&#x27;path&#x27;, {
          class: &#x27;bq-angle-arc&#x27;,
          d: arcPath
        }));

        drawing.appendChild(svgElement(&#x27;circle&#x27;, {
          class: &#x27;bq-vertex&#x27;,
          cx: point.x,
          cy: point.y,
          r: 3
        }));

        const bisector = outgoingDirection + angle / 2;
        const labelRadius = item.angles[index] &lt;= 40 ? 43 : 34;
        const angleLabel = svgElement(&#x27;text&#x27;, {
          class: &#x27;bq-angle-label&#x27;,
          x: point.x + labelRadius * Math.cos(bisector),
          y: point.y - labelRadius * Math.sin(bisector)
        });
        angleLabel.textContent = `${item.angles[index]}°`;
        drawing.appendChild(angleLabel);
      });
    }

    function drawAll() {
      root.querySelectorAll(&#x27;.bq-case&#x27;).forEach((figure) =&gt; {
        const index = Number(figure.dataset.caseIndex);
        drawCase(figure, cases[index]);
      });
    }

    root.querySelectorAll(&#x27;[data-label-mode]&#x27;).forEach((button) =&gt; {
      button.addEventListener(&#x27;click&#x27;, () =&gt; {
        labelMode = button.dataset.labelMode;
        root.querySelectorAll(&#x27;[data-label-mode]&#x27;).forEach((peer) =&gt; {
          const isSelected = peer === button;
          peer.setAttribute(&#x27;aria-pressed&#x27;, String(isSelected));
          peer.classList.toggle(&#x27;btn-primary&#x27;, isSelected);
        });
        root.querySelector(&#x27;#bq-scale-status&#x27;).textContent = labelMode === &#x27;ratio&#x27;
          ? &#x27;Side labels are ratios with the shortest side equal to 1.&#x27;
          : &#x27;Side labels are normalized so that the perimeter equals 4.&#x27;;
        drawAll();
      });
    });

    drawAll();
  })();
&lt;/script&gt;

&lt;script src=&quot;https://unpkg.com/@floating-ui/core@1.7.3/dist/floating-ui.core.umd.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://unpkg.com/@floating-ui/dom@1.7.4/dist/floating-ui.dom.umd.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;
(() =&gt; {
  if (window.FloatingUIDOM == null) {
    return;
  }
  const { autoUpdate, computePosition, flip, offset, shift, size } =
    window.FloatingUIDOM;
  const tooltipPlacements = new Set([&quot;top&quot;, &quot;right&quot;, &quot;bottom&quot;, &quot;left&quot;]);
  const tooltipId = `codex-visualization-tooltip-${
    window.crypto?.randomUUID?.() ?? Date.now().toString(36)
  }`;
  const tooltipGap = 5;
  const hoverDelay = 700;
  const skipDelay = 300;
  let activeTrigger = null;
  let pendingTrigger = null;
  let tooltip = null;
  let openTimeout = null;
  let autoUpdateCleanup = null;
  let positionRequest = 0;
  let skipDelayUntil = 0;

  const getTrigger = (target) =&gt;
    target?.nodeType === Node.ELEMENT_NODE
      ? target.closest(&quot;[data-tooltip]&quot;)
      : null;
  const containsTarget = (trigger, target) =&gt;
    target?.nodeType != null &amp;&amp; trigger.contains(target);
  const getContent = (trigger) =&gt;
    trigger.getAttribute(&quot;data-tooltip&quot;)?.trim() ?? &quot;&quot;;
  const getPlacement = (trigger) =&gt; {
    const placement = trigger.getAttribute(&quot;data-tooltip-placement&quot;);
    return tooltipPlacements.has(placement) ? placement : &quot;top&quot;;
  };
  const getTooltip = () =&gt; {
    if (tooltip == null) {
      tooltip = document.createElement(&quot;div&quot;);
      tooltip.id = tooltipId;
      tooltip.className = &quot;tooltip&quot;;
      tooltip.setAttribute(&quot;role&quot;, &quot;tooltip&quot;);
    }
    return tooltip;
  };
  const setDescribedBy = (trigger, described) =&gt; {
    const ids = new Set(
      (trigger.getAttribute(&quot;aria-describedby&quot;) ?? &quot;&quot;)
        .split(/\s+/)
        .filter(Boolean),
    );
    if (described) {
      ids.add(tooltipId);
    } else {
      ids.delete(tooltipId);
    }
    if (ids.size === 0) {
      trigger.removeAttribute(&quot;aria-describedby&quot;);
    } else {
      trigger.setAttribute(&quot;aria-describedby&quot;, [...ids].join(&quot; &quot;));
    }
  };
  const clearOpenTimeout = () =&gt; {
    if (openTimeout != null) {
      window.clearTimeout(openTimeout);
      openTimeout = null;
    }
    pendingTrigger = null;
  };
  const closeTooltip = (activateSkipDelay = true) =&gt; {
    clearOpenTimeout();
    positionRequest += 1;
    autoUpdateCleanup?.();
    autoUpdateCleanup = null;
    if (activeTrigger == null) {
      return;
    }
    setDescribedBy(activeTrigger, false);
    activeTrigger = null;
    tooltip?.remove();
    if (activateSkipDelay) {
      skipDelayUntil = Date.now() + skipDelay;
    }
  };
  const updatePosition = (trigger, floating) =&gt; {
    const request = ++positionRequest;
    void computePosition(trigger, floating, {
      middleware: [
        offset(tooltipGap),
        flip({ padding: tooltipGap }),
        shift({ padding: tooltipGap }),
        size({
          padding: tooltipGap,
          apply({ availableHeight, availableWidth, elements }) {
            elements.floating.style.setProperty(
              &quot;--tooltip-available-width&quot;,
              `${Math.max(0, availableWidth)}px`,
            );
            elements.floating.style.setProperty(
              &quot;--tooltip-available-height&quot;,
              `${Math.max(0, availableHeight)}px`,
            );
          },
        }),
      ],
      placement: getPlacement(trigger),
      strategy: &quot;fixed&quot;,
    })
      .then(({ x, y }) =&gt; {
        if (activeTrigger !== trigger || request !== positionRequest) {
          return;
        }
        const scale = window.devicePixelRatio || 1;
        floating.style.transform = `translate(${Math.round(x * scale) / scale}px, ${Math.round(y * scale) / scale}px)`;
        floating.style.visibility = &quot;visible&quot;;
      })
      .catch(() =&gt; {
        if (activeTrigger === trigger &amp;&amp; request === positionRequest) {
          closeTooltip(false);
        }
      });
  };
  const openTooltip = (trigger) =&gt; {
    const content = getContent(trigger);
    if (!trigger.isConnected || content.length === 0) {
      return;
    }
    clearOpenTimeout();
    if (activeTrigger === trigger) {
      return;
    }
    closeTooltip();
    const floating = getTooltip();
    floating.textContent = content;
    floating.style.visibility = &quot;hidden&quot;;
    floating.style.transform = &quot;translate(0, 0)&quot;;
    document.body.appendChild(floating);
    activeTrigger = trigger;
    setDescribedBy(trigger, true);
    autoUpdateCleanup = autoUpdate(trigger, floating, () =&gt; {
      updatePosition(trigger, floating);
    });
  };
  const requestOpen = (trigger, immediate = false) =&gt; {
    if (
      getContent(trigger).length === 0 ||
      activeTrigger === trigger ||
      pendingTrigger === trigger
    ) {
      return;
    }
    clearOpenTimeout();
    pendingTrigger = trigger;
    const delay =
      immediate || activeTrigger != null || Date.now() &lt; skipDelayUntil
        ? 0
        : hoverDelay;
    if (delay === 0) {
      openTooltip(trigger);
      return;
    }
    openTimeout = window.setTimeout(() =&gt; {
      openTimeout = null;
      pendingTrigger = null;
      openTooltip(trigger);
    }, delay);
  };
  const handlePointerOpen = (event) =&gt; {
    if (event.pointerType === &quot;touch&quot;) {
      return;
    }
    const trigger = getTrigger(event.target);
    if (trigger == null || containsTarget(trigger, event.relatedTarget)) {
      return;
    }
    requestOpen(trigger);
  };
  const handleLeave = (event) =&gt; {
    const trigger = getTrigger(event.target);
    if (trigger == null || containsTarget(trigger, event.relatedTarget)) {
      return;
    }
    if (activeTrigger === trigger || pendingTrigger === trigger) {
      closeTooltip();
    }
  };
  const handleFocusIn = (event) =&gt; {
    const trigger = getTrigger(event.target);
    if (trigger?.matches(&quot;:focus-visible&quot;)) {
      requestOpen(trigger, true);
    }
  };
  const handleKeyDown = (event) =&gt; {
    if (event.key === &quot;Escape&quot;) {
      closeTooltip();
    }
  };
  const handleContextMenu = (event) =&gt; {
    const trigger = getTrigger(event.target);
    if (activeTrigger === trigger || pendingTrigger === trigger) {
      closeTooltip();
    }
  };
  const destroy = () =&gt; {
    closeTooltip(false);
    document.removeEventListener(&quot;pointerover&quot;, handlePointerOpen);
    document.removeEventListener(&quot;pointerout&quot;, handleLeave);
    document.removeEventListener(&quot;focusin&quot;, handleFocusIn);
    document.removeEventListener(&quot;focusout&quot;, handleLeave);
    document.removeEventListener(&quot;keydown&quot;, handleKeyDown);
    document.removeEventListener(&quot;contextmenu&quot;, handleContextMenu);
    tooltip = null;
  };

  document.addEventListener(&quot;pointerover&quot;, handlePointerOpen);
  document.addEventListener(&quot;pointerout&quot;, handleLeave);
  document.addEventListener(&quot;focusin&quot;, handleFocusIn);
  document.addEventListener(&quot;focusout&quot;, handleLeave);
  document.addEventListener(&quot;keydown&quot;, handleKeyDown);
  document.addEventListener(&quot;contextmenu&quot;, handleContextMenu);
  window.addEventListener(&quot;pagehide&quot;, destroy, { once: true });
})();
&lt;/script&gt;
&lt;script id=&quot;codex-visualization-lucide&quot; async src=&quot;https://unpkg.com/lucide@1.17.0/dist/umd/lucide.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;
(() =&gt; {
  const initialize = () =&gt; {
    globalThis.lucide?.createIcons({ attrs: { width: 16, height: 16 } });
  };
  if (globalThis.lucide != null) {
    initialize();
    return;
  }
  document
    .getElementById(&quot;codex-visualization-lucide&quot;)
    ?.addEventListener(&quot;load&quot;, initialize, { once: true });
})();
&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;
"></iframe>
</body>
</html>

上次由 BobMaster 在 2026年 7月 28日 01:25,总共编辑 1 次。
人生如音乐,欢乐且自由
头像
ejsoon
一枝独秀
帖子: 6360
注册时间: 2022年 11月 18日 17:36
联系:

Re: 一個新的遊戲創意

帖子 ejsoon »

展示三種tile

代码: 全选

<!DOCTYPE html>
<html lang="zh-TW">
<head>
    <meta charset="UTF-8">
    <title>特定內角四邊形最佳化比例</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background-color: #f8f9fa;
            color: #333;
            display: flex;
            flex-direction: column;
            align-items: center;
            padding: 20px;
        }
        h1 {
            color: #2c3e50;
            margin-bottom: 30px;
        }
        .container {
            display: flex;
            flex-wrap: wrap;
            gap: 25px;
            justify-content: center;
            max-width: 1000px;
        }
        .card {
            background: white;
            border-radius: 12px;
            padding: 20px;
            box-shadow: 0 4px 15px rgba(0,0,0,0.05);
            text-align: center;
            width: 280px;
        }
        .card h3 {
            margin-top: 0;
            color: #34495e;
            font-size: 1.1em;
        }
        .ratio-text {
            background: #eef2f5;
            padding: 8px;
            border-radius: 6px;
            font-weight: bold;
            color: #2980b9;
            margin-bottom: 15px;
            font-family: monospace;
            font-size: 1.2em;
        }
        svg {
            width: 100%;
            height: 250px;
            border: 1px dashed #dcdde1;
            border-radius: 8px;
            background-color: #ffffff;
        }
        polygon {
            fill: rgba(52, 152, 219, 0.15);
            stroke: #2980b9;
            stroke-width: 2.5; /* 現在配合放大後的座標,線條粗細會正常顯示 */
            stroke-linejoin: round;
        }
        text.label {
            font-size: 15px; /* 字體大小正常化 */
            fill: #c0392b;
            font-weight: bold;
            text-anchor: middle;
            user-select: none;
        }
    </style>
</head>
<body>

    <h1>四邊形極值邊長比例與圖形</h1>
    <div class="container" id="svg-container"></div>

    <script>
        const phi = (1 + Math.sqrt(5)) / 2;
        const phi2 = phi * phi;

        const data = [
            {
                name: "情況 1: 36°, 72°, 108°, 144°",
                angles: [36, 72, 108, 144],
                sides: [phi2, 1, 1, phi],
                ratioText: "φ² : 1 : 1 : φ"
            },
            {
                name: "情況 2: 36°, 72°, 144°, 108°",
                angles: [36, 72, 144, 108],
                sides: [2 * phi, 1, 1, phi2],
                ratioText: "2φ : 1 : 1 : φ²"
            },
            {
                name: "情況 3: 36°, 108°, 72°, 144°",
                angles: [36, 108, 72, 144],
                sides: [2, 1, 1, phi],
                ratioText: "2 : 1 : 1 : φ"
            }
        ];

        const container = document.getElementById('svg-container');
        const deg2rad = Math.PI / 180;
        const scale = 60; // 關鍵修復:加入縮放因子,將座標放大,使 14px 字體與 2.5px 邊框比例正常

        data.forEach(item => {
            let pts = [{x: 0, y: 0}];
            let currentAngle = 0; 
            
            for(let i = 0; i < 3; i++) {
                let p = pts[pts.length - 1];
                // 座標乘以 scale 進行放大
                let nx = p.x + item.sides[i] * scale * Math.cos(currentAngle);
                let ny = p.y - item.sides[i] * scale * Math.sin(currentAngle);
                pts.push({x: nx, y: ny});
                
                currentAngle += (180 - item.angles[i + 1]) * deg2rad;
            }

            let minX = Math.min(...pts.map(p => p.x));
            let maxX = Math.max(...pts.map(p => p.x));
            let minY = Math.min(...pts.map(p => p.y));
            let maxY = Math.max(...pts.map(p => p.y));

            let width = maxX - minX;
            let height = maxY - minY;
            let pad = Math.max(width, height) * 0.25; 

            let cx = (minX + maxX) / 2;
            let cy = (minY + maxY) / 2;

            let labels = "";
            pts.forEach((p, i) => {
                let dx = p.x - cx;
                let dy = p.y - cy;
                let len = Math.sqrt(dx*dx + dy*dy);
                // 文字標籤偏移量調整
                let lx = p.x + (dx/len) * (pad * 0.4);
                let ly = p.y + (dy/len) * (pad * 0.4) + 5; 
                labels += `<text x="${lx}" y="${ly}" class="label" dominant-baseline="middle">${item.angles[i]}°</text>`;
            });

            let polyPts = pts.map(p => `${p.x},${p.y}`).join(" ");
            let viewBox = `${minX - pad} ${minY - pad} ${width + 2*pad} ${height + 2*pad}`;

            let card = document.createElement('div');
            card.className = 'card';
            card.innerHTML = `
                <h3>${item.name}</h3>
                <div class="ratio-text">${item.ratioText}</div>
                <svg viewBox="${viewBox}">
                    <polygon points="${polyPts}" />
                    ${labels}
                </svg>
            `;
            container.appendChild(card);
        });
    </script>
</body>
</html>
Screenshot_20260727_225947_Firefox.png
Screenshot_20260727_225947_Firefox.png (168.58 KiB) 查看 36 次
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
帖子: 6360
注册时间: 2022年 11月 18日 17:36
联系:

Re: 一個新的遊戲創意

帖子 ejsoon »

新遊戲取個什麼名字好呢?黄金眼?黄金磚?

代码: 全选

<svg id="etmain" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" width="480" height="480"> <defs mode="0" rotatestep="0" rotatestart="0" stepvalue="60" snapto="0" displaywait="1">   <g id="tile0" frontfill="#ff94dc" backfill="#ff94dc"><path d="M -47.124,17.119 L 0,-17.119 L 36,-17.119 L 47.125,17.119 Z"></path></g><g id="tile1" frontfill="#ff94dc" backfill="#ff94dc"><path d="M -58.249,27.699 L 17.999,-27.699 L 47.124,-6.539 L 58.249,27.699 Z"></path></g><g id="tile2" frontfill="#ff94dc" backfill="#ff94dc"><path d="M -41.562,17.119 L 5.562,-17.119 L 41.562,-17.119 L 30.437,17.119 Z"></path></g><g id="tile3" frontfill="#96ffbe" backfill="#96ffbe"><path d="M -47.124,17.119 L 0,-17.119 L 36,-17.119 L 47.125,17.119 Z"></path></g><g id="tile4" frontfill="#96ffbe" backfill="#96ffbe"><path d="M -58.249,27.699 L 17.999,-27.699 L 47.124,-6.539 L 58.249,27.699 Z"></path></g><g id="tile5" frontfill="#96ffbe" backfill="#96ffbe"><path d="M -41.562,17.119 L 5.562,-17.119 L 41.562,-17.119 L 30.437,17.119 Z"></path></g></defs> <g class="etdrop" stroke="#777" stroke-width="2" stroke-linejoin="round" transform="translate(73.791,125.797) scale(0.859)"><g class="etboard"></g><use href="#tile0" fill="#ff94dc" transform="translate(143,164) scale(1,1) rotate(0)" class="tiledropped"></use><use href="#tile3" fill="#96ffbe" transform="translate(143,198.238) scale(-1,1) rotate(180)" class="tiledropped"></use><use href="#tile0" fill="#ff94dc" transform="translate(195.281,220.647) scale(1,1) rotate(-71.999)" class="tiledropped"></use><use href="#tile3" fill="#96ffbe" transform="translate(218.188,139.569) scale(-1,1) rotate(36.001)" class="tiledropped"></use><use href="#tile3" fill="#96ffbe" transform="translate(159.937,111.871) scale(-1,1) rotate(144.002)" class="tiledropped"></use><use href="#tile1" fill="#ff94dc" transform="translate(163.779,78.881) scale(1,1) rotate(-108.002)" class="tiledropped"></use><use href="#tile1" fill="#ff94dc" transform="translate(216.465,61.761) scale(1,1) rotate(71.998)" class="tiledropped"></use><use href="#tile3" fill="#96ffbe" transform="translate(264.652,75.608) scale(-1,1) rotate(72.003)" class="tiledropped"></use><use href="#tile1" fill="#ff94dc" transform="translate(204.025,23.481) scale(1,1) rotate(-108.002)" class="tiledropped"></use><use href="#tile2" fill="#ff94dc" transform="translate(125,215.357) scale(1,1) rotate(72.001)" class="tiledropped"></use><use href="#tile1" fill="#ff94dc" transform="translate(227.844,214.108) scale(1,1) rotate(-35.999)" class="tiledropped"></use><use href="#tile2" fill="#ff94dc" transform="translate(305.812,191.7) scale(1,1) rotate(-144)" class="tiledropped"></use><use href="#tile0" fill="#ff94dc" transform="translate(297.214,86.186) scale(1,1) rotate(107.997)" class="tiledropped"></use><use href="#tile2" fill="#ff94dc" transform="translate(316.936,136.293) scale(1,1) rotate(-72.003)" class="tiledropped"></use><use href="#tile4" fill="#96ffbe" transform="translate(256.711,6.361) scale(-1,1) rotate(-71.998)" class="tiledropped"></use><use href="#tile2" fill="#ff94dc" transform="translate(292.053,-51.059) scale(-1,1) rotate(36.001)" class="tiledropped"></use><use href="#tile5" fill="#96ffbe" transform="translate(321.177,-29.899) scale(-1,1) rotate(-143.999)" class="tiledropped"></use><use href="#tile0" fill="#ff94dc" transform="translate(311.774,41.368) scale(1,1) rotate(-72.003)" class="tiledropped"></use><use href="#tile3" fill="#96ffbe" transform="translate(132.933,22.236) scale(-1,1) rotate(-143.997)" class="tiledropped"></use><use href="#tile5" fill="#96ffbe" transform="translate(186.678,-64.134) scale(-1,1) rotate(108.002)" class="tiledropped"></use><use href="#tile5" fill="#96ffbe" transform="translate(141.679,-36.434) scale(-1,1) rotate(-179.999)" class="tiledropped"></use><use href="#tile3" fill="#96ffbe" transform="translate(363.145,9.63) scale(1,1) rotate(-108)" class="tiledropped"></use><use href="#tile5" fill="#96ffbe" transform="translate(375.988,49.158) scale(1,1) rotate(72)" class="tiledropped"></use><use href="#tile1" fill="#ff94dc" transform="translate(360.769,130.234) scale(1,1) rotate(-71.999)" class="tiledropped"></use><use href="#tile4" fill="#96ffbe" transform="translate(413.455,147.354) scale(-1,1) rotate(-108.001)" class="tiledropped"></use><use href="#tile4" fill="#96ffbe" transform="translate(401.017,185.634) scale(-1,1) rotate(71.999)" class="tiledropped"></use><use href="#tile2" fill="#ff94dc" transform="translate(334.936,212.86) scale(1,1) rotate(36)" class="tiledropped"></use><use href="#tile5" fill="#96ffbe" transform="translate(124.998,283.833) scale(-1,1) rotate(-108.002)" class="tiledropped"></use><use href="#tile3" fill="#96ffbe" transform="translate(159.279,289.124) scale(1,1) rotate(-71.998)" class="tiledropped"></use><use href="#tile2" fill="#ff94dc" transform="translate(99.31,46.667) scale(-1,1) rotate(36.003)" class="tiledropped"></use><use href="#tile3" fill="#96ffbe" transform="translate(36.562,92.261) scale(1,1) rotate(-36.003)" class="tiledropped"></use><use href="#tile4" fill="#96ffbe" transform="translate(66.75,106.109) scale(1,1) rotate(-0.003)" class="tiledropped"></use><use href="#tile1" fill="#ff94dc" transform="translate(66.752,161.507) scale(1,1) rotate(179.997)" class="tiledropped"></use><use href="#tile4" fill="#96ffbe" transform="translate(1.63,195.749) scale(1,1) rotate(-0.003)" class="tiledropped"></use><use href="#tile2" fill="#ff94dc" transform="translate(92.437,225.937) scale(-1,1) rotate(107.999)" class="tiledropped"></use><use href="#tile2" fill="#ff94dc" transform="translate(74.435,281.335) scale(-1,1) rotate(-72.001)" class="tiledropped"></use><use href="#tile5" fill="#96ffbe" transform="translate(45.309,302.495) scale(-1,1) rotate(107.999)" class="tiledropped"></use><use href="#tile5" fill="#96ffbe" transform="translate(34.185,268.257) scale(-1,1) rotate(-72.001)" class="tiledropped"></use></g></svg>
SVG preview

黄金圍棋?
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
帖子: 6360
注册时间: 2022年 11月 18日 17:36
联系:

Re: 一個新的遊戲創意

帖子 ejsoon »

代码: 全选

<svg id="etmain" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" width="480" height="480"> <defs mode="0" rotatestep="0" rotatestart="0" stepvalue="60" snapto="0" displaywait="1">   <g id="tile0" frontfill="#ff94dc" backfill="#ff94dc"><path d="M -47.124,17.119 L 0,-17.119 L 36,-17.119 L 47.125,17.119 Z"></path></g><g id="tile1" frontfill="#ff94dc" backfill="#ff94dc"><path d="M -58.249,27.699 L 17.999,-27.699 L 47.124,-6.539 L 58.249,27.699 Z"></path></g><g id="tile2" frontfill="#ff94dc" backfill="#ff94dc"><path d="M -41.562,17.119 L 5.562,-17.119 L 41.562,-17.119 L 30.437,17.119 Z"></path></g><g id="tile3" frontfill="#96ffbe" backfill="#96ffbe"><path d="M -47.124,17.119 L 0,-17.119 L 36,-17.119 L 47.125,17.119 Z"></path></g><g id="tile4" frontfill="#96ffbe" backfill="#96ffbe"><path d="M -58.249,27.699 L 17.999,-27.699 L 47.124,-6.539 L 58.249,27.699 Z"></path></g><g id="tile5" frontfill="#96ffbe" backfill="#96ffbe"><path d="M -41.562,17.119 L 5.562,-17.119 L 41.562,-17.119 L 30.437,17.119 Z"></path></g></defs> <g class="etdrop" stroke="#777" stroke-width="2" stroke-linejoin="round" transform="translate(90.885,106.361) scale(0.783)"><g class="etboard"></g><use href="#tile0" fill="#ff94dc" transform="translate(143,164) scale(1,1) rotate(0)" class="tiledropped"></use><use href="#tile3" fill="#96ffbe" transform="translate(143,198.238) scale(-1,1) rotate(180)" class="tiledropped"></use><use href="#tile0" fill="#ff94dc" transform="translate(195.281,220.647) scale(1,1) rotate(-71.999)" class="tiledropped"></use><use href="#tile3" fill="#96ffbe" transform="translate(218.188,139.569) scale(-1,1) rotate(36.001)" class="tiledropped"></use><use href="#tile3" fill="#96ffbe" transform="translate(159.937,111.871) scale(-1,1) rotate(144.002)" class="tiledropped"></use><use href="#tile1" fill="#ff94dc" transform="translate(163.779,78.881) scale(1,1) rotate(-108.002)" class="tiledropped"></use><use href="#tile1" fill="#ff94dc" transform="translate(216.465,61.761) scale(1,1) rotate(71.998)" class="tiledropped"></use><use href="#tile3" fill="#96ffbe" transform="translate(264.652,75.608) scale(-1,1) rotate(72.003)" class="tiledropped"></use><use href="#tile1" fill="#ff94dc" transform="translate(204.025,23.481) scale(1,1) rotate(-108.002)" class="tiledropped"></use><use href="#tile2" fill="#ff94dc" transform="translate(125,215.357) scale(1,1) rotate(72.001)" class="tiledropped"></use><use href="#tile1" fill="#ff94dc" transform="translate(227.844,214.108) scale(1,1) rotate(-35.999)" class="tiledropped"></use><use href="#tile2" fill="#ff94dc" transform="translate(305.812,191.7) scale(1,1) rotate(-144)" class="tiledropped"></use><use href="#tile0" fill="#ff94dc" transform="translate(297.214,86.186) scale(1,1) rotate(107.997)" class="tiledropped"></use><use href="#tile2" fill="#ff94dc" transform="translate(316.936,136.293) scale(1,1) rotate(-72.003)" class="tiledropped"></use><use href="#tile4" fill="#96ffbe" transform="translate(256.711,6.361) scale(-1,1) rotate(-71.998)" class="tiledropped"></use><use href="#tile2" fill="#ff94dc" transform="translate(292.053,-51.059) scale(-1,1) rotate(36.001)" class="tiledropped"></use><use href="#tile5" fill="#96ffbe" transform="translate(321.177,-29.899) scale(-1,1) rotate(-143.999)" class="tiledropped"></use><use href="#tile3" fill="#96ffbe" transform="translate(132.933,22.236) scale(-1,1) rotate(-143.997)" class="tiledropped"></use><use href="#tile5" fill="#96ffbe" transform="translate(186.678,-64.134) scale(-1,1) rotate(108.002)" class="tiledropped"></use><use href="#tile5" fill="#96ffbe" transform="translate(141.679,-36.434) scale(-1,1) rotate(-179.999)" class="tiledropped"></use><use href="#tile3" fill="#96ffbe" transform="translate(363.145,9.63) scale(1,1) rotate(-108)" class="tiledropped"></use><use href="#tile5" fill="#96ffbe" transform="translate(375.988,49.158) scale(1,1) rotate(72)" class="tiledropped"></use><use href="#tile1" fill="#ff94dc" transform="translate(360.769,130.234) scale(1,1) rotate(-71.999)" class="tiledropped"></use><use href="#tile4" fill="#96ffbe" transform="translate(413.455,147.354) scale(-1,1) rotate(-108.001)" class="tiledropped"></use><use href="#tile4" fill="#96ffbe" transform="translate(401.017,185.634) scale(-1,1) rotate(71.999)" class="tiledropped"></use><use href="#tile2" fill="#ff94dc" transform="translate(334.936,212.86) scale(1,1) rotate(36)" class="tiledropped"></use><use href="#tile5" fill="#96ffbe" transform="translate(124.998,283.833) scale(-1,1) rotate(-108.002)" class="tiledropped"></use><use href="#tile2" fill="#ff94dc" transform="translate(99.31,46.667) scale(-1,1) rotate(36.003)" class="tiledropped"></use><use href="#tile3" fill="#96ffbe" transform="translate(36.562,92.261) scale(1,1) rotate(-36.003)" class="tiledropped"></use><use href="#tile4" fill="#96ffbe" transform="translate(66.75,106.109) scale(1,1) rotate(-0.003)" class="tiledropped"></use><use href="#tile1" fill="#ff94dc" transform="translate(66.752,161.507) scale(1,1) rotate(179.997)" class="tiledropped"></use><use href="#tile4" fill="#96ffbe" transform="translate(1.63,195.749) scale(1,1) rotate(-0.003)" class="tiledropped"></use><use href="#tile2" fill="#ff94dc" transform="translate(92.437,225.937) scale(-1,1) rotate(107.999)" class="tiledropped"></use><use href="#tile2" fill="#ff94dc" transform="translate(74.435,281.335) scale(-1,1) rotate(-72.001)" class="tiledropped"></use><use href="#tile5" fill="#96ffbe" transform="translate(45.309,302.495) scale(-1,1) rotate(107.999)" class="tiledropped"></use><use href="#tile5" fill="#96ffbe" transform="translate(34.185,268.257) scale(-1,1) rotate(-72.001)" class="tiledropped"></use><use href="#tile0" fill="#ff94dc" transform="translate(112.153,323.361) scale(-1,1) rotate(71.998)" class="tiledropped"></use><use href="#tile2" fill="#ff94dc" transform="translate(47.433,364.432) scale(1,1) rotate(-36)" class="tiledropped"></use><use href="#tile5" fill="#96ffbe" transform="translate(67.558,392.131) scale(-1,1) rotate(-144)" class="tiledropped"></use><use href="#tile3" fill="#96ffbe" transform="translate(144.715,333.942) scale(1,1) rotate(108.002)" class="tiledropped"></use><use href="#tile4" fill="#96ffbe" transform="translate(115.588,406.458) scale(1,1) rotate(-35.998)" class="tiledropped"></use><use href="#tile3" fill="#96ffbe" transform="translate(198.058,359.621) scale(1,1) rotate(144.002)" class="tiledropped"></use><use href="#tile0" fill="#ff94dc" transform="translate(236.184,331.923) scale(1,1) rotate(-35.998)" class="tiledropped"></use><use href="#tile1" fill="#ff94dc" transform="translate(276.03,271.236) scale(-1,1) rotate(107.999)" class="tiledropped"></use></g></svg>
SVG preview

黄金不規則圍棋
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
帖子: 6360
注册时间: 2022年 11月 18日 17:36
联系:

Re: 一個新的遊戲創意

帖子 ejsoon »

代码: 全选

<svg id="etmain" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" width="480" height="480"> <defs mode="0" rotatestep="0" rotatestart="0" stepvalue="60" snapto="0" displaywait="1">   <g id="tile0" frontfill="#ff94dc" backfill="#ff94dc"><path d="M -47.124,17.119 L 0,-17.119 L 36,-17.119 L 47.125,17.119 Z"></path></g><g id="tile1" frontfill="#ff94dc" backfill="#ff94dc"><path d="M -58.249,27.699 L 17.999,-27.699 L 47.124,-6.539 L 58.249,27.699 Z"></path></g><g id="tile2" frontfill="#ff94dc" backfill="#ff94dc"><path d="M -41.562,17.119 L 5.562,-17.119 L 41.562,-17.119 L 30.437,17.119 Z"></path></g><g id="tile3" frontfill="#96ffbe" backfill="#96ffbe"><path d="M -47.124,17.119 L 0,-17.119 L 36,-17.119 L 47.125,17.119 Z"></path></g><g id="tile4" frontfill="#96ffbe" backfill="#96ffbe"><path d="M -58.249,27.699 L 17.999,-27.699 L 47.124,-6.539 L 58.249,27.699 Z"></path></g><g id="tile5" frontfill="#96ffbe" backfill="#96ffbe"><path d="M -41.562,17.119 L 5.562,-17.119 L 41.562,-17.119 L 30.437,17.119 Z"></path></g></defs> <g class="etdrop" stroke="#777" stroke-width="2" stroke-linejoin="round" transform="translate(-16.593,103.736) scale(1.095)"><g class="etboard"></g><use href="#tile0" fill="#ff94dc" transform="translate(143,164) scale(1,1) rotate(0)" class="tiledropped"></use><use href="#tile3" fill="#96ffbe" transform="translate(143,198.238) scale(-1,1) rotate(180)" class="tiledropped"></use><use href="#tile0" fill="#ff94dc" transform="translate(195.281,220.647) scale(1,1) rotate(-71.999)" class="tiledropped"></use><use href="#tile1" fill="#ff94dc" transform="translate(220.968,124.471) scale(-1,1) rotate(36.001)" class="tiledropped"></use><use href="#tile1" fill="#ff94dc" transform="translate(134.656,100.043) scale(-1,1) rotate(108.001)" class="tiledropped"></use><use href="#tile3" fill="#96ffbe" transform="translate(237.249,95.523) scale(-1,1) rotate(0.001)" class="tiledropped"></use><use href="#tile1" fill="#ff94dc" transform="translate(235.53,45.415) scale(1,1) rotate(144)" class="tiledropped"></use><use href="#tile4" fill="#96ffbe" transform="translate(202.968,0.597) scale(-1,1) rotate(36)" class="tiledropped"></use><use href="#tile3" fill="#96ffbe" transform="translate(124.999,5.887) scale(-1,1) rotate(180)" class="tiledropped"></use><use href="#tile5" fill="#96ffbe" transform="translate(106.999,23.006) scale(1,1) rotate(72.001)" class="tiledropped"></use><use href="#tile1" fill="#ff94dc" transform="translate(227.844,214.108) scale(1,1) rotate(-35.999)" class="tiledropped"></use><use href="#tile4" fill="#96ffbe" transform="translate(282.907,155.442) scale(-1,1) rotate(108)" class="tiledropped"></use><use href="#tile1" fill="#ff94dc" transform="translate(268.092,21.757) scale(1,1) rotate(-36)" class="tiledropped"></use><use href="#tile4" fill="#96ffbe" transform="translate(300.654,66.575) scale(-1,1) rotate(-144)" class="tiledropped"></use><use href="#tile3" fill="#96ffbe" transform="translate(347.778,83.694) scale(1,1) rotate(-71.999)" class="tiledropped"></use><use href="#tile1" fill="#ff94dc" transform="translate(370.278,108.124) scale(-1,1) rotate(107.999)" class="tiledropped"></use><use href="#tile0" fill="#ff94dc" transform="translate(351.214,183.911) scale(-1,1) rotate(-108.001)" class="tiledropped"></use></g></svg>
SVG preview
https://ejsoon.vip/
弈趣極光:享受思維樂趣
回复
  • 相似主题
    回复总数
    阅读次数
    最新帖子

在线用户

正浏览此版面之用户: 没有注册用户 和 49 访客