122 lines
3.2 KiB
HTML
122 lines
3.2 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<style>
|
|
* { margin: 0; padding: 0; }
|
|
body { background: transparent; overflow: hidden; }
|
|
canvas { display: block; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<canvas id="c"></canvas>
|
|
<script>
|
|
var canvas = document.getElementById('c');
|
|
var ctx = canvas.getContext('2d');
|
|
|
|
var TEX_SIZE = 512;
|
|
canvas.width = TEX_SIZE;
|
|
canvas.height = TEX_SIZE;
|
|
|
|
// UV islands span Y: 0.15 to 0.85 (centered, 70% of texture height)
|
|
var CARD_TOP = Math.round(TEX_SIZE * 0.15); // 77px
|
|
var CARD_BOTTOM = Math.round(TEX_SIZE * 0.85); // 435px
|
|
var CARD_H = CARD_BOTTOM - CARD_TOP; // 358px
|
|
var CARD_W = TEX_SIZE / 2; // 256px each
|
|
|
|
var SUITS = { '♠': '#1a1a2e', '♣': '#1a1a2e', '♥': '#cc2222', '♦': '#cc2222' };
|
|
|
|
function drawCard(xOffset, rank, suit) {
|
|
var col = SUITS[suit] || '#1a1a2e';
|
|
var w = CARD_W;
|
|
var h = CARD_H;
|
|
var r = 10;
|
|
var p = 12;
|
|
|
|
ctx.save();
|
|
ctx.translate(xOffset, CARD_TOP);
|
|
|
|
// Card background
|
|
ctx.beginPath();
|
|
ctx.moveTo(r, 0);
|
|
ctx.lineTo(w - r, 0);
|
|
ctx.quadraticCurveTo(w, 0, w, r);
|
|
ctx.lineTo(w, h - r);
|
|
ctx.quadraticCurveTo(w, h, w - r, h);
|
|
ctx.lineTo(r, h);
|
|
ctx.quadraticCurveTo(0, h, 0, h - r);
|
|
ctx.lineTo(0, r);
|
|
ctx.quadraticCurveTo(0, 0, r, 0);
|
|
ctx.closePath();
|
|
ctx.fillStyle = '#ffffff';
|
|
ctx.fill();
|
|
ctx.strokeStyle = '#d0d0d0';
|
|
ctx.lineWidth = 1;
|
|
ctx.stroke();
|
|
|
|
ctx.fillStyle = col;
|
|
|
|
// Top-left rank
|
|
ctx.font = 'bold 36px Georgia, serif';
|
|
ctx.textBaseline = 'top';
|
|
ctx.textAlign = 'left';
|
|
ctx.fillText(rank, p, p);
|
|
|
|
// Suit below rank top-left
|
|
ctx.font = '26px Georgia, serif';
|
|
ctx.fillText(suit, p, p + 40);
|
|
|
|
// Bottom-right flipped
|
|
ctx.save();
|
|
ctx.translate(w, h);
|
|
ctx.rotate(Math.PI);
|
|
ctx.font = 'bold 36px Georgia, serif';
|
|
ctx.textBaseline = 'top';
|
|
ctx.textAlign = 'left';
|
|
ctx.fillText(rank, p, p);
|
|
ctx.font = '26px Georgia, serif';
|
|
ctx.fillText(suit, p, p + 40);
|
|
ctx.restore();
|
|
|
|
// Center suit
|
|
ctx.font = '110px Georgia, serif';
|
|
ctx.textAlign = 'center';
|
|
ctx.textBaseline = 'middle';
|
|
ctx.fillText(suit, w / 2, h / 2);
|
|
|
|
ctx.restore();
|
|
}
|
|
|
|
function render(card1, card2) {
|
|
// Clear with transparent background
|
|
ctx.clearRect(0, 0, TEX_SIZE, TEX_SIZE);
|
|
|
|
drawCard(0, card1.rank, card1.suit);
|
|
drawCard(CARD_W, card2.rank, card2.suit);
|
|
|
|
var dataURI = canvas.toDataURL('image/png');
|
|
if (typeof EventBridge !== 'undefined') {
|
|
EventBridge.emitWebEvent(JSON.stringify({
|
|
type: 'cardTexture',
|
|
dataURI: dataURI,
|
|
}));
|
|
}
|
|
}
|
|
|
|
if (typeof EventBridge !== 'undefined') {
|
|
EventBridge.scriptEventReceived.connect(function(data) {
|
|
try {
|
|
var msg = JSON.parse(data);
|
|
if (msg.type === 'dealCards') {
|
|
render(msg.card1, msg.card2);
|
|
} else if (msg.type === 'ready') {
|
|
EventBridge.emitWebEvent(JSON.stringify({ type: 'rendererReady' }));
|
|
}
|
|
} catch(e) {}
|
|
});
|
|
// Signal ready on load
|
|
EventBridge.emitWebEvent(JSON.stringify({ type: 'rendererReady' }));
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|