Skip to content

Instantly share code, notes, and snippets.

@PhoenixIllusion
Created May 29, 2020 19:28
Show Gist options
  • Save PhoenixIllusion/ca10ad82a05b41e5654ce0b329f12ddd to your computer and use it in GitHub Desktop.
Save PhoenixIllusion/ca10ad82a05b41e5654ce0b329f12ddd to your computer and use it in GitHub Desktop.
Allows editing and saving Bingo Cards
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.slim.js"></script>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" viewport="0 0 410 510" width="410" height="510" style="width: 100vw;max-width:600px;">
<style>
text {
font-family: sans-serif;
font-weight: bold;
}
.header {
font-size: 40px;
text-anchor: middle;
}
</style>
<defs>
<g id="tile" class="tile" onclick="updateText(this, 60)">
<path style="stroke: black;stroke-width: 5;fill:none;"
d="M 0,0 h80 v80 h-80 Z"></path>
<text x="40" y="40" style="font-size: 10px" text-anchor="middle">ENTER TEXT</text>
</g>
<g id="star">
<path style="stroke: black;stroke-width: 5;fill:none;"
d="M 0,0 h80 v80 h-80 Z"></path>
<path d="m55,237 74-228 74,228L9,96h240" transform="scale(.3)"/>
</g>
</defs>
<rect x="0" y="0" width="100%" height="100%" fill="white"></rect>
<g transform="translate(5,5)" id="board">
<text class="header" y="85" x="40">B</text>
<text class="header" y="85" x="120" >I</text>
<text class="header" y="85" x="200" >N</text>
<text class="header" y="85" x="280" >G</text>
<text class="header" y="85" x="360" >O</text>
<path style="stroke: black;stroke-width: 5px;fill: none;"
d="
M 0,0 h400 v500 h-400 Z
M 0,100 h400"></path>
</g>
</svg>
<hr />
<a id="savePNG" href="#" download="BINGO.jpg" >SAVE AS PNG</a><br />
<a id="saveSVG" href="#" download="BINGO.svg" >SAVE AS SVG</a>
</body>
<script type="text/javascript">
const board=document.querySelector('#board');
function updateText(ele, width) {
ele.text = prompt("Enter Text", ele.text);
const text = $(ele).find('text');
let y = text.attr("y");
let x = text.attr("x");
let dy = parseFloat( text.attr("dy") || 0 );
let tspan = $(document.createElementNS("http://www.w3.org/2000/svg",'tspan')).attr("x", x).attr("y", y).attr("dy", dy + "em");
text.text('').append(tspan);
let words = ele.text.split(/\s+/).reverse();
let line = [];
let word;
let lineNumber = 0;
let lineHeight = 1.1;
let spans = [tspan];
while ( word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.get(0).getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = $(document.createElementNS("http://www.w3.org/2000/svg",'tspan')).attr("x", x).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
spans.push(tspan);
text.append(tspan);
}
}
let maxSpan = parseFloat(tspan.attr('dy').replace('em',''));
spans.forEach(span => {
let dy = parseFloat(span.attr('dy').replace('em',''));
span.attr('dy', (dy-maxSpan/3)+'em');
});
save();
}
function loadSVG() {
return new Promise(resolve => {
const svg = document.querySelector('svg');
// get svg data
const xml = new XMLSerializer().serializeToString(svg);
// make it base64
const svg64 = btoa(xml);
const b64Start = 'data:image/svg+xml;base64,';
// prepend a "header"
const image64 = b64Start + svg64;
const anchor = document.querySelector('#saveSVG');
anchor.href = image64;
// set it as the source of the img element
const img = document.createElement('img');
img.onload = function() {
// draw the image onto the canvas
resolve(img);
}
img.src = image64;
})
}
async function save() {
const anchor = document.querySelector('#savePNG');
const canvas = document.createElement('canvas');
const svg = await loadSVG();
canvas.width = svg.width*1.5;
canvas.height = svg.height*1.5;
const ctx = canvas.getContext('2d');
ctx.drawImage(svg,0,0,canvas.width,canvas.height);
anchor.href = canvas.toDataURL();
}
for(let x=0;x<5;x++) {
for(let y=0;y<5;y++) {
let xId = '#tile';
if(x==2 && y==2) {
xId = '#star';
}
const use = document.querySelector(xId).cloneNode(true);
use.setAttribute('transform',`translate(${x*80},${y*80+100})`)
use.text = 'ENTER TEXT';
board.appendChild(use);
}
}
save();
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment