共享会话
增加功能
分享于 2026年9月8日 23:59增加功能 當在導出中選擇「數字」時,程式應自動調整預覽區中的clone中的g#etanidrop的translate和scale,以使所有棋子都居中顯示在視圖中並留有邊距,就跟「動畫」最後把鏡頭拉到使所有棋子可見一樣。找到跟「動畫」一樣的程式邏輯,套用到「數字」中。
在「數字」導出的svg中,增加一個「記分標誌」,跟「動畫」的最上面最中間的一樣,大小也是48*48,位置默認在右下角,保持一定的邊距(跟棋子與邊的距離一樣)。
在「數字」的右邊增加一個svg圖標按鈕(包含在label內),這個按鈕的圖案是「四個小三角形位於左上、右上、左下、右下」,當點擊時,它將高亮,再次點擊則恢復,當它高亮時,預覽區的「左上、右上、左下、右下」四個地方中的三個(排除記分標誌所在)位置,都將出現一個透明度為0.777的記分標誌,絕對定位在預覽區svg元素的上方,並沒有加進預覽區真實的clone的svg內部,當點擊其中一個半透明的記分標誌,則clone的svg內部真實的記分標誌就會移到那個位置,同時所有的半透明標誌消失,按鈕也不再高亮。這個位置會被記住,下次再導出「數字」則會把標誌顯示在同一位置。
回答要求:請明確給出所要修改的地方和所要替換的代碼。
QuanAI以下修改均針對附件 trigolden_game2668.html。核心做法是:
- 將「動畫」使用的
getDownloadFullView()全景計算抽成可指定可視範圍的共用邏輯。 - 「數字」模式把 clone 中的
g#etanidrop改成全景translate + scale。 - 在「數字」SVG 根節點加入真正的 48×48 記分標誌。
- 在預覽容器上方另外建立三個 HTML 絕對定位按鈕;它們不會進入下載 SVG。
- 使用
localStorage保存記分標誌角落。
一、修改下載預覽區 CSS
找到原本這兩段:
#download-preview {
flex: none;
display: block;
overflow: hidden;
background: white;
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.32);
}
#download-preview object {
display: block;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
border: none;
overflow: hidden;
background: #fff;
}替換成:
#download-preview {
position: relative;
isolation: isolate;
flex: none;
display: block;
overflow: hidden;
background: white;
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.32);
}
#download-preview object {
position: relative;
z-index: 1;
display: block;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
border: none;
overflow: hidden;
background: #fff;
}
/* 「數字」選項內的記分標誌位置按鈕 */
.download-option-number {
padding-right: 7px;
gap: 8px;
}
.download-marker-position-btn {
width: 28px;
height: 28px;
flex: none;
display: inline-flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
border-radius: 50%;
background: rgba(255, 255, 255, 0.06);
color: #9ca4ad;
cursor: pointer;
transition:
color 0.2s,
background 0.2s,
box-shadow 0.2s,
transform 0.12s;
}
.download-marker-position-btn:hover {
color: #fff;
background: rgba(114, 137, 218, 0.28);
}
.download-marker-position-btn:active {
transform: scale(0.9);
}
.download-marker-position-btn:focus-visible {
outline: 2px solid #fff;
outline-offset: 2px;
}
.download-marker-position-btn.active {
color: #fff;
background: #7289da;
box-shadow: 0 0 11px rgba(114, 137, 218, 0.9);
}
.download-marker-position-btn svg {
display: block;
width: 20px;
height: 20px;
fill: currentColor;
pointer-events: none;
}
/*
* 預覽區上方的三個半透明記分標誌。
* 它們是 HTML 按鈕,不屬於預覽 object 內的真實 SVG。
*/
.download-marker-choice {
appearance: none;
position: absolute;
z-index: 3;
width: 10%;
height: 10%;
margin: 0;
padding: 0;
border: none;
outline: none;
background: transparent;
opacity: 0.777;
cursor: pointer;
filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.35));
transition:
filter 0.16s,
transform 0.16s;
}
.download-marker-choice:hover,
.download-marker-choice:focus-visible {
filter:
drop-shadow(0 0 3px rgba(255, 255, 255, 0.95))
drop-shadow(0 0 7px rgba(114, 137, 218, 0.95));
transform: scale(1.08);
}
.download-marker-choice[data-corner='tl'] {
top: 2.5%;
left: 2.5%;
}
.download-marker-choice[data-corner='tr'] {
top: 2.5%;
right: 2.5%;
}
.download-marker-choice[data-corner='bl'] {
bottom: 2.5%;
left: 2.5%;
}
.download-marker-choice[data-corner='br'] {
right: 2.5%;
bottom: 2.5%;
}
.download-marker-choice svg {
display: block;
width: 100%;
height: 100%;
pointer-events: none;
}其中:
48 / 480 = 10%,所以候選標誌尺寸為預覽區的10%。12 / 480 = 2.5%,所以四邊距離為2.5%。- 這和後面棋子全景使用的 12 單位邊距一致。
二、替換「數字」選項的 HTML
找到:
<label class="download-option">
<input type="checkbox" id="download-option-number" onchange="handleDownloadOptionChange('number')" />
<span class="download-checkmark" aria-hidden="true">
<svg viewBox="0 0 24 24">
<path fill="currentColor" d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" />
</svg>
</span>
<span>數字</span>
</label>替換成:
<label class="download-option download-option-number">
<input type="checkbox" id="download-option-number" onchange="handleDownloadOptionChange('number')" />
<span class="download-checkmark" aria-hidden="true">
<svg viewBox="0 0 24 24">
<path fill="currentColor" d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" />
</svg>
</span>
<span>數字</span>
<span
id="download-marker-position-btn"
class="download-marker-position-btn"
role="button"
tabindex="0"
aria-label="選擇記分標誌位置"
aria-pressed="false"
onclick="toggleDownloadMarkerPicker(event)"
onkeydown="handleDownloadMarkerPickerKeydown(event)"
>
<svg viewBox="0 0 24 24" aria-hidden="true">
<!-- 左上 -->
<path d="M3 3h6L3 9z" />
<!-- 右上 -->
<path d="M15 3h6v6z" />
<!-- 左下 -->
<path d="M3 15l6 6H3z" />
<!-- 右下 -->
<path d="M21 15v6h-6z" />
</svg>
</span>
</label>這裡用帶有 role="button" 的 span,避免在 label 中嵌套原生 <button> 所產生的標籤點擊衝突。
三、增加記分標誌狀態與保存位置
找到:
let downloadSvgSource = '';
let downloadSvgBlob = null;
let downloadPreviewUrl = '';替換成:
let downloadSvgSource = '';
let downloadSvgBlob = null;
let downloadPreviewUrl = '';
const DOWNLOAD_NUMBER_MARGIN = 12;
const DOWNLOAD_NUMBER_MARKER_SIZE = 48;
const DOWNLOAD_NUMBER_MARKER_STORAGE_KEY = 'bt-download-number-marker-corner';
const DOWNLOAD_NUMBER_MARKER_CORNERS = new Set(['tl', 'tr', 'bl', 'br']);
function loadDownloadNumberMarkerCorner() {
try {
const savedCorner = localStorage.getItem(DOWNLOAD_NUMBER_MARKER_STORAGE_KEY);
if (DOWNLOAD_NUMBER_MARKER_CORNERS.has(savedCorner)) {
return savedCorner;
}
} catch (error) {
/* file:// 或禁止 localStorage 時,退回本次頁面內保存。 */
}
return 'br';
}
function saveDownloadNumberMarkerCorner() {
try {
localStorage.setItem(DOWNLOAD_NUMBER_MARKER_STORAGE_KEY, downloadNumberMarkerCorner);
} catch (error) {
/* localStorage 不可用時,downloadNumberMarkerCorner 仍會在本頁中保存。 */
}
}
/* 默認右下角。 */
let downloadNumberMarkerCorner = loadDownloadNumberMarkerCorner();
/* 控制四角候選標誌是否顯示。 */
let downloadMarkerPickerOpen = false;
/* 避免同一頁中的漸層 ID 重複。 */
let downloadMarkerGraphicSerial = 0;這樣不但關閉再打開下載窗口後仍會記住位置,重新載入頁面後也會繼續保留。
四、加入記分標誌建立函數和角落選擇功能
在下面這個函數結束後:
function createDownloadSvgElement(tagName, attributes = {}) {
const element = document.createElementNS(DOWNLOAD_SVG_NS, tagName);
Object.entries(attributes).forEach(([name, value]) => {
if (value !== undefined && value !== null) {
element.setAttribute(name, String(value));
}
});
return element;
}緊接著加入:
/*
* 建立和動畫狀態欄中相同圖案的記分標誌。
* 外層是帶 viewBox 的獨立 SVG,因此 width/height 可明確設為 48×48。
*/
function createDownloadScoringMarkerSvg(attributes = {}) {
const markerSvg = createDownloadSvgElement('svg', {
viewBox: '0 0 120 120',
preserveAspectRatio: 'xMidYMid meet',
width: DOWNLOAD_NUMBER_MARKER_SIZE,
height: DOWNLOAD_NUMBER_MARKER_SIZE,
...attributes
});
const defs = createDownloadSvgElement('defs');
const gradientId = `bt-download-score-gradient-${++downloadMarkerGraphicSerial}`;
if (SCORING_MODE === 0) {
const gradient = createDownloadSvgElement('linearGradient', {
id: gradientId,
x1: '0',
y1: '0',
x2: '0',
y2: '1'
});
gradient.appendChild(
createDownloadSvgElement('stop', {
offset: '0%',
'stop-color': '#7289da'
})
);
gradient.appendChild(
createDownloadSvgElement('stop', {
offset: '100%',
'stop-color': '#7289da',
'stop-opacity': '0'
})
);
defs.appendChild(gradient);
markerSvg.appendChild(defs);
markerSvg.appendChild(
createDownloadSvgElement('path', {
d: 'M4,4 L14.397,36 H105.602 L116,4',
fill: 'none',
stroke: '#7289da',
'stroke-width': '4'
})
);
markerSvg.appendChild(
createDownloadSvgElement('polygon', {
points: '32.707,120 60,36 87.293,120',
fill: `url(#${gradientId})`,
stroke: 'none'
})
);
} else {
const gradient = createDownloadSvgElement('linearGradient', {
id: gradientId,
x1: '0',
y1: '0',
x2: '1',
y2: '0'
});
gradient.appendChild(
createDownloadSvgElement('stop', {
offset: '0%',
'stop-color': '#7289da',
'stop-opacity': '0'
})
);
gradient.appendChild(
createDownloadSvgElement('stop', {
offset: '50%',
'stop-color': '#7289da'
})
);
gradient.appendChild(
createDownloadSvgElement('stop', {
offset: '100%',
'stop-color': '#7289da',
'stop-opacity': '0'
})
);
defs.appendChild(gradient);
markerSvg.appendChild(defs);
markerSvg.appendChild(
createDownloadSvgElement('path', {
d: 'M4,4 L14.397,36 H105.602 L116,4 Z',
fill: `url(#${gradientId})`,
stroke: 'none'
})
);
markerSvg.appendChild(
createDownloadSvgElement('path', {
d: 'M32.707,120 L60,36 L87.293,120',
fill: 'none',
stroke: '#7289da',
'stroke-width': '4'
})
);
}
return markerSvg;
}
function getDownloadNumberMarkerPosition(corner = downloadNumberMarkerCorner) {
const near = DOWNLOAD_NUMBER_MARGIN;
const far =
480 -
DOWNLOAD_NUMBER_MARGIN -
DOWNLOAD_NUMBER_MARKER_SIZE;
return {
x: corner.endsWith('r') ? far : near,
y: corner.startsWith('b') ? far : near
};
}
/*
* 加入真正會被序列化及下載的記分標誌。
* 它位於 SVG 根節點,不放進 #etanidrop,因此不受棋盤縮放影響。
*/
function appendDownloadNumberScoringMarker(svg) {
const position = getDownloadNumberMarkerPosition();
const marker = createDownloadScoringMarkerSvg({
id: 'btnumberscoremarker',
x: position.x,
y: position.y,
width: DOWNLOAD_NUMBER_MARKER_SIZE,
height: DOWNLOAD_NUMBER_MARKER_SIZE,
'pointer-events': 'none'
});
svg.appendChild(marker);
}
function updateDownloadMarkerPickerButton() {
const button = document.getElementById('download-marker-position-btn');
if (!button) {
return;
}
const active =
downloadMarkerPickerOpen &&
getDownloadMode() === 'number';
button.classList.toggle('active', active);
button.setAttribute('aria-pressed', active ? 'true' : 'false');
}
function clearDownloadMarkerChoices() {
const preview = document.getElementById('download-preview');
if (!preview) {
return;
}
preview.querySelectorAll('.download-marker-choice').forEach(choice => {
choice.remove();
});
}
/*
* 候選標誌是 #download-preview 的 HTML 子元素,
* 位於 object 上方,不會加入 object 內的 clone SVG。
*/
function renderDownloadMarkerChoices() {
const preview = document.getElementById('download-preview');
clearDownloadMarkerChoices();
updateDownloadMarkerPickerButton();
if (
!preview ||
!downloadMarkerPickerOpen ||
getDownloadMode() !== 'number'
) {
return;
}
['tl', 'tr', 'bl', 'br']
.filter(corner => corner !== downloadNumberMarkerCorner)
.forEach(corner => {
const choice = document.createElement('button');
choice.type = 'button';
choice.className = 'download-marker-choice';
choice.dataset.corner = corner;
choice.setAttribute('aria-label', `把記分標誌移到 ${corner}`);
choice.title = '移動記分標誌';
choice.addEventListener('click', event => {
selectDownloadNumberMarkerCorner(corner, event);
});
choice.appendChild(
createDownloadScoringMarkerSvg({
width: '100%',
height: '100%',
focusable: 'false',
'aria-hidden': 'true'
})
);
preview.appendChild(choice);
});
}
function setDownloadMarkerPickerOpen(open) {
downloadMarkerPickerOpen =
Boolean(open) &&
getDownloadMode() === 'number';
renderDownloadMarkerChoices();
}
function toggleDownloadMarkerPicker(event) {
if (event) {
event.preventDefault();
event.stopPropagation();
}
const numberOption = document.getElementById('download-option-number');
const animateOption = document.getElementById('download-option-animate');
if (!numberOption) {
return;
}
/*
* 如果目前不是數字模式,點位置按鈕時自動切換到數字模式,
* 並直接打開角落選擇。
*/
if (!numberOption.checked) {
numberOption.checked = true;
if (animateOption) {
animateOption.checked = false;
}
downloadMarkerPickerOpen = true;
refreshDownloadPreview();
return;
}
setDownloadMarkerPickerOpen(!downloadMarkerPickerOpen);
}
function handleDownloadMarkerPickerKeydown(event) {
if (event.key !== 'Enter' && event.key !== ' ') {
return;
}
toggleDownloadMarkerPicker(event);
}
function selectDownloadNumberMarkerCorner(corner, event) {
if (event) {
event.preventDefault();
event.stopPropagation();
}
if (!DOWNLOAD_NUMBER_MARKER_CORNERS.has(corner)) {
return;
}
downloadNumberMarkerCorner = corner;
saveDownloadNumberMarkerCorner();
/*
* 選擇後關閉三個候選標誌,取消按鈕高亮,
* 並重建 clone,讓真實記分標誌移到新位置。
*/
downloadMarkerPickerOpen = false;
refreshDownloadPreview();
}五、替換下載選項切換函數
找到:
function handleDownloadOptionChange(changedMode) {
const numberOption = document.getElementById('download-option-number');
const animateOption = document.getElementById('download-option-animate');
if (changedMode === 'number' && numberOption.checked) {
animateOption.checked = false;
}
if (changedMode === 'animate' && animateOption.checked) {
numberOption.checked = false;
}
refreshDownloadPreview();
}替換成:
function handleDownloadOptionChange(changedMode) {
const numberOption = document.getElementById('download-option-number');
const animateOption = document.getElementById('download-option-animate');
if (changedMode === 'number' && numberOption.checked) {
animateOption.checked = false;
}
if (changedMode === 'animate' && animateOption.checked) {
numberOption.checked = false;
}
/*
* 直接切換數字/動畫/普通模式時,
* 關閉角落候選標誌並取消位置按鈕高亮。
*/
downloadMarkerPickerOpen = false;
refreshDownloadPreview();
}六、替換「數字模式」函數
找到完整的:
function addDownloadPieceNumbers(svg) {
prependDownloadFontStyle(svg);
svg.querySelectorAll('.board-marker-dot').forEach(dot => {
dot.remove();
});
const drop = svg.querySelector('.etdrop');
if (!drop) {
return;
}
const uses = getDirectDownloadUses(drop);
const modelPieces = pieces.concat(tempPieces, ghosts);
uses.forEach((useElement, index) => {
const number = index + 1;
const piece = modelPieces[index] || null;
const center = getDownloadPieceCenter(piece, useElement);
const text = createDownloadSvgElement('text', {
x: trimNum(center.x),
y: trimNum(center.y),
stroke: 'none',
fill: '#333',
'font-size': '18',
'font-family': 'Techfont',
'text-anchor': 'middle',
'dominant-baseline': 'central'
});
text.textContent = String(number);
drop.appendChild(text);
});
}替換成:
function addDownloadPieceNumbers(svg) {
prependDownloadFontStyle(svg);
/*
* 數字導出不保留最後落子點、臨時棋子點及目標點。
*/
svg.querySelectorAll('.board-marker-dot').forEach(dot => {
dot.remove();
});
const drop = svg.querySelector('.etdrop');
if (!drop) {
appendDownloadNumberScoringMarker(svg);
return;
}
const uses = getDirectDownloadUses(drop);
const modelPieces = pieces.concat(tempPieces, ghosts);
/*
* 所有 text 最後加入 #etanidrop,
* 確保數字顯示在棋子上方。
*/
uses.forEach((useElement, index) => {
const number = index + 1;
const piece = modelPieces[index] || null;
const center = getDownloadPieceCenter(piece, useElement);
const text = createDownloadSvgElement('text', {
x: trimNum(center.x),
y: trimNum(center.y),
stroke: 'none',
fill: '#333',
'font-size': '18',
'font-family': 'Techfont',
'text-anchor': 'middle',
'dominant-baseline': 'central'
});
text.textContent = String(number);
drop.appendChild(text);
});
/*
* 套用和動畫最後全景相同的邊界計算邏輯。
*
* 數字模式沒有上方 60 高度的動畫狀態欄,
* 因此四邊都保留 12 單位邊距。
*/
const fullView = getDownloadFullView(modelPieces, {
left: DOWNLOAD_NUMBER_MARGIN,
top: DOWNLOAD_NUMBER_MARGIN,
right: 480 - DOWNLOAD_NUMBER_MARGIN,
bottom: 480 - DOWNLOAD_NUMBER_MARGIN
});
/*
* 直接調整 clone 中真實的 g#etanidrop。
* 棋子和數字會一起平移、縮放及居中。
*/
drop.setAttribute(
'transform',
`translate(${trimNum(fullView.tx)},${trimNum(fullView.ty)}) ` +
`scale(${trimNum(fullView.scale, 6)})`
);
/*
* 記分標誌放在 SVG 根節點,固定於所選角落,
* 不跟隨 #etanidrop 縮放。
*/
appendDownloadNumberScoringMarker(svg);
}七、替換動畫全景計算函數,使它也可供「數字」模式使用
找到完整的:
function getDownloadFullView(pieceRecords) {
const points = [];
pieceRecords.forEach(piece => {
if (!piece || !piece.vertices) {
return;
}
piece.vertices.forEach(vertex => {
points.push(exactToScreen(vertex));
});
});
if (points.length === 0) {
return {
tx: 240,
ty: 270,
scale: 1
};
}
let minX = Infinity;
let minY = Infinity;
let maxX = -Infinity;
let maxY = -Infinity;
points.forEach(point => {
minX = Math.min(minX, point.x);
minY = Math.min(minY, point.y);
maxX = Math.max(maxX, point.x);
maxY = Math.max(maxY, point.y);
});
const width = Math.max(1, maxX - minX);
const height = Math.max(1, maxY - minY);
/*
* 左右各保留 12:
* 480 - 24 = 456
*
* 狀態欄下方高度為 420,上下各保留 12:
* 420 - 24 = 396
*/
const fullScale = Math.min(456 / width, 396 / height);
const centerX = (minX + maxX) / 2;
const centerY = (minY + maxY) / 2;
return {
tx: 240 - centerX * fullScale,
ty: 270 - centerY * fullScale,
scale: fullScale
};
}替換成:
/*
* 計算所有棋子的全景鏡頭。
*
* 默認 viewport 保持原動畫模式:
* x = 12..468
* y = 72..468
*
* 即避開上方 60 高度的動畫狀態欄,並在棋子四周保留 12。
*
* 數字模式會傳入:
* x = 12..468
* y = 12..468
*/
function getDownloadFullView(
pieceRecords,
viewport = {
left: 12,
top: 72,
right: 468,
bottom: 468
}
) {
const points = [];
pieceRecords.forEach(piece => {
if (!piece || !piece.vertices) {
return;
}
piece.vertices.forEach(vertex => {
points.push(exactToScreen(vertex));
});
});
const viewportWidth = Math.max(1, viewport.right - viewport.left);
const viewportHeight = Math.max(1, viewport.bottom - viewport.top);
const viewportCenterX = (viewport.left + viewport.right) / 2;
const viewportCenterY = (viewport.top + viewport.bottom) / 2;
if (points.length === 0) {
return {
tx: viewportCenterX,
ty: viewportCenterY,
scale: 1
};
}
let minX = Infinity;
let minY = Infinity;
let maxX = -Infinity;
let maxY = -Infinity;
points.forEach(point => {
minX = Math.min(minX, point.x);
minY = Math.min(minY, point.y);
maxX = Math.max(maxX, point.x);
maxY = Math.max(maxY, point.y);
});
const width = Math.max(1, maxX - minX);
const height = Math.max(1, maxY - minY);
const fullScale = Math.min(
viewportWidth / width,
viewportHeight / height
);
const centerX = (minX + maxX) / 2;
const centerY = (minY + maxY) / 2;
return {
tx: viewportCenterX - centerX * fullScale,
ty: viewportCenterY - centerY * fullScale,
scale: fullScale
};
}原本動畫中的這行:
const fullView = getDownloadFullView(actualPieceRecords);不需要修改。因為新的默認參數仍然是動畫原先的:
- 左右邊距 12
- 上方狀態欄 60
- 狀態欄下再留 12
- 底部邊距 12
- 中心仍然是
(240, 270)
八、讓預覽刷新後顯示三個候選標誌
在 refreshDownloadPreview() 中找到:
preview.appendChild(object);
requestAnimationFrame(fitDownloadPreview);替換成:
preview.appendChild(object);
/*
* 候選標誌加入預覽容器,而不是加入 object 內的 SVG。
*/
renderDownloadMarkerChoices();
requestAnimationFrame(fitDownloadPreview);完整位置應該是:
const object = document.createElement('object');
object.type = 'image/svg+xml';
object.data = downloadPreviewUrl;
object.setAttribute('aria-label', '下載 SVG 預覽');
preview.appendChild(object);
/*
* 候選標誌加入預覽容器,而不是加入 object 內的 SVG。
*/
renderDownloadMarkerChoices();
requestAnimationFrame(fitDownloadPreview);九、關閉下載窗口時取消高亮和候選標誌
在 closeDownloadDialog() 中找到:
dialog.style.display = 'none';
if (preview) {替換成:
dialog.style.display = 'none';
downloadMarkerPickerOpen = false;
updateDownloadMarkerPickerButton();
if (preview) {修改後完整函數為:
function closeDownloadDialog() {
const dialog = document.getElementById('download-dialog');
const preview = document.getElementById('download-preview');
dialog.style.display = 'none';
downloadMarkerPickerOpen = false;
updateDownloadMarkerPickerButton();
if (preview) {
preview.replaceChildren();
preview.style.width = '';
preview.style.height = '';
}
releaseDownloadPreviewUrl();
downloadSvgSource = '';
downloadSvgBlob = null;
}修改後的行為
-
選中「數字」:
- clone 中的
g#etanidrop自動修改為全景translate + scale。 - 所有正式棋子、臨時棋子和目前顯示的 ghost 都會納入邊界計算。
- 棋子整體在 480×480 視圖中居中,四周保留 12 單位邊距。
- 右下角加入真正的 48×48 記分標誌。
- clone 中的
-
點擊「數字」右側的四角按鈕:
- 按鈕高亮。
- 除真實記分標誌所在角落外,其餘三個角落顯示透明度
0.777的候選標誌。 - 三個候選標誌位於
#download-preview上方,不會序列化到下載 SVG。
-
點擊任意候選標誌:
- 保存新角落。
- 重建下載 SVG。
- 真實的
#btnumberscoremarker移到新位置。 - 三個候選標誌消失。
- 四角按鈕取消高亮。
-
再次點擊已高亮的四角按鈕:
- 直接關閉候選標誌並恢復非高亮狀態。
-
記分標誌位置:
- 使用
localStorage保存。 - 下次打開「數字」導出時仍使用上次選擇的位置。
- 使用