Document

 

Y2xhc3MgS29rYWNQNUV4dCB7CiAgICN0YXNrcyA9IG5ldyBNYXAoKTsKICAgYWRkKHYpIHsKICAgICAgdGhpcy4jdGFza3Muc2V0KHYpOwogICB9CiAgIHJlbW92ZSh2KSB7CiAgICAgIHRoaXMuI3Rhc2tzLmRlbGV0ZSh2KTsKICAgfQogICBnZXQgaXRlcmF0b3IoKSB7CiAgICAgIHJldHVybiB0aGlzLiN0YXNrcy5rZXlzKCk7CiAgIH0KICAgZGVsYXkocykgewogICAgICBpZiAoIXMpIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlKSk7CiAgICAgIGxldCB3YWl0ZXIgPSB7fTsKICAgICAgdGhpcy5hZGQod2FpdGVyKTsKICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7CiAgICAgICAgIHdhaXRlci51cGRhdGUgPSAoKSA9PiB7CiAgICAgICAgICAgIGlmICgtLXMgPiAwKSByZXR1cm47CiAgICAgICAgICAgIHRoaXMucmVtb3ZlKHdhaXRlcik7CiAgICAgICAgICAgIHJlc29sdmUoKTsKICAgICAgICAgfTsKICAgICAgfSk7CiAgIH0KICAgc3RlcCgpIHsKICAgICAgY29uc3QgeyBpdGVyYXRvciB9ID0gdGhpczsKICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICAgbGV0IG50ID0gaXRlcmF0b3IubmV4dCgpOwogICAgICAgICBpZiAobnQuZG9uZSkgYnJlYWs7CiAgICAgICAgIGxldCB7IHZhbHVlIH0gPSBudDsKICAgICAgICAgaWYgKHZhbHVlLmNvbnN0cnVjdG9yID09PSBGdW5jdGlvbikgewogICAgICAgICAgICB2YWx1ZSgpOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgfQogICAgICAgICB2YWx1ZS51cGRhdGUgJiYgdmFsdWUudXBkYXRlKCk7CiAgICAgICAgIHZhbHVlLnJlZHJhdyAmJiB2YWx1ZS5yZWRyYXcoKTsKICAgICAgfQogICB9CiAgIHRleHQoc3RyaW5nLCB4eCwgeXksIHNpemUsIGZvbnQpIHsKICAgICAgbGV0IGluZm8gPSB0aGlzLnRleHRCb3VuZHMoc3RyaW5nLCB4eCwgeXksIHNpemUsIGZvbnQpOwogICAgICB0ZXh0Rm9udChpbmZvLmZvbnQpOwogICAgICB0ZXh0U2l6ZShpbmZvLnNpemUpOwogICAgICB0ZXh0KGluZm8uc3RyaW5nLCBpbmZvLngsIGluZm8ueSk7CiAgIH0KICAgdGV4dEJvdW5kcyhzdHJpbmcsIHh4LCB5eSwgc2l6ZSwgZm9udCkgewogICAgICBsZXQgbXlGb250ID0gZm9udDsKICAgICAgbGV0IHRleHQxID0gc3RyaW5nOwogICAgICBsZXQgZm9udFNpemVTbWFsbCA9IHNpemU7CiAgICAgIGxldCB4ID0geHg7CiAgICAgIGxldCB5ID0geXk7CiAgICAgIGxldCBib3VuZGluZ19ib3ggPSBteUZvbnQudGV4dEJvdW5kcyh0ZXh0MSwgeCwgeSwgZm9udFNpemVTbWFsbCk7CiAgICAgIHggLT0gYm91bmRpbmdfYm94Lng7CiAgICAgIHkgLT0gYm91bmRpbmdfYm94Lnk7CiAgICAgIHJldHVybiB7CiAgICAgICAgIHg6IHggKyB4eCwKICAgICAgICAgeTogeSArIHl5LAogICAgICAgICBzaXplOiBmb250U2l6ZVNtYWxsLAogICAgICAgICBmb250OiBteUZvbnQsCiAgICAgICAgIHN0cmluZzogc3RyaW5nLAogICAgICAgICByZWN0OiB7CiAgICAgICAgICAgIHg6IHggKyBib3VuZGluZ19ib3gueCwKICAgICAgICAgICAgeTogeSArIGJvdW5kaW5nX2JveC55LAogICAgICAgICAgICB3OiBib3VuZGluZ19ib3gudywKICAgICAgICAgICAgaDogYm91bmRpbmdfYm94LmgsCiAgICAgICAgIH0sCiAgICAgIH07CiAgIH0KfQpmdW5jdGlvbiBkcmF3KCkgewogICBrb2thYy5zdGVwKCk7Cn0KCgpjb25zdCBrb2thYyA9IG5ldyBLb2thY1A1RXh0KCk7CgpsZXQgbXlGb250OwpmdW5jdGlvbiBwcmVsb2FkKCkgewogICBteUZvbnQgPSBsb2FkRm9udCgiaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L2doL2tzdG9zdC9Lb2thY1A1RXh0L3NyYy9mb250cy9Ob3RvU2Fuc0tSLUJvbGQub3RmIik7Cn0KYXN5bmMgZnVuY3Rpb24gc2V0dXAoKSB7CiAgIC8vIOuhnOyngeydgCBzZXR1cCDslYjsl5DshJzrp4wg7IaQIOuMgOuptCDrkJjrj4TroZ0g7L2U65Oc66W8IOq1rOyEse2VqAogICBsZXQgc2l6ZVdpZHRoID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcigiI3N0ZyIpLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoOwogICBsZXQgc2l6ZUhlaWdodCA9IHNpemVXaWR0aCAqIC41OwogICAvLyBzaXplV2lkdGggPSBpbm5lcldpZHRoOwogICAvLyBzaXplSGVpZ2h0ID0gaW5uZXJIZWlnaHQ7CiAgIGNyZWF0ZUNhbnZhcyhzaXplV2lkdGgsIHNpemVIZWlnaHQpOwogICBub1N0cm9rZSgpOwogICBrb2thYy5hZGQoKGUpID0+IGJhY2tncm91bmQoMjApKTsKICAga29rYWMuYWRkKChlKSA9PiB7CiAgICAgIGZpbGwoIiMwMGRkMDAiKTsKICAgICAga29rYWMudGV4dChgYWJjXG5kZWZcbu2VnOq4gGAsIDEwLCAwLCAxMzAsIG15Rm9udCk7CiAgIH0pOwogICAvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgIGNsYXNzIE1vdGhlciB7CiAgICAgIGNvbnN0cnVjdG9yKCkgewogICAgICAgICB0aGlzLnggPSAwOwogICAgICAgICB0aGlzLnkgPSAwOwogICAgICAgICB0aGlzLnIgPSAyMDsKICAgICAgICAgdGhpcy5hbHBoYSA9IDA7CiAgICAgICAgIHRoaXMuYWxwaGFUb2dnbGUgPSBmYWxzZTsKICAgICAgfQogICAgICB1cGRhdGUoKSB7CiAgICAgICAgIHRoaXMueCArPSAwLjE7CiAgICAgICAgIGlmICghdGhpcy5hbHBoYVRvZ2dsZSkgewogICAgICAgICAgICB0aGlzLmFscGhhKys7CiAgICAgICAgICAgIGlmICh0aGlzLmFscGhhID49IDI1NSkgdGhpcy5hbHBoYVRvZ2dsZSA9ICF0aGlzLmFscGhhVG9nZ2xlOwogICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB0aGlzLmFscGhhLS07CiAgICAgICAgICAgIGlmICh0aGlzLmFscGhhIDw9IDApIHRoaXMuYWxwaGFUb2dnbGUgPSAhdGhpcy5hbHBoYVRvZ2dsZTsKICAgICAgICAgfQogICAgICB9CiAgICAgIHJlZHJhdygpIHsKICAgICAgICAgZmlsbCgyNTUsIDAsIDAsIHRoaXMuYWxwaGEpOwogICAgICAgICBjaXJjbGUodGhpcy54LCB0aGlzLnksIHRoaXMuciAqIDIpOwogICAgICB9CiAgIH0KICAgZm9yIChsZXQgaSA9IDA7IGkgPCAxMDsgaSsrKSB7CiAgICAgIGxldCBjMiA9IG5ldyBNb3RoZXIoKTsKICAgICAgYzIueCA9IGMyLnI7CiAgICAgIGMyLnkgPSBjMi5yICsgaSAqIGMyLnIgKiAyOwogICAgICBrb2thYy5hZGQoYzIpOwogICAgICBsZXQgYzMgPSB7IHI6IDEwIH07CiAgICAgIGMzLnJlZHJhdyA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgZmlsbCgyNTUsIDI1NSwgMCk7CiAgICAgICAgIGNpcmNsZShjMi54LCBjMi55LCB0aGlzLnIgKiAyKTsKICAgICAgfTsKICAgICAga29rYWMuYWRkKGMzKTsKCiAgICAgIGtva2FjLmFkZCgoKSA9PiB7CiAgICAgICAgIGxldCBib3VuZCA9IGtva2FjLnRleHRCb3VuZHMoCiAgICAgICAgICAgIGAke01hdGgucmFuZG9tKCl9YCwKICAgICAgICAgICAgYzIueCwKICAgICAgICAgICAgYzIueSwKICAgICAgICAgICAgMjAsCiAgICAgICAgICAgIG15Rm9udCwKICAgICAgICAgICAgdHJ1ZQogICAgICAgICApOwogICAgICAgICBsZXQgbWFyZ2luID0gNDsKICAgICAgICAgcHVzaCgpOwogICAgICAgICBzdHJva2UoMjU1KTsKICAgICAgICAgZmlsbCgzMCk7CiAgICAgICAgIHJlY3QoCiAgICAgICAgICAgIGMyLnIgKyBtYXJnaW4gKyBib3VuZC5yZWN0LnggLSBtYXJnaW4sCiAgICAgICAgICAgIGJvdW5kLnJlY3QueSAtIG1hcmdpbiAtIGJvdW5kLnJlY3QuaCAqIDAuNSwKICAgICAgICAgICAgYm91bmQucmVjdC53ICsgbWFyZ2luICogMiwKICAgICAgICAgICAgYm91bmQucmVjdC5oICsgbWFyZ2luICogMgogICAgICAgICApOwogICAgICAgICBwb3AoKTsKICAgICAgICAgbGV0IHsgc3RyaW5nLCB4LCB5LCBmb250LCBzaXplIH0gPSBib3VuZDsKICAgICAgICAgZmlsbCgyNTUpOwogICAgICAgICB0ZXh0Rm9udChmb250KTsKICAgICAgICAgdGV4dFNpemUoc2l6ZSk7CiAgICAgICAgIHRleHQoc3RyaW5nLCBjMi5yICsgbWFyZ2luICsgeCwgeSAtIGJvdW5kLnJlY3QuaCAqIDAuNSk7CiAgICAgIH0pOwogICB9Cn0K
class KokacP5Ext { #tasks = new Map(); add(v) { this.#tasks.set(v); } remove(v) { this.#tasks.delete(v); } get iterator() { return this.#tasks.keys(); } delay(s) { if (!s) return new Promise((resolve) => setTimeout(resolve)); let waiter = {}; this.add(waiter); return new Promise((resolve) => { waiter.update = () => { if (--s > 0) return; this.remove(waiter); resolve(); }; }); } step() { const { iterator } = this; while (true) { let nt = iterator.next(); if (nt.done) break; let { value } = nt; if (value.constructor === Function) { value(); continue; } value.update && value.update(); value.redraw && value.redraw(); } } text(string, xx, yy, size, font) { let info = this.textBounds(string, xx, yy, size, font); textFont(info.font); textSize(info.size); text(info.string, info.x, info.y); } textBounds(string, xx, yy, size, font) { let myFont = font; let text1 = string; let fontSizeSmall = size; let x = xx; let y = yy; let bounding_box = myFont.textBounds(text1, x, y, fontSizeSmall); x -= bounding_box.x; y -= bounding_box.y; return { x: x + xx, y: y + yy, size: fontSizeSmall, font: myFont, string: string, rect: { x: x + bounding_box.x, y: y + bounding_box.y, w: bounding_box.w, h: bounding_box.h, }, }; } } function draw() { kokac.step(); } const kokac = new KokacP5Ext(); let myFont; function preload() { myFont = loadFont("https://cdn.jsdelivr.net/gh/kstost/KokacP5Ext/src/fonts/NotoSansKR-Bold.otf"); } async function setup() { // 로직은 setup 안에서만 손 대면 되도록 코드를 구성함 let sizeWidth = document.querySelector("#stg").getBoundingClientRect().width; let sizeHeight = sizeWidth * .5; // sizeWidth = innerWidth; // sizeHeight = innerHeight; createCanvas(sizeWidth, sizeHeight); noStroke(); kokac.add((e) => background(20)); kokac.add((e) => { fill("#00dd00"); kokac.text(`abc\ndef\n한글`, 10, 0, 130, myFont); }); //----------------------------------------- class Mother { constructor() { this.x = 0; this.y = 0; this.r = 20; this.alpha = 0; this.alphaToggle = false; } update() { this.x += 0.1; if (!this.alphaToggle) { this.alpha++; if (this.alpha >= 255) this.alphaToggle = !this.alphaToggle; } else { this.alpha--; if (this.alpha <= 0) this.alphaToggle = !this.alphaToggle; } } redraw() { fill(255, 0, 0, this.alpha); circle(this.x, this.y, this.r * 2); } } for (let i = 0; i < 10; i++) { let c2 = new Mother(); c2.x = c2.r; c2.y = c2.r + i * c2.r * 2; kokac.add(c2); let c3 = { r: 10 }; c3.redraw = function () { fill(255, 255, 0); circle(c2.x, c2.y, this.r * 2); }; kokac.add(c3); kokac.add(() => { let bound = kokac.textBounds( `${Math.random()}`, c2.x, c2.y, 20, myFont, true ); let margin = 4; push(); stroke(255); fill(30); rect( c2.r + margin + bound.rect.x - margin, bound.rect.y - margin - bound.rect.h * 0.5, bound.rect.w + margin * 2, bound.rect.h + margin * 2 ); pop(); let { string, x, y, font, size } = bound; fill(255); textFont(font); textSize(size); text(string, c2.r + margin + x, y - bound.rect.h * 0.5); }); } }