Skip to content

Commit

Permalink
add letter and line spacing
Browse files Browse the repository at this point in the history
  • Loading branch information
nclslbrn committed May 31, 2024
1 parent 5ae1add commit 26ce468
Show file tree
Hide file tree
Showing 8 changed files with 2,339 additions and 947 deletions.
3 changes: 2 additions & 1 deletion demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
<footer>
<p>
<a href="https://github.com/nclslbrn/plot-writer"> Plot-writer </a>
MIT License
MIT License -
<a href="https://nicolas-lebrun.fr">Nicolas Lebrun &#60;@nclslbrn&#62;</a>
</p>
</footer>
<script type="module" src="./src/index.ts"></script>
Expand Down
16 changes: 10 additions & 6 deletions demo/src/field.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
export type OnChange = (name: string, val: boolean | string | number) => void;

const trueFalseCheckbox = (name: string, val: boolean, parent: HTMLElement, onchange: OnChange) => {
const fieldset = document.createElement('fieldset');

const field = document.createElement('input');
field.type = 'checkbox';

Expand All @@ -16,8 +18,9 @@ const trueFalseCheckbox = (name: string, val: boolean, parent: HTMLElement, onch
onchange(name, false);
}
});
parent.appendChild(label);
parent.appendChild(field);
fieldset.appendChild(label);
fieldset.appendChild(field);
parent.appendChild(fieldset);
};

const inputRange = (
Expand All @@ -29,12 +32,13 @@ const inputRange = (
max?: number,
step?: number
) => {
const fieldset = document.createElement('fieldset');
const field = document.createElement('input');
field.type = 'range';
field.value = `${val}`;
if (min) field.min = `${min}`;
if (max) field.max = `${max}`;
if (step) field.step = `${step}`;
field.value = `${val}`;

const label = document.createElement('label');
label.innerText = name;
Expand All @@ -43,14 +47,14 @@ const inputRange = (
label.innerText = name + ' ' + field.value;
onchange(name, parseFloat(field.value));
});
parent.appendChild(label);
parent.appendChild(field);
fieldset.appendChild(label);
fieldset.appendChild(field);
parent.appendChild(fieldset);
};

const textarea = (name: string, val: string, parent: HTMLElement, onchange: OnChange) => {
const field = document.createElement('textarea');
field.value = val;

field.addEventListener('input', () => onchange(name, field.value));
parent.appendChild(field);
};
Expand Down
48 changes: 31 additions & 17 deletions demo/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
import { type Char, getGlyphPath, getParagraphPath } from '../../src/index.ts';
import { trueFalseCheckbox, inputRange, textarea, button } from './field.ts';
import { inputRange, textarea, button } from './field.ts';
import { togglablePanel } from './panel.ts';
import { name, version } from '../../package.json';
import quotes from './quotes.ts';

const app = document.getElementById('app'),
header = document.createElement('header'),
[settingsPanel, openSettingsPanel] = togglablePanel(false, 'settings'),
[settingsPanel, openSettingsPanel] = togglablePanel(false, '☰', '✖'),
namespace = 'http://www.w3.org/2000/svg',
svg = document.createElementNS(namespace, 'svg'),
settings = {
Text: quotes[Math.floor(Math.random() * quotes.length)],
'Char per line': 32,
'Letter spacing': 0.8,
'Line spacing': 0.8,
'Letters per line': 60,
'Letter spacing': 1,
'Line spacing': 0.92,
},
group = document.createElementNS(namespace, 'g');

