I'm trying to make a dynamic Javascript digital clock with text art numbers. Since the numbers are text art they are multi-line strings and appear on top of eachother when logged to the console. The example is below.

let time0 =`
 a8888a  
d8' ..8b 
88 .P 88 
88 d' 88 
Y8'' .8P 
 Y8888P`
let time1 =`
d88  
 88  
 88  
 88  
 88  
d88P`

I want the output to be for example 12:03:52 p.m. in the text art, but instead it is on top of eachother sorta like this

1
2
:
...

5 Answers

0
Jonas Wilms On

You could merge all the letters into one large chunk:

 function mergeDigits(...digits) {
  const result = [];

  for(const digit of digits) {
   for(const [index, row] of digit.split("\n").entries())
      result[index] = (result[index] || "") + row + " ".repeat(10 - row.length);
  }

  return result.join("\n");
}

console.log(mergeDigits(time0, time1));
0
nvioli On

My approach would be to convert the strings to arrays by splitting them on the newline character (\n), then logging one row at a time:

let time0 =`
 a8888a  
d8' ..8b 
88 .P 88 
88 d' 88 
Y8'' .8P 
 Y8888P  `.split('\n')
let time1 =`
d88  
 88  
 88  
 88  
 88  
d88P`.split('\n')


for (let i = 1; i < time0.length; i++) {
  console.log(time0[i] + '  ' + time1[i]);
}

0
Community On

I recommend create a function that joins the numbers, here an example:

    let time0 =`
     a8888a  
    d8' ..8b 
    88 .P 88 
    88 d' 88 
    Y8'' .8P 
     Y8888P  `;
    let time1 =`
    d88  
     88  
     88  
     88  
     88  
    d88P`;

    function concat(number1, number2) {
       var parts1 = number1.split('\n');
       var parts2 = number2.split('\n');
       var result = [];
       parts1.forEach((line, index)=>{
           var line2 = parts2[index] || '';
           result.push(line + ' ' + line2);
       });
       return result.join('\n');
    }
    var result = concat(time0, time1);
    console.log(result)

0
trincot On

I would suggest this function. It looks for the height of the patterns, the widths of each line in each pattern, in order to ensure a correct aligning:

function joinPatterns(...args) {
    const patterns = args.map(pat => pat.split(/[\n\r]+/));
    const widths = patterns.map(lines => Math.max(...lines.map(line => line.length)));
    const length = Math.max(...patterns.map(lines => lines.length));
    return Array.from({length}, (_, i) =>
        patterns.map((lines, j) => (lines[i]||"").padEnd(widths[j], " ")).join(" ")
    ).join("\n");
}

let time0 =`
 a8888a  
d8' ..8b 
88 .P 88 
88 d' 88 
Y8'' .8P 
 Y8888P`
let time1 =`
d88  
 88  
 88  
 88  
 88  
d88P`

const res = joinPatterns(time0, time1, time0);

console.log(res);

0
Scott Sauyet On

This version starts with a character mapping and the number of spaces to place between them and returns a function which takes a string, splits it into characters and creates a combined text art string from them. Note that it doesn't care what the characters are. It does not do any error checking to ensure that all the characters exist, and that they are the same height. That would not be hard to add.

const formatChars = (chars, spacing) => {
  const cs = Object.entries(chars)
    .map(([k, c]) => [k, c.split('\n')])
    .reduce((a, [k, c]) => ({...a, [k]: c}), {})
  return (str) => 
    ('' + str).split('').map(c => cs[c])
    .reduce((c1, c2) => {
      const width = Math.max(...c1.map(c => c.length)) + spacing
      return c1.map((c, i) => c.padEnd(width, ' ') + c2[i])
    }).join('\n')
}

const chars = {
  '0': `
 a8888a  
d8' ..8b 
88 .P 88 
88 d' 88 
Y8'' .8P 
 Y8888P  `,
  '1': `
d88  
 88  
 88  
 88  
 88  
d88P`
}

console.log(formatChars(chars, 1)('11010'))
console.log(formatChars(chars, 4)('11010'))

A very interesting variant on this, if you only care about the digits 0 - 9, would be to start by parsing a more complete version of this:

 a8888a   d88  
d8' ..8b   88  
88 .P 88   88  
88 d' 88   88  
Y8'' .8P   88  
 Y8888P   d88P