summaryrefslogtreecommitdiffhomepage
path: root/vhosts/blog/static/my-icon.js
diff options
context:
space:
mode:
Diffstat (limited to 'vhosts/blog/static/my-icon.js')
-rw-r--r--vhosts/blog/static/my-icon.js267
1 files changed, 159 insertions, 108 deletions
diff --git a/vhosts/blog/static/my-icon.js b/vhosts/blog/static/my-icon.js
index 5b52ca3d..7d3ea96e 100644
--- a/vhosts/blog/static/my-icon.js
+++ b/vhosts/blog/static/my-icon.js
@@ -1,121 +1,172 @@
-const colorBackground = 'white';
-const color蜜柑の果実 = [255, 165, 0];
-const color蜜柑の内果皮 = [255, 255, 255];
-const color蜜柑のじょうのう = [255, 255, 255];
-const colorMosaic = [
- [255, 165, 0],
- [255, 140, 0],
- [255, 215, 0],
- [255, 205, 114],
- [255, 210, 127],
- [255, 192, 76],
- [255, 169, 12],
- [255, 228, 178],
-];
-const colorEye = [0, 0, 0];
-
-function setup() {
- const container = document.getElementById("p5jsMyIcon");
- const canvas = createCanvas(100, 100);
- canvas.parent(container);
-
- background(colorBackground);
- frameRate(15);
-}
-
-function draw() {
- if (4 <= frameCount % 15) {
- return;
+const init = () => {
+ const SIZE = 100;
+ const DPR = globalThis.devicePixelRatio || 1;
+ const FPS = 15;
+
+ const colorBackground = "rgb(255, 255, 255)";
+ const color蜜柑の果実 = "rgb(255, 165, 0)";
+ const color蜜柑の内果皮 = "rgb(255, 255, 255)";
+ const color蜜柑のじょうのう = "rgb(255, 255, 255)";
+ const colorMosaic = [
+ [255, 165, 0],
+ [255, 140, 0],
+ [255, 215, 0],
+ [255, 205, 114],
+ [255, 210, 127],
+ [255, 192, 76],
+ [255, 169, 12],
+ [255, 228, 178],
+ ];
+ const colorEye = "rgb(0, 0, 0)";
+
+ const container = document.getElementById("myIcon");
+ const canvas = document.createElement("canvas");
+ canvas.width = SIZE * DPR;
+ canvas.height = SIZE * DPR;
+ canvas.style.width = `${SIZE}px`;
+ canvas.style.height = `${SIZE}px`;
+ container.appendChild(canvas);
+ const ctx = canvas.getContext("2d");
+ ctx.scale(DPR, DPR);
+
+ let frameCount = 0;
+
+ function randomChoice(xs) {
+ return xs[(Math.random() * xs.length) | 0];
}
- clear();
+ function roundRect(x, y, w, h, r) {
+ ctx.beginPath();
+ ctx.moveTo(x + r, y);
+ ctx.lineTo(x + w - r, y);
+ ctx.quadraticCurveTo(x + w, y, x + w, y + r);
+ ctx.lineTo(x + w, y + h - r);
+ ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
+ ctx.lineTo(x + r, y + h);
+ ctx.quadraticCurveTo(x, y + h, x, y + h - r);
+ ctx.lineTo(x, y + r);
+ ctx.quadraticCurveTo(x, y, x + r, y);
+ ctx.closePath();
+ ctx.fill();
+ }
+
+ function draw蜜柑() {
+ // 果実、外果皮
+ ctx.fillStyle = color蜜柑の果実;
+ ctx.beginPath();
+ ctx.arc(50, 50, 50, 0, Math.PI * 2);
+ ctx.fill();
+
+ // 内果皮
+ ctx.strokeStyle = color蜜柑の内果皮;
+ ctx.lineWidth = 4;
+ ctx.beginPath();
+ ctx.arc(50, 50, 45, 0, Math.PI * 2);
+ ctx.stroke();
+
+ // じょうのう
+ ctx.strokeStyle = color蜜柑のじょうのう;
+ ctx.lineWidth = 2;
+ for (let t = 0; t < 10; t++) {
+ ctx.save();
+ ctx.translate(50, 50);
+ ctx.rotate((t * Math.PI) / 5);
- draw蜜柑();
- applyMosaicEffect([10, 5, 2, 0][frameCount % 15]);
- drawMosaic();
- drawEyes();
-}
+ ctx.beginPath();
+ ctx.moveTo(0, -45);
+ ctx.lineTo(0, 0);
+ ctx.stroke();
-function applyMosaicEffect(k) {
- if (k === 0) {
- return;
+ ctx.beginPath();
+ ctx.moveTo(0, -40);
+ ctx.lineTo(-4, -45);
+ ctx.lineTo(4, -45);
+ ctx.closePath();
+ ctx.stroke();
+
+ ctx.beginPath();
+ ctx.moveTo(0, -20);
+ ctx.lineTo(-3, 0);
+ ctx.lineTo(3, 0);
+ ctx.closePath();
+ ctx.stroke();
+
+ ctx.restore();
+ }
}
- loadPixels();
- noStroke();
- const d = pixelDensity();
- for (let y = 0; y < 100; y += k) {
- for (let x = 50; x < 100; x += k) {
- var r = 0, g = 0, b = 0;
- for (let i = 0; i < k; i++) {
- for (let j = 0; j < k; j++) {
- const offset = 4 * d * ((y + i) * 100 * d + (x + j));
- const r_ = pixels[offset];
- const g_ = pixels[offset + 1];
- const b_ = pixels[offset + 2];
- const a_ = pixels[offset + 3];
- r += a_ === 0 ? red(colorBackground) : r_;
- g += a_ === 0 ? green(colorBackground) : g_;
- b += a_ === 0 ? blue(colorBackground) : b_;
+ function applyMosaic(k) {
+ if (k === 0) return;
+
+ const img = ctx.getImageData(0, 0, SIZE, SIZE);
+ const pixels = img.data;
+
+ for (let y = 0; y < SIZE; y += k) {
+ for (let x = 50; x < SIZE; x += k) {
+ let r = 0, g = 0, b = 0;
+ for (let i = 0; i < k; i++) {
+ for (let j = 0; j < k; j++) {
+ const offset = 4 * ((y + i) * SIZE + (x + j));
+ const a = pixels[offset + 3];
+ r += a ? pixels[offset + 0] : 255;
+ g += a ? pixels[offset + 1] : 255;
+ b += a ? pixels[offset + 2] : 255;
+ }
}
+ const n = k * k;
+ ctx.fillStyle = `rgb(${(r / n) | 0}, ${(g / n) | 0}, ${(b / n) | 0})`;
+ ctx.fillRect(x, y, k, k);
}
- fill(r / k**2, g / k**2, b / k**2);
- rect(x, y, k, k);
}
}
-}
-
-function draw蜜柑() {
- // 果実、外果皮
- fill(color蜜柑の果実);
- noStroke();
- ellipse(50, 50, 100, 100);
-
- // 内果皮
- noFill();
- stroke(color蜜柑の内果皮);
- strokeWeight(4);
- ellipse(50, 50, 90, 90);
-
- // じょうのう
- stroke(color蜜柑のじょうのう);
- strokeWeight(2);
- for (let t = 0; t < 10; t++) {
- push();
- translate(50, 50);
- rotate(t * PI / 5);
- line(0, -45, 0, 0);
- triangle(0, -40, -4, -45, 4, -45);
- triangle(0, -20, -3, 0, 3, 0);
- pop();
- }
-}
-
-function drawMosaic() {
- for (let dy = 0; dy < 10; dy++) {
- for (let dx = 0; dx < 10; dx++) {
- const y = dy * 10;
- const x = dx * 10;
- if (x < 50) {
- continue;
- }
- if ((x - 45)**2 + (y - 45)**2 > 55**2) {
- continue;
- }
- if (random() < 0.5) {
- continue;
+
+ function drawMosaic() {
+ for (let dy = 0; dy < 10; dy++) {
+ for (let dx = 0; dx < 10; dx++) {
+ const y = dy * 10;
+ const x = dx * 10;
+ if (x < 50) {
+ continue;
+ }
+ if ((x - 45) ** 2 + (y - 45) ** 2 > 55 ** 2) {
+ continue;
+ }
+ if (Math.random() < 0.5) {
+ continue;
+ }
+
+ const [r, g, b] = randomChoice(colorMosaic);
+ ctx.fillStyle = `rgba(${r}, ${g}, ${b}, 0.75)`;
+ ctx.fillRect(x, y, 10, 10);
}
- const [r, g, b] = random(colorMosaic);
- noStroke();
- fill(r, g, b, 192);
- rect(x, y, 10, 10);
}
}
-}
-
-function drawEyes() {
- noStroke();
- fill(colorEye);
- rect(30, 35, 6, 25, 2);
- rect(64, 35, 6, 25, 2);
-}
+
+ function drawEyes() {
+ ctx.fillStyle = colorEye;
+ roundRect(30, 35, 6, 25, 2);
+ roundRect(64, 35, 6, 25, 2);
+ }
+
+ function mainLoop() {
+ frameCount++;
+ if (4 <= frameCount % 15) {
+ setTimeout(mainLoop, 1000 / FPS);
+ return;
+ }
+
+ ctx.fillStyle = colorBackground;
+ ctx.fillRect(0, 0, SIZE, SIZE);
+ ctx.clearRect(0, 0, SIZE, SIZE);
+
+ draw蜜柑();
+ applyMosaic([10, 5, 2, 0][frameCount % 15]);
+ drawMosaic();
+ drawEyes();
+
+ setTimeout(mainLoop, 1000 / FPS);
+ }
+ setTimeout(mainLoop, 2000);
+};
+
+document.addEventListener("DOMContentLoaded", init);