canvas-design-jp — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited canvas-design-jp (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
HTML5 Canvas および SVG を用いて、日本の伝統美学にもとづくグラフィック表現を実現するスキルです。間・侘寂・幽玄の美学原則から、書道要素、和紙テクスチャ、伝統紋様、四季のモチーフまでを網羅します。
/* 間を意識したレイアウト: 要素間に十分な余白を設ける */
const MA_RATIO = 0.618; /* 黄金比に近い余白比率 */
function applyMa(canvasWidth, contentWidth) {
const margin = (canvasWidth - contentWidth) * MA_RATIO;
return { left: margin, right: canvasWidth - contentWidth - margin };
}function drawBrushStroke(ctx, points, options = {}) {
const { maxWidth = 12, minWidth = 2, opacity = 0.85 } = options;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
for (let i = 1; i < points.length; i++) {
const speed = distance(points[i], points[i - 1]);
const pressure = Math.max(minWidth, maxWidth - speed * 0.1);
/* 筆のかすれ(kasure): 速度が速いと透明度が下がる */
ctx.globalAlpha = Math.max(0.3, opacity - speed * 0.005);
ctx.lineWidth = pressure;
ctx.beginPath();
ctx.moveTo(points[i - 1].x, points[i - 1].y);
ctx.lineTo(points[i].x, points[i].y);
ctx.stroke();
}
ctx.globalAlpha = 1.0;
}function createSumiGradient(ctx, x, y, radius) {
const gradient = ctx.createRadialGradient(x, y, 0, x, y, radius);
gradient.addColorStop(0, 'rgba(10, 10, 10, 0.9)'); /* 濃墨 */
gradient.addColorStop(0.4, 'rgba(30, 30, 30, 0.6)'); /* 中墨 */
gradient.addColorStop(0.7, 'rgba(60, 60, 60, 0.3)'); /* 淡墨 */
gradient.addColorStop(1, 'rgba(100, 100, 100, 0)'); /* にじみ */
return gradient;
}stroke-dasharray + stroke-dashoffset でパスを順に描画animation-delay で制御stroke-width のアニメーションで表現function generateWashiTexture(ctx, width, height) {
const imageData = ctx.createImageData(width, height);
for (let i = 0; i < imageData.data.length; i += 4) {
const noise = Math.random() * 20 - 10;
const base = 240; /* 生成紙色(きなり) */
imageData.data[i] = base + noise - 5; /* R */
imageData.data[i + 1] = base + noise - 8; /* G */
imageData.data[i + 2] = base + noise - 15; /* B */
imageData.data[i + 3] = 255;
}
/* 繊維の筋をランダムに追加 */
addFiberLines(imageData, width, height);
ctx.putImageData(imageData, 0, 0);
}function drawGoldLeaf(ctx, x, y, size) {
/* 不均一な金箔の貼り付けを表現 */
const gradient = ctx.createLinearGradient(x, y, x + size, y + size);
gradient.addColorStop(0, '#C5A355');
gradient.addColorStop(0.3, '#E8D48B');
gradient.addColorStop(0.5, '#F5E6A3');
gradient.addColorStop(0.7, '#D4B456');
gradient.addColorStop(1, '#B8933E');
ctx.fillStyle = gradient;
/* ランダムな多角形で金箔の輪郭を描画 */
drawIrregularPolygon(ctx, x, y, size);
}globalCompositeOperation: 'screen' で光の重なりを表現<use> で回転対称パターンを効率的に生成function drawKumikoPattern(ctx, x, y, size, depth) {
if (depth === 0) return;
/* 正三角形の分割を再帰的に描画 */
drawTriangleGrid(ctx, x, y, size);
/* 各三角形の中心に装飾パターンを配置 */
const subSize = size / 2;
drawKumikoPattern(ctx, x, y, subSize, depth - 1);
/* 麻の葉や胡麻柄などのバリエーション */
}function createSakuraPetal(ctx, x, y, size, rotation) {
ctx.save();
ctx.translate(x, y);
ctx.rotate(rotation);
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.bezierCurveTo(size * 0.3, -size * 0.5,
size * 0.7, -size * 0.5, size, 0);
ctx.bezierCurveTo(size * 0.7, size * 0.15,
size * 0.3, size * 0.15, 0, 0);
ctx.fillStyle = 'rgba(255, 183, 197, 0.8)';
ctx.fill();
ctx.restore();
}
/* 花びらの落下: 重力 + 風 + 回転のパラメータで自然な動きを実現 */| 色名 | HEX | 用途例 |
|---|---|---|
| 紅(くれない) | #D7003A | アクセント、花 |
| 藍(あい) | #165E83 | 背景、水 |
| 鶯(うぐいす) | #928C36 | 葉、自然 |
| 朱(しゅ) | #EB6101 | 鳥居、秋 |
| 藤(ふじ) | #A48EC5 | 花、優雅さ |
| 墨(すみ) | #1C1C1C | 書道、文字 |
| 金(きん) | #C5A355 | 装飾、金箔 |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.