console.log(settings.Text);
const pathFromD = (d: string): SVGPathElement => {
const path = document.createElementNS(namespace, 'path');
path.setAttribute('d', d);
Expand All @@ -26,17 +25,16 @@ const pathFromD = (d: string): SVGPathElement => {

const init = () => {
if (app === null) return;

app.appendChild(header);
app.appendChild(settingsPanel);

const svgLogo = svg.cloneNode(true),
logoGlyphSize = [window.innerWidth / 46, 40],
logoGlyphSize = [window.innerWidth / 100, 48],
logoText = `${name.replace('@nclslbrn/', '')}: ${version}`;

([...logoText] as Array<Char>).forEach((l: Char, x: number) => {
// prevent empty space
if (l !== ' ') {
// prevent empty space
const line = getGlyphPath(l, logoGlyphSize, [x * logoGlyphSize[0], 0]);
line.forEach((d: string) => svgLogo.appendChild(pathFromD(d)));
}
Expand All @@ -45,23 +43,31 @@ const init = () => {
header.appendChild(openSettingsPanel);

textarea('Text', settings.Text, settingsPanel, updateSettings);
inputRange('Char per line', settings['Char per line'], settingsPanel, updateSettings, 12, 120, 1);
inputRange(
'Letters per line',
settings['Letters per line'],
settingsPanel,
updateSettings,
12,
120,
1
);
inputRange(
'Letter spacing',
settings['Letter spacing'],
settingsPanel,
updateSettings,
0.6,
1.2,
0.7,
1.4,
0.01
);
inputRange(
'Line spacing',
settings['Line spacing'],
settingsPanel,
updateSettings,
0.7,
1.3,
0.5,
1.4,
0.01
);
button('Download SVG', settingsPanel, download);
Expand All @@ -74,6 +80,9 @@ const init = () => {
svg.appendChild(group);
app.appendChild(svg);
render();
window.onresize = () => {
setTimeout(render, 600);
};
};

const download = () => {
Expand All @@ -99,14 +108,19 @@ const render = () => {
width = window.innerWidth - 40;

group.textContent = '';
getParagraphPath(userInput, settings['Char per line'], 5, width).forEach((d: string) => {
const textBlock = getParagraphPath(userInput, settings['Letters per line'], 5, width, [
settings['Letter spacing'],
settings['Line spacing'],
]);
textBlock.paths.forEach((d: string) => {
const path = document.createElementNS(namespace, 'path');
path.setAttribute('d', d);
group.appendChild(path);
});
group.setAttribute('stroke-width', '2');

//group.setAttribute('stroke-width', width < 800 ? '0.5' : '2');
svg.setAttribute('width', `${width}`);
svg.setAttribute('height', `${height + 40}`);
svg.setAttribute('height', `${textBlock.height + 40}`);
svg.setAttribute('viewbox', `0 0 ${width} ${height + 40}`);
};

Expand Down
24 changes: 11 additions & 13 deletions demo/src/panel.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
const togglablePanel = (open: boolean, purpose: string) => {
const elem = document.createElement("div");
elem.classList.add("panel");
if (open) elem.classList.add("open");
const togglablePanel = (open: boolean, openText: string, closeText: string) => {
const elem = document.createElement('div');
elem.classList.add('panel');
if (open) elem.classList.add('open');

const toggle = document.createElement("button");
toggle.innerText = `open ${purpose}`;
const toggle = document.createElement('button');
toggle.innerText = openText;

//parent.appendChild(elem);

toggle.addEventListener("click", () => {
toggle.addEventListener('click', () => {
open = !open;
if (open) {
toggle.innerText = `close ${purpose}`;
elem.classList.add("open");
toggle.innerText = closeText;
elem.classList.add('open');
} else {
toggle.innerText = `open ${purpose}`;
elem.classList.remove("open");
toggle.innerText = openText;
elem.classList.remove('open');
}
});

Expand Down
77 changes: 55 additions & 22 deletions demo/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ footer {
#app header {
position: relative;
justify-content: space-between;
background: linear-gradient(to bottom, #ffffff, #d9d6d6);
background: linear-gradient(to bottom, #333, #111);
width: 100%;
}

Expand All @@ -61,15 +61,18 @@ footer {

#app .panel {
display: flex;
flex-flow: column wrap;
flex-flow: row wrap;
padding-top: 2em;
padding-bottom: 2em;
max-height: 25vh;
transform: translateY(-25vh);
padding-bottom: 0.5em;
max-height: 50vh;
transform: translateY(-50vh);
overflow-y: hidden;
height: 0;
border: 1px solid #b0b0b0;
background: #eeeeee;
background: linear-gradient(to bottom, #c3c3c3, #f1f1f1);
transition: transform 0.5 ease-in-out;
overflow-y: auto;
}

#app .panel.open {
Expand All @@ -82,34 +85,63 @@ footer p {
text-align: center;
}

#app header svg,
#app header button {
#app .panel fieldset {
padding: 0;
margin: 0;
border: 0;
flex: 100%;
max-width: 100%;
}

#app .panel fieldset label,
#app .panel fieldset input,
#app .panel button {
display: block;
padding: 2px 4px;
border: none;
width: 90%;
margin: 1em 5% 2em 5%;
text-align: center;
}

#app .panel button {
padding: 1em 0;
}

@media only screen and (min-width: 960px) {
#app .panel fieldset {
flex: 33.33%;
max-width: 33%;
}
}

#app header svg {
width: 80%;
padding-left: 2em;
max-height: 40px;
max-height: 48px;

fill: #00000000;
stroke: #000;
stroke: #ccc;
stroke-width: 0.1vw;
}

#app header button {
width: 20%;
padding-right: 2em;
background: #fefefe;
margin: 8px;
width: 38px;
}

#app button {
border: 1px solid #ccc;
background: #000;
color: #fff;
}

#app header button:hover {
background: royalblue;
color: royalblue;
border-color: royalblue;
}

#app header button:focus {
background: steelblue;
color: steelblue;
border-color: steelblue;
}

#app svg {
Expand All @@ -136,12 +168,13 @@ footer p {
stroke-width: 0;
}

@media screen and (min-width: 900px) {
#app header textarea {
display: block;
font-size: 1.4em;
padding: 0.4em;
}
#app .panel > textarea {
display: block;
position: relative;
width: 100%;
font-size: 1.4em;
padding: 0.4em;
height: 200px;
}

footer {
Expand Down
7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@
"license": "MIT",
"devDependencies": {
"@types/node": "^20.12.7",
"eslint-plugin-prettier": "^5.1.3",
"prettier": "^3.2.5",
"typescript": "^5.4.5",
"vite": "^5.2.10",
"prettier": "^3.2.5",
"eslint-plugin-prettier": "^5.1.3",
"vite-plugin-dts": "^3.9.0"
},
"publishConfig": {
Expand All @@ -60,6 +60,5 @@
"engines": {
"node": ">=16"
},
"dependencies": {
}
"packageManager": "[email protected]"
}
Loading

0 comments on commit 26ce468

Please sign in to comment.