[{"data":1,"prerenderedAt":6956},["ShallowReactive",2],{"articles":3},[4,662,1302,2508,3462,4311,5095,5428,6210,6569,6799],{"id":5,"title":6,"body":7,"date":654,"description":655,"extension":656,"meta":657,"navigation":278,"path":658,"seo":659,"stem":660,"__hash__":661},"articles\u002Farticles\u002Faurora-ring-art.md","CSS @property と conic-gradient で描くオーロラリング",{"type":8,"value":9,"toc":646},"minimark",[10,14,18,21,24,28,53,118,132,134,138,151,321,326,328,332,344,397,413,415,419,433,551,554,556,559,634,642],[11,12,13],"h2",{"id":13},"作品",[15,16,17],"p",{},"4 つのリングがそれぞれ異なる速度・方向で回転し続けます。\nJavaScript は一切使わず、CSS だけで動いています。",[19,20],"aurora-ring",{},[22,23],"hr",{},[11,25,27],{"id":26},"property-とは","@property とは",[15,29,30,31,35,36,39,40,43,44,47,48,52],{},"通常の CSS カスタムプロパティ（",[32,33,34],"code",{},"--my-color: red"," のような変数）は ",[32,37,38],{},"transition"," や ",[32,41,42],{},"animation"," で補間できません。\n",[32,45,46],{},"@property"," を使うと型と初期値を宣言でき、",[49,50,51],"strong",{},"アニメーション可能なカスタムプロパティ","になります。",[54,55,60],"pre",{"className":56,"code":57,"language":58,"meta":59,"style":59},"language-css shiki shiki-themes github-light github-dark","@property --angle {\n  syntax: '\u003Cangle>';   \u002F* 型: 角度 *\u002F\n  inherits: false;     \u002F* 継承しない *\u002F\n  initial-value: 0deg; \u002F* 初期値 *\u002F\n}\n","css","",[32,61,62,74,90,99,112],{"__ignoreMap":59},[63,64,67,70],"span",{"class":65,"line":66},"line",1,[63,68,46],{"class":69},"szBVR",[63,71,73],{"class":72},"sVt8B"," --angle {\n",[63,75,77,80,83,86],{"class":65,"line":76},2,[63,78,79],{"class":72},"  syntax: '\u003Cangle",[63,81,82],{"class":69},">",[63,84,85],{"class":72},"';   ",[63,87,89],{"class":88},"sJ8bj","\u002F* 型: 角度 *\u002F\n",[63,91,93,96],{"class":65,"line":92},3,[63,94,95],{"class":72},"  inherits: false;     ",[63,97,98],{"class":88},"\u002F* 継承しない *\u002F\n",[63,100,102,106,109],{"class":65,"line":101},4,[63,103,105],{"class":104},"s9eBZ","  initial-value",[63,107,108],{"class":72},": 0deg; ",[63,110,111],{"class":88},"\u002F* 初期値 *\u002F\n",[63,113,115],{"class":65,"line":114},5,[63,116,117],{"class":72},"}\n",[15,119,120,123,124,127,128,131],{},[32,121,122],{},"syntax: '\u003Cangle>'"," と宣言することで、ブラウザが ",[32,125,126],{},"0deg"," → ",[32,129,130],{},"360deg"," の間を補間できるようになります。",[22,133],{},[11,135,137],{"id":136},"conic-gradient-の開始角を回転させる","conic-gradient の開始角を回転させる",[15,139,140,143,144,147,148,150],{},[32,141,142],{},"conic-gradient(from \u003Cangle>, ...)"," の ",[32,145,146],{},"from"," に ",[32,149,46],{}," で定義したカスタムプロパティを使います。",[54,152,154],{"className":56,"code":153,"language":58,"meta":59,"style":59},".ring {\n  background: conic-gradient(\n    from var(--a1),       \u002F* ← この角度をアニメーション *\u002F\n    transparent 0%,\n    #00DC82 15%,\n    transparent 45%\n  );\n  animation: spin 4s linear infinite;\n}\n\n@keyframes spin {\n  to { --a1: 360deg; }  \u002F* 0deg → 360deg へ補間 *\u002F\n}\n",[32,155,156,165,180,201,215,227,238,244,268,273,280,291,316],{"__ignoreMap":59},[63,157,158,162],{"class":65,"line":66},[63,159,161],{"class":160},"sScJk",".ring",[63,163,164],{"class":72}," {\n",[63,166,167,171,174,177],{"class":65,"line":76},[63,168,170],{"class":169},"sj4cs","  background",[63,172,173],{"class":72},": ",[63,175,176],{"class":169},"conic-gradient",[63,178,179],{"class":72},"(\n",[63,181,182,185,188,191,195,198],{"class":65,"line":92},[63,183,184],{"class":69},"    from",[63,186,187],{"class":169}," var",[63,189,190],{"class":72},"(",[63,192,194],{"class":193},"s4XuR","--a1",[63,196,197],{"class":72},"),       ",[63,199,200],{"class":88},"\u002F* ← この角度をアニメーション *\u002F\n",[63,202,203,206,209,212],{"class":65,"line":101},[63,204,205],{"class":169},"    transparent",[63,207,208],{"class":169}," 0",[63,210,211],{"class":69},"%",[63,213,214],{"class":72},",\n",[63,216,217,220,223,225],{"class":65,"line":114},[63,218,219],{"class":169},"    #00DC82",[63,221,222],{"class":169}," 15",[63,224,211],{"class":69},[63,226,214],{"class":72},[63,228,230,232,235],{"class":65,"line":229},6,[63,231,205],{"class":169},[63,233,234],{"class":169}," 45",[63,236,237],{"class":69},"%\n",[63,239,241],{"class":65,"line":240},7,[63,242,243],{"class":72},"  );\n",[63,245,247,250,253,256,259,262,265],{"class":65,"line":246},8,[63,248,249],{"class":169},"  animation",[63,251,252],{"class":72},": spin ",[63,254,255],{"class":169},"4",[63,257,258],{"class":69},"s",[63,260,261],{"class":169}," linear",[63,263,264],{"class":169}," infinite",[63,266,267],{"class":72},";\n",[63,269,271],{"class":65,"line":270},9,[63,272,117],{"class":72},[63,274,276],{"class":65,"line":275},10,[63,277,279],{"emptyLinePlaceholder":278},true,"\n",[63,281,283,286,289],{"class":65,"line":282},11,[63,284,285],{"class":69},"@keyframes",[63,287,288],{"class":193}," spin",[63,290,164],{"class":72},[63,292,294,297,300,302,304,307,310,313],{"class":65,"line":293},12,[63,295,296],{"class":160},"  to",[63,298,299],{"class":72}," { ",[63,301,194],{"class":193},[63,303,173],{"class":72},[63,305,306],{"class":169},"360",[63,308,309],{"class":69},"deg",[63,311,312],{"class":72},"; }  ",[63,314,315],{"class":88},"\u002F* 0deg → 360deg へ補間 *\u002F\n",[63,317,319],{"class":65,"line":318},13,[63,320,117],{"class":72},[15,322,323,325],{},[32,324,194],{}," が 0° から 360° へ変化するにつれ、グラデーションの始点がぐるりと一周します。\nこれが「グラデーションが回転する」ように見える仕組みです。",[22,327],{},[11,329,331],{"id":330},"mask-image-でリング状に切り抜く","mask-image でリング状に切り抜く",[15,333,334,336,337,147,340,343],{},[32,335,176],{}," は円形全体を塗るため、そのままでは円盤になってしまいます。\n",[32,338,339],{},"mask-image",[32,341,342],{},"radial-gradient","（中心と外縁を透明に）を指定し、リング状に切り抜きます。",[54,345,347],{"className":56,"code":346,"language":58,"meta":59,"style":59},"mask-image: radial-gradient(\n  circle,\n  transparent 68%,  \u002F* 内側: 透明 → リングの穴 *\u002F\n  black       72%,  \u002F* ここからリングの帯 *\u002F\n  black       92%,\n  transparent 96%   \u002F* 外縁: フェードアウト *\u002F\n);\n",[32,348,349,356,363,371,379,384,392],{"__ignoreMap":59},[63,350,351,353],{"class":65,"line":66},[63,352,339],{"class":104},[63,354,355],{"class":72},": radial-gradient(\n",[63,357,358,361],{"class":65,"line":76},[63,359,360],{"class":104},"  circle",[63,362,214],{"class":72},[63,364,365,368],{"class":65,"line":92},[63,366,367],{"class":72},"  transparent 68%,  ",[63,369,370],{"class":88},"\u002F* 内側: 透明 → リングの穴 *\u002F\n",[63,372,373,376],{"class":65,"line":101},[63,374,375],{"class":72},"  black       72%,  ",[63,377,378],{"class":88},"\u002F* ここからリングの帯 *\u002F\n",[63,380,381],{"class":65,"line":114},[63,382,383],{"class":72},"  black       92%,\n",[63,385,386,389],{"class":65,"line":229},[63,387,388],{"class":72},"  transparent 96%   ",[63,390,391],{"class":88},"\u002F* 外縁: フェードアウト *\u002F\n",[63,393,394],{"class":65,"line":240},[63,395,396],{"class":72},");\n",[398,399,401],"callout",{"type":400},"tip",[15,402,403,405,406,409,410,412],{},[32,404,339],{}," は ",[32,407,408],{},"-webkit-mask-image"," としても指定が必要なブラウザがあります。モダンブラウザでは ",[32,411,339],{}," のみで動作します。",[22,414],{},[11,416,418],{"id":417},"_4-つのリングに異なる動きを与える","4 つのリングに異なる動きを与える",[15,420,421,422,424,425,428,429,432],{},"各リングに別々の ",[32,423,46],{}," 変数と ",[32,426,427],{},"animation-duration"," を割り当てます。\n逆回転は ",[32,430,431],{},"animation-direction: reverse"," で実現します。",[54,434,436],{"className":56,"code":435,"language":58,"meta":59,"style":59},"\u002F* 内側から外側へ: 速い→遅い *\u002F\n.ring-1 { animation: spin1  4s linear infinite; }         \u002F* 速い *\u002F\n.ring-2 { animation: spin2  7s linear infinite; }         \u002F* 中速 *\u002F\n.ring-3 { animation: spin3 11s linear infinite; }         \u002F* 遅い *\u002F\n.ring-4 { animation: spin4 17s linear infinite reverse; } \u002F* 最遅・逆回転 *\u002F\n",[32,437,438,443,469,495,521],{"__ignoreMap":59},[63,439,440],{"class":65,"line":66},[63,441,442],{"class":88},"\u002F* 内側から外側へ: 速い→遅い *\u002F\n",[63,444,445,448,450,452,455,457,459,461,463,466],{"class":65,"line":76},[63,446,447],{"class":160},".ring-1",[63,449,299],{"class":72},[63,451,42],{"class":169},[63,453,454],{"class":72},": spin1  ",[63,456,255],{"class":169},[63,458,258],{"class":69},[63,460,261],{"class":169},[63,462,264],{"class":169},[63,464,465],{"class":72},"; }         ",[63,467,468],{"class":88},"\u002F* 速い *\u002F\n",[63,470,471,474,476,478,481,484,486,488,490,492],{"class":65,"line":92},[63,472,473],{"class":160},".ring-2",[63,475,299],{"class":72},[63,477,42],{"class":169},[63,479,480],{"class":72},": spin2  ",[63,482,483],{"class":169},"7",[63,485,258],{"class":69},[63,487,261],{"class":169},[63,489,264],{"class":169},[63,491,465],{"class":72},[63,493,494],{"class":88},"\u002F* 中速 *\u002F\n",[63,496,497,500,502,504,507,510,512,514,516,518],{"class":65,"line":101},[63,498,499],{"class":160},".ring-3",[63,501,299],{"class":72},[63,503,42],{"class":169},[63,505,506],{"class":72},": spin3 ",[63,508,509],{"class":169},"11",[63,511,258],{"class":69},[63,513,261],{"class":169},[63,515,264],{"class":169},[63,517,465],{"class":72},[63,519,520],{"class":88},"\u002F* 遅い *\u002F\n",[63,522,523,526,528,530,533,536,538,540,542,545,548],{"class":65,"line":114},[63,524,525],{"class":160},".ring-4",[63,527,299],{"class":72},[63,529,42],{"class":169},[63,531,532],{"class":72},": spin4 ",[63,534,535],{"class":169},"17",[63,537,258],{"class":69},[63,539,261],{"class":169},[63,541,264],{"class":169},[63,543,544],{"class":169}," reverse",[63,546,547],{"class":72},"; } ",[63,549,550],{"class":88},"\u002F* 最遅・逆回転 *\u002F\n",[15,552,553],{},"回転速度の比（4:7:11:17）を素数に近い値にすることで、\n4つが元の配置に戻る周期が極めて長くなり、飽きない動きになります。",[22,555],{},[11,557,558],{"id":558},"技術比較",[560,561,562,581],"table",{},[563,564,565],"thead",{},[566,567,568,572,575,578],"tr",{},[569,570,571],"th",{},"手法",[569,573,574],{},"JS 必要",[569,576,577],{},"動き",[569,579,580],{},"向いている表現",[582,583,584,599,613],"tbody",{},[566,585,586,590,593,596],{},[587,588,589],"td",{},"CSS animation + transform",[587,591,592],{},"不要",[587,594,595],{},"位置・スケール",[587,597,598],{},"移動・回転",[566,600,601,604,607,610],{},[587,602,603],{},"Canvas + rAF",[587,605,606],{},"必要",[587,608,609],{},"無制限",[587,611,612],{},"粒子・曲線",[566,614,615,620,624,629],{},[587,616,617],{},[49,618,619],{},"CSS @property",[587,621,622],{},[49,623,592],{},[587,625,626],{},[49,627,628],{},"値の補間",[587,630,631],{},[49,632,633],{},"グラデーション変化・色変化",[398,635,637],{"type":636},"warning",[15,638,639,641],{},[32,640,46],{}," は Safari 16.4 以降、Chrome 85 以降で対応しています。未対応ブラウザではアニメーションが動かず静止します。",[643,644,645],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":59,"searchDepth":76,"depth":76,"links":647},[648,649,650,651,652,653],{"id":13,"depth":76,"text":13},{"id":26,"depth":76,"text":27},{"id":136,"depth":76,"text":137},{"id":330,"depth":76,"text":331},{"id":417,"depth":76,"text":418},{"id":558,"depth":76,"text":558},"2026-05-01T23:00:00+09:00","CSS @property でカスタムプロパティをアニメーション可能にし、conic-gradient の回転でオーロラ状に光るリングを純粋 CSS だけで実現します。","md",{},"\u002Farticles\u002Faurora-ring-art",{"title":6,"description":655},"articles\u002Faurora-ring-art","IqmsV_P1x0f_xSUeOA_3ArsPLtqtktcZy6WWnyVOUMU",{"id":663,"title":664,"body":665,"date":1295,"description":1296,"extension":656,"meta":1297,"navigation":278,"path":1298,"seo":1299,"stem":1300,"__hash__":1301},"articles\u002Farticles\u002Fflow-field-art.md","パーティクルフローフィールド — 粒子と力場のシミュレーション",{"type":8,"value":666,"toc":1286},[667,669,672,675,678,680,683,686,694,696,699,706,924,927,929,932,943,1062,1069,1071,1075,1086,1089,1136,1139,1144,1146,1149,1156,1203,1206,1208,1211,1274,1283],[11,668,13],{"id":13},[15,670,671],{},"380 個の粒子が、sin \u002F cos を重ね合わせた「ベクトル場」の流れに沿ってキャンバス上を漂います。\n粒子の軌跡は半透明の暗いオーバーレイで徐々に消え、絶えず変化する模様を作り出します。",[673,674],"flow-field",{},[15,676,677],{},"クリック \u002F タップするとフィールドの時間軸がジャンプし、風向きが急変します。",[22,679],{},[11,681,682],{"id":682},"フローフィールドとは",[15,684,685],{},"フローフィールド（Flow Field）は平面上のすべての点に「向き（角度）」を持ったベクトルを定義したものです。\n粒子はそのベクトルに従って進み、多数の軌跡が重なることで複雑な模様が生まれます。",[54,687,692],{"className":688,"code":690,"language":691},[689],"language-text"," ↗ → ↘ ↓ ↙ ← ↖    ← 各格子点にベクトルが定義されている\n ↑ ↗ → ↘ ↓ ↙ ←\n ↖ ↑ ↗ → ↘ ↓ ↙\n","text",[32,693,690],{"__ignoreMap":59},[22,695],{},[11,697,698],{"id":698},"ベクトル場の定義",[15,700,701,702,705],{},"このアートでは sin \u002F cos の重ね合わせで角度を決める数式を使っています。\n時間 ",[32,703,704],{},"t"," を変数に含めることで、フィールドが時間とともに変化し続けます。",[54,707,711],{"className":708,"code":709,"language":710,"meta":59,"style":59},"language-ts shiki shiki-themes github-light github-dark","function fieldAngle(x: number, y: number, t: number): number {\n  const nx = x \u002F SIZE  \u002F\u002F 0〜1 に正規化\n  const ny = y \u002F SIZE\n\n  return (\n    Math.sin(nx * 4.5 + t * 0.35) * Math.cos(ny * 3.2 + t * 0.22) +\n    Math.cos(nx * 2.1 - ny * 1.8 + t * 0.14)\n  ) * Math.PI\n}\n","ts",[32,712,713,759,782,799,803,811,872,908,920],{"__ignoreMap":59},[63,714,715,718,721,723,726,729,732,735,738,740,742,744,746,748,750,753,755,757],{"class":65,"line":66},[63,716,717],{"class":69},"function",[63,719,720],{"class":160}," fieldAngle",[63,722,190],{"class":72},[63,724,725],{"class":193},"x",[63,727,728],{"class":69},":",[63,730,731],{"class":169}," number",[63,733,734],{"class":72},", ",[63,736,737],{"class":193},"y",[63,739,728],{"class":69},[63,741,731],{"class":169},[63,743,734],{"class":72},[63,745,704],{"class":193},[63,747,728],{"class":69},[63,749,731],{"class":169},[63,751,752],{"class":72},")",[63,754,728],{"class":69},[63,756,731],{"class":169},[63,758,164],{"class":72},[63,760,761,764,767,770,773,776,779],{"class":65,"line":76},[63,762,763],{"class":69},"  const",[63,765,766],{"class":169}," nx",[63,768,769],{"class":69}," =",[63,771,772],{"class":72}," x ",[63,774,775],{"class":69},"\u002F",[63,777,778],{"class":169}," SIZE",[63,780,781],{"class":88},"  \u002F\u002F 0〜1 に正規化\n",[63,783,784,786,789,791,794,796],{"class":65,"line":92},[63,785,763],{"class":69},[63,787,788],{"class":169}," ny",[63,790,769],{"class":69},[63,792,793],{"class":72}," y ",[63,795,775],{"class":69},[63,797,798],{"class":169}," SIZE\n",[63,800,801],{"class":65,"line":101},[63,802,279],{"emptyLinePlaceholder":278},[63,804,805,808],{"class":65,"line":114},[63,806,807],{"class":69},"  return",[63,809,810],{"class":72}," (\n",[63,812,813,816,819,822,825,828,831,834,836,839,842,844,847,850,853,855,858,860,862,864,867,869],{"class":65,"line":229},[63,814,815],{"class":72},"    Math.",[63,817,818],{"class":160},"sin",[63,820,821],{"class":72},"(nx ",[63,823,824],{"class":69},"*",[63,826,827],{"class":169}," 4.5",[63,829,830],{"class":69}," +",[63,832,833],{"class":72}," t ",[63,835,824],{"class":69},[63,837,838],{"class":169}," 0.35",[63,840,841],{"class":72},") ",[63,843,824],{"class":69},[63,845,846],{"class":72}," Math.",[63,848,849],{"class":160},"cos",[63,851,852],{"class":72},"(ny ",[63,854,824],{"class":69},[63,856,857],{"class":169}," 3.2",[63,859,830],{"class":69},[63,861,833],{"class":72},[63,863,824],{"class":69},[63,865,866],{"class":169}," 0.22",[63,868,841],{"class":72},[63,870,871],{"class":69},"+\n",[63,873,874,876,878,880,882,885,888,891,893,896,898,900,902,905],{"class":65,"line":240},[63,875,815],{"class":72},[63,877,849],{"class":160},[63,879,821],{"class":72},[63,881,824],{"class":69},[63,883,884],{"class":169}," 2.1",[63,886,887],{"class":69}," -",[63,889,890],{"class":72}," ny ",[63,892,824],{"class":69},[63,894,895],{"class":169}," 1.8",[63,897,830],{"class":69},[63,899,833],{"class":72},[63,901,824],{"class":69},[63,903,904],{"class":169}," 0.14",[63,906,907],{"class":72},")\n",[63,909,910,913,915,917],{"class":65,"line":246},[63,911,912],{"class":72},"  ) ",[63,914,824],{"class":69},[63,916,846],{"class":72},[63,918,919],{"class":169},"PI\n",[63,921,922],{"class":65,"line":270},[63,923,117],{"class":72},[15,925,926],{},"各係数を変えると模様が変わります。係数の比が整数に近いほど規則的な渦が生まれ、\n無理数比に近いほど複雑でカオス的なパターンになります。",[22,928],{},[11,930,931],{"id":931},"パーティクルの移動",[15,933,934,935,938,939,942],{},"粒子は毎フレーム、自分の現在地から ",[32,936,937],{},"fieldAngle"," を求めて速度を更新します。\n速度をいきなり変えず ",[32,940,941],{},"0.88"," の慣性係数を掛けることで、動きが滑らかになります。",[54,944,946],{"className":708,"code":945,"language":710,"meta":59,"style":59},"const angle = fieldAngle(p.x, p.y, t)\n\n\u002F\u002F 慣性あり：急に向きが変わらず、流れるような動きになる\np.vx = p.vx * 0.88 + Math.cos(angle) * speed * 0.12\np.vy = p.vy * 0.88 + Math.sin(angle) * speed * 0.12\n\np.x += p.vx\np.y += p.vy\n",[32,947,948,963,967,972,1007,1037,1041,1052],{"__ignoreMap":59},[63,949,950,953,956,958,960],{"class":65,"line":66},[63,951,952],{"class":69},"const",[63,954,955],{"class":169}," angle",[63,957,769],{"class":69},[63,959,720],{"class":160},[63,961,962],{"class":72},"(p.x, p.y, t)\n",[63,964,965],{"class":65,"line":76},[63,966,279],{"emptyLinePlaceholder":278},[63,968,969],{"class":65,"line":92},[63,970,971],{"class":88},"\u002F\u002F 慣性あり：急に向きが変わらず、流れるような動きになる\n",[63,973,974,977,980,983,985,988,990,992,994,997,999,1002,1004],{"class":65,"line":101},[63,975,976],{"class":72},"p.vx ",[63,978,979],{"class":69},"=",[63,981,982],{"class":72}," p.vx ",[63,984,824],{"class":69},[63,986,987],{"class":169}," 0.88",[63,989,830],{"class":69},[63,991,846],{"class":72},[63,993,849],{"class":160},[63,995,996],{"class":72},"(angle) ",[63,998,824],{"class":69},[63,1000,1001],{"class":72}," speed ",[63,1003,824],{"class":69},[63,1005,1006],{"class":169}," 0.12\n",[63,1008,1009,1012,1014,1017,1019,1021,1023,1025,1027,1029,1031,1033,1035],{"class":65,"line":114},[63,1010,1011],{"class":72},"p.vy ",[63,1013,979],{"class":69},[63,1015,1016],{"class":72}," p.vy ",[63,1018,824],{"class":69},[63,1020,987],{"class":169},[63,1022,830],{"class":69},[63,1024,846],{"class":72},[63,1026,818],{"class":160},[63,1028,996],{"class":72},[63,1030,824],{"class":69},[63,1032,1001],{"class":72},[63,1034,824],{"class":69},[63,1036,1006],{"class":169},[63,1038,1039],{"class":65,"line":229},[63,1040,279],{"emptyLinePlaceholder":278},[63,1042,1043,1046,1049],{"class":65,"line":240},[63,1044,1045],{"class":72},"p.x ",[63,1047,1048],{"class":69},"+=",[63,1050,1051],{"class":72}," p.vx\n",[63,1053,1054,1057,1059],{"class":65,"line":246},[63,1055,1056],{"class":72},"p.y ",[63,1058,1048],{"class":69},[63,1060,1061],{"class":72}," p.vy\n",[15,1063,1064,1065,1068],{},"画面外に出るか寿命（",[32,1066,1067],{},"life","）が尽きた粒子は、ランダムな位置で新生します。",[22,1070],{},[11,1072,1074],{"id":1073},"残像トレイル効果","残像（トレイル）効果",[15,1076,1077,1078,1081,1082,1085],{},"スピログラフではキャンバスを ",[32,1079,1080],{},"clearRect"," で完全に消去してから描き直していました。\nフローフィールドでは",[49,1083,1084],{},"消去しない","ことが重要です。",[15,1087,1088],{},"代わりに毎フレームの最初に「極めて薄い暗い矩形」を重ねます。",[54,1090,1092],{"className":708,"code":1091,"language":710,"meta":59,"style":59},"ctx.fillStyle = 'rgba(13, 17, 23, 0.06)'  \u002F\u002F 不透明度 6% の暗いオーバーレイ\nctx.fillRect(0, 0, SIZE, SIZE)\n",[32,1093,1094,1108],{"__ignoreMap":59},[63,1095,1096,1099,1101,1105],{"class":65,"line":66},[63,1097,1098],{"class":72},"ctx.fillStyle ",[63,1100,979],{"class":69},[63,1102,1104],{"class":1103},"sZZnC"," 'rgba(13, 17, 23, 0.06)'",[63,1106,1107],{"class":88},"  \u002F\u002F 不透明度 6% の暗いオーバーレイ\n",[63,1109,1110,1113,1116,1118,1121,1123,1125,1127,1130,1132,1134],{"class":65,"line":76},[63,1111,1112],{"class":72},"ctx.",[63,1114,1115],{"class":160},"fillRect",[63,1117,190],{"class":72},[63,1119,1120],{"class":169},"0",[63,1122,734],{"class":72},[63,1124,1120],{"class":169},[63,1126,734],{"class":72},[63,1128,1129],{"class":169},"SIZE",[63,1131,734],{"class":72},[63,1133,1129],{"class":169},[63,1135,907],{"class":72},[15,1137,1138],{},"これにより古い軌跡は 1 フレームごとに 6% ずつ暗くなり、約 16 フレームで消えます。\n結果として「長い尾を引きながら流れる」ように見えます。",[398,1140,1141],{"type":400},[15,1142,1143],{},"オーバーレイの不透明度が高いほど尾が短くなり、低いほど長く残ります。0.01〜0.15 の範囲で試すと印象が大きく変わります。",[22,1145],{},[11,1147,1148],{"id":1148},"クリックで風向きを変える",[15,1150,1151,1152,1155],{},"クリック時は ",[32,1153,1154],{},"tOffset"," を大きくジャンプさせることで、\nフィールドの時間軸を飛ばして「急な風向き変化」を表現しています。",[54,1157,1159],{"className":708,"code":1158,"language":710,"meta":59,"style":59},"function shiftField() {\n  tOffset += 4 + Math.random() * 3  \u002F\u002F 4〜7 秒分ジャンプ\n}\n",[32,1160,1161,1171,1199],{"__ignoreMap":59},[63,1162,1163,1165,1168],{"class":65,"line":66},[63,1164,717],{"class":69},[63,1166,1167],{"class":160}," shiftField",[63,1169,1170],{"class":72},"() {\n",[63,1172,1173,1176,1178,1181,1183,1185,1188,1191,1193,1196],{"class":65,"line":76},[63,1174,1175],{"class":72},"  tOffset ",[63,1177,1048],{"class":69},[63,1179,1180],{"class":169}," 4",[63,1182,830],{"class":69},[63,1184,846],{"class":72},[63,1186,1187],{"class":160},"random",[63,1189,1190],{"class":72},"() ",[63,1192,824],{"class":69},[63,1194,1195],{"class":169}," 3",[63,1197,1198],{"class":88},"  \u002F\u002F 4〜7 秒分ジャンプ\n",[63,1200,1201],{"class":65,"line":92},[63,1202,117],{"class":72},[15,1204,1205],{},"滑らかに変化するフィールドの流れが突然乱れ、\n渦や吹き返しが生まれる瞬間を楽しめます。",[22,1207],{},[11,1209,1210],{"id":1210},"手法まとめ",[560,1212,1213,1226],{},[563,1214,1215],{},[566,1216,1217,1220,1223],{},[569,1218,1219],{},"技術",[569,1221,1222],{},"性質",[569,1224,1225],{},"本作での役割",[582,1227,1228,1241,1252,1263],{},[566,1229,1230,1235,1238],{},[587,1231,1232],{},[32,1233,1234],{},"requestAnimationFrame",[587,1236,1237],{},"60fps ループ",[587,1239,1240],{},"フレームごとに粒子を更新",[566,1242,1243,1246,1249],{},[587,1244,1245],{},"sin \u002F cos 合成",[587,1247,1248],{},"連続・周期的",[587,1250,1251],{},"時間変化するベクトル場",[566,1253,1254,1257,1260],{},[587,1255,1256],{},"半透明オーバーレイ",[587,1258,1259],{},"積算描画",[587,1261,1262],{},"残像・トレイル効果",[566,1264,1265,1268,1271],{},[587,1266,1267],{},"慣性係数",[587,1269,1270],{},"低域フィルタ",[587,1272,1273],{},"動きの滑らかさ",[398,1275,1276],{"type":636},[15,1277,1278,1279,1282],{},"粒子数を増やすと描画コストが上がります。モバイルでは ",[32,1280,1281],{},"COUNT"," を 200 程度に下げるとフレームレートが安定します。",[643,1284,1285],{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":59,"searchDepth":76,"depth":76,"links":1287},[1288,1289,1290,1291,1292,1293,1294],{"id":13,"depth":76,"text":13},{"id":682,"depth":76,"text":682},{"id":698,"depth":76,"text":698},{"id":931,"depth":76,"text":931},{"id":1073,"depth":76,"text":1074},{"id":1148,"depth":76,"text":1148},{"id":1210,"depth":76,"text":1210},"2026-05-01T22:00:00+09:00","数百の粒子が時間変化するベクトル場に沿って流れる Canvas シミュレーションアートです。クリックで風向きを変えられます。",{},"\u002Farticles\u002Fflow-field-art",{"title":664,"description":1296},"articles\u002Fflow-field-art","lzWzpTbeBkkA_PiHq0VObsuF1ygo1ze9JzFA18Oovfs",{"id":1303,"title":1304,"body":1305,"date":2501,"description":2502,"extension":656,"meta":2503,"navigation":278,"path":2504,"seo":2505,"stem":2506,"__hash__":2507},"articles\u002Farticles\u002Fspirograph-art.md","Canvas API で描くスピログラフ",{"type":8,"value":1306,"toc":2490},[1307,1309,1316,1319,1321,1325,1332,1450,1461,1552,1554,1557,1560,1604,1724,1726,1730,1739,1872,1896,1898,1902,1908,2235,2240,2244,2251,2275,2286,2331,2333,2337,2356,2421,2423,2425,2479,2487],[11,1308,13],{"id":13},[15,1310,1311,1312,1315],{},"内側の円が外側の円の内壁を転がるとき、円上の一点が描く軌跡が ",[49,1313,1314],{},"ハイポトロコイド（スピログラフ）"," です。\nクリック \u002F タップするたびに異なる比率のパターンに切り替わります。",[1317,1318],"spirograph",{},[22,1320],{},[11,1322,1324],{"id":1323},"canvas-api-とは","Canvas API とは",[15,1326,1327,1328,1331],{},"これまでの作品は CSS や SVG という「宣言的」な手法でした。Canvas はその反対で、JavaScript から ",[32,1329,1330],{},"ctx.lineTo()"," などのメソッドを呼び出してピクセルを直接操作する「命令的」な描画 API です。",[54,1333,1335],{"className":708,"code":1334,"language":710,"meta":59,"style":59},"const canvas = document.querySelector('canvas')\nconst ctx = canvas.getContext('2d')\n\nctx.beginPath()\nctx.moveTo(100, 100)\nctx.lineTo(200, 200)\nctx.strokeStyle = '#00DC82'\nctx.stroke()\n",[32,1336,1337,1359,1381,1385,1395,1413,1431,1441],{"__ignoreMap":59},[63,1338,1339,1341,1344,1346,1349,1352,1354,1357],{"class":65,"line":66},[63,1340,952],{"class":69},[63,1342,1343],{"class":169}," canvas",[63,1345,769],{"class":69},[63,1347,1348],{"class":72}," document.",[63,1350,1351],{"class":160},"querySelector",[63,1353,190],{"class":72},[63,1355,1356],{"class":1103},"'canvas'",[63,1358,907],{"class":72},[63,1360,1361,1363,1366,1368,1371,1374,1376,1379],{"class":65,"line":76},[63,1362,952],{"class":69},[63,1364,1365],{"class":169}," ctx",[63,1367,769],{"class":69},[63,1369,1370],{"class":72}," canvas.",[63,1372,1373],{"class":160},"getContext",[63,1375,190],{"class":72},[63,1377,1378],{"class":1103},"'2d'",[63,1380,907],{"class":72},[63,1382,1383],{"class":65,"line":92},[63,1384,279],{"emptyLinePlaceholder":278},[63,1386,1387,1389,1392],{"class":65,"line":101},[63,1388,1112],{"class":72},[63,1390,1391],{"class":160},"beginPath",[63,1393,1394],{"class":72},"()\n",[63,1396,1397,1399,1402,1404,1407,1409,1411],{"class":65,"line":114},[63,1398,1112],{"class":72},[63,1400,1401],{"class":160},"moveTo",[63,1403,190],{"class":72},[63,1405,1406],{"class":169},"100",[63,1408,734],{"class":72},[63,1410,1406],{"class":169},[63,1412,907],{"class":72},[63,1414,1415,1417,1420,1422,1425,1427,1429],{"class":65,"line":229},[63,1416,1112],{"class":72},[63,1418,1419],{"class":160},"lineTo",[63,1421,190],{"class":72},[63,1423,1424],{"class":169},"200",[63,1426,734],{"class":72},[63,1428,1424],{"class":169},[63,1430,907],{"class":72},[63,1432,1433,1436,1438],{"class":65,"line":240},[63,1434,1435],{"class":72},"ctx.strokeStyle ",[63,1437,979],{"class":69},[63,1439,1440],{"class":1103}," '#00DC82'\n",[63,1442,1443,1445,1448],{"class":65,"line":246},[63,1444,1112],{"class":72},[63,1446,1447],{"class":160},"stroke",[63,1449,1394],{"class":72},[15,1451,1452,1453,1456,1457,1460],{},"Vue では ",[32,1454,1455],{},"ref"," でキャンバス要素を取得し、",[32,1458,1459],{},"onMounted"," で描画を開始します。",[54,1462,1464],{"className":708,"code":1463,"language":710,"meta":59,"style":59},"const canvasRef = ref\u003CHTMLCanvasElement | null>(null)\n\nonMounted(() => {\n  const ctx = canvasRef.value!.getContext('2d')!\n  \u002F\u002F ここで描画処理\n})\n",[32,1465,1466,1498,1502,1514,1542,1547],{"__ignoreMap":59},[63,1467,1468,1470,1473,1475,1478,1481,1484,1487,1490,1493,1496],{"class":65,"line":66},[63,1469,952],{"class":69},[63,1471,1472],{"class":169}," canvasRef",[63,1474,769],{"class":69},[63,1476,1477],{"class":160}," ref",[63,1479,1480],{"class":72},"\u003C",[63,1482,1483],{"class":160},"HTMLCanvasElement",[63,1485,1486],{"class":69}," |",[63,1488,1489],{"class":169}," null",[63,1491,1492],{"class":72},">(",[63,1494,1495],{"class":169},"null",[63,1497,907],{"class":72},[63,1499,1500],{"class":65,"line":76},[63,1501,279],{"emptyLinePlaceholder":278},[63,1503,1504,1506,1509,1512],{"class":65,"line":92},[63,1505,1459],{"class":160},[63,1507,1508],{"class":72},"(() ",[63,1510,1511],{"class":69},"=>",[63,1513,164],{"class":72},[63,1515,1516,1518,1520,1522,1525,1528,1531,1533,1535,1537,1539],{"class":65,"line":101},[63,1517,763],{"class":69},[63,1519,1365],{"class":169},[63,1521,769],{"class":69},[63,1523,1524],{"class":72}," canvasRef.value",[63,1526,1527],{"class":69},"!",[63,1529,1530],{"class":72},".",[63,1532,1373],{"class":160},[63,1534,190],{"class":72},[63,1536,1378],{"class":1103},[63,1538,752],{"class":72},[63,1540,1541],{"class":69},"!\n",[63,1543,1544],{"class":65,"line":114},[63,1545,1546],{"class":88},"  \u002F\u002F ここで描画処理\n",[63,1548,1549],{"class":65,"line":229},[63,1550,1551],{"class":72},"})\n",[22,1553],{},[11,1555,1556],{"id":1556},"スピログラフの数式",[15,1558,1559],{},"ハイポトロコイドは 3 つのパラメータで定義されます。",[560,1561,1562,1572],{},[563,1563,1564],{},[566,1565,1566,1569],{},[569,1567,1568],{},"変数",[569,1570,1571],{},"意味",[582,1573,1574,1584,1594],{},[566,1575,1576,1581],{},[587,1577,1578],{},[32,1579,1580],{},"R",[587,1582,1583],{},"外側の固定円の半径",[566,1585,1586,1591],{},[587,1587,1588],{},[32,1589,1590],{},"r",[587,1592,1593],{},"内側の転がる円の半径",[566,1595,1596,1601],{},[587,1597,1598],{},[32,1599,1600],{},"d",[587,1602,1603],{},"描画点と内円中心の距離",[54,1605,1607],{"className":708,"code":1606,"language":710,"meta":59,"style":59},"\u002F\u002F 媒介変数 t を 0 から増やしながら座標を計算\nconst x = (R - r) * Math.cos(t) + d * Math.cos(((R - r) \u002F r) * t)\nconst y = (R - r) * Math.sin(t) - d * Math.sin(((R - r) \u002F r) * t)\n",[32,1608,1609,1614,1672],{"__ignoreMap":59},[63,1610,1611],{"class":65,"line":66},[63,1612,1613],{"class":88},"\u002F\u002F 媒介変数 t を 0 から増やしながら座標を計算\n",[63,1615,1616,1618,1621,1623,1626,1628,1630,1633,1635,1637,1639,1642,1645,1648,1650,1652,1654,1657,1659,1661,1663,1665,1667,1669],{"class":65,"line":76},[63,1617,952],{"class":69},[63,1619,1620],{"class":169}," x",[63,1622,769],{"class":69},[63,1624,1625],{"class":72}," (",[63,1627,1580],{"class":169},[63,1629,887],{"class":69},[63,1631,1632],{"class":72}," r) ",[63,1634,824],{"class":69},[63,1636,846],{"class":72},[63,1638,849],{"class":160},[63,1640,1641],{"class":72},"(t) ",[63,1643,1644],{"class":69},"+",[63,1646,1647],{"class":72}," d ",[63,1649,824],{"class":69},[63,1651,846],{"class":72},[63,1653,849],{"class":160},[63,1655,1656],{"class":72},"(((",[63,1658,1580],{"class":169},[63,1660,887],{"class":69},[63,1662,1632],{"class":72},[63,1664,775],{"class":69},[63,1666,1632],{"class":72},[63,1668,824],{"class":69},[63,1670,1671],{"class":72}," t)\n",[63,1673,1674,1676,1679,1681,1683,1685,1687,1689,1691,1693,1695,1697,1700,1702,1704,1706,1708,1710,1712,1714,1716,1718,1720,1722],{"class":65,"line":92},[63,1675,952],{"class":69},[63,1677,1678],{"class":169}," y",[63,1680,769],{"class":69},[63,1682,1625],{"class":72},[63,1684,1580],{"class":169},[63,1686,887],{"class":69},[63,1688,1632],{"class":72},[63,1690,824],{"class":69},[63,1692,846],{"class":72},[63,1694,818],{"class":160},[63,1696,1641],{"class":72},[63,1698,1699],{"class":69},"-",[63,1701,1647],{"class":72},[63,1703,824],{"class":69},[63,1705,846],{"class":72},[63,1707,818],{"class":160},[63,1709,1656],{"class":72},[63,1711,1580],{"class":169},[63,1713,887],{"class":69},[63,1715,1632],{"class":72},[63,1717,775],{"class":69},[63,1719,1632],{"class":72},[63,1721,824],{"class":69},[63,1723,1671],{"class":72},[22,1725],{},[11,1727,1729],{"id":1728},"_1サイクルの長さを最大公約数で求める","1サイクルの長さを最大公約数で求める",[15,1731,1732,1733,1735,1736,1738],{},"曲線が「閉じる」（元に戻る）のは、内円が外円の内壁をちょうど整数回転したときです。\nこれは ",[32,1734,1580],{}," と ",[32,1737,1590],{}," の最大公約数（GCD）から求められます。",[54,1740,1742],{"className":708,"code":1741,"language":710,"meta":59,"style":59},"function gcd(a: number, b: number): number {\n  return b === 0 ? a : gcd(b, a % b)  \u002F\u002F ユークリッドの互除法\n}\n\nconst cycles = r \u002F gcd(R, r)           \u002F\u002F 内円の回転数\nconst totalAngle = 2 * Math.PI * cycles \u002F\u002F 描画する総角度\n",[32,1743,1744,1777,1810,1814,1818,1844],{"__ignoreMap":59},[63,1745,1746,1748,1751,1753,1756,1758,1760,1762,1765,1767,1769,1771,1773,1775],{"class":65,"line":66},[63,1747,717],{"class":69},[63,1749,1750],{"class":160}," gcd",[63,1752,190],{"class":72},[63,1754,1755],{"class":193},"a",[63,1757,728],{"class":69},[63,1759,731],{"class":169},[63,1761,734],{"class":72},[63,1763,1764],{"class":193},"b",[63,1766,728],{"class":69},[63,1768,731],{"class":169},[63,1770,752],{"class":72},[63,1772,728],{"class":69},[63,1774,731],{"class":169},[63,1776,164],{"class":72},[63,1778,1779,1781,1784,1787,1789,1792,1795,1797,1799,1802,1804,1807],{"class":65,"line":76},[63,1780,807],{"class":69},[63,1782,1783],{"class":72}," b ",[63,1785,1786],{"class":69},"===",[63,1788,208],{"class":169},[63,1790,1791],{"class":69}," ?",[63,1793,1794],{"class":72}," a ",[63,1796,728],{"class":69},[63,1798,1750],{"class":160},[63,1800,1801],{"class":72},"(b, a ",[63,1803,211],{"class":69},[63,1805,1806],{"class":72}," b)  ",[63,1808,1809],{"class":88},"\u002F\u002F ユークリッドの互除法\n",[63,1811,1812],{"class":65,"line":92},[63,1813,117],{"class":72},[63,1815,1816],{"class":65,"line":101},[63,1817,279],{"emptyLinePlaceholder":278},[63,1819,1820,1822,1825,1827,1830,1832,1834,1836,1838,1841],{"class":65,"line":114},[63,1821,952],{"class":69},[63,1823,1824],{"class":169}," cycles",[63,1826,769],{"class":69},[63,1828,1829],{"class":72}," r ",[63,1831,775],{"class":69},[63,1833,1750],{"class":160},[63,1835,190],{"class":72},[63,1837,1580],{"class":169},[63,1839,1840],{"class":72},", r)           ",[63,1842,1843],{"class":88},"\u002F\u002F 内円の回転数\n",[63,1845,1846,1848,1851,1853,1856,1859,1861,1864,1866,1869],{"class":65,"line":229},[63,1847,952],{"class":69},[63,1849,1850],{"class":169}," totalAngle",[63,1852,769],{"class":69},[63,1854,1855],{"class":169}," 2",[63,1857,1858],{"class":69}," *",[63,1860,846],{"class":72},[63,1862,1863],{"class":169},"PI",[63,1865,1858],{"class":69},[63,1867,1868],{"class":72}," cycles ",[63,1870,1871],{"class":88},"\u002F\u002F 描画する総角度\n",[15,1873,1874,1877,1878,1881,1882,1885,1886,1877,1889,1881,1892,1895],{},[32,1875,1876],{},"R:r = 120:45"," のとき ",[32,1879,1880],{},"gcd(120, 45) = 15","、",[32,1883,1884],{},"cycles = 3"," → 内円を 3 周して閉じます。\n",[32,1887,1888],{},"R:r = 120:25",[32,1890,1891],{},"gcd(120, 25) = 5",[32,1893,1894],{},"cycles = 5"," → 5 周。周数が多いほど複雑な形状になります。",[22,1897],{},[11,1899,1901],{"id":1900},"requestanimationframe-でアニメーション描画","requestAnimationFrame でアニメーション描画",[15,1903,1904,1905,1907],{},"全座標を事前計算しておき、毎フレーム少しずつ ",[32,1906,1419],{}," で線を伸ばしていきます。",[54,1909,1911],{"className":708,"code":1910,"language":710,"meta":59,"style":59},"\u002F\u002F 全点を先に計算\nconst pts = Array.from({ length: totalPoints + 1 }, (_, i) => {\n  const t = (i \u002F totalPoints) * totalAngle\n  return [\n    cx + (R - r) * Math.cos(t) + d * Math.cos(((R - r) \u002F r) * t),\n    cy + (R - r) * Math.sin(t) - d * Math.sin(((R - r) \u002F r) * t),\n  ]\n})\n\nlet i = 1\nfunction frame() {\n  ctx.beginPath()\n  ctx.moveTo(pts[i - 1][0], pts[i - 1][1])\n  ctx.lineTo(pts[i][0], pts[i][1])\n  ctx.stroke()\n  i++\n  if (i \u003C pts.length) requestAnimationFrame(frame)\n}\nframe()\n",[32,1912,1913,1918,1957,1979,1986,2036,2085,2090,2094,2098,2111,2120,2129,2162,2181,2190,2199,2222,2227],{"__ignoreMap":59},[63,1914,1915],{"class":65,"line":66},[63,1916,1917],{"class":88},"\u002F\u002F 全点を先に計算\n",[63,1919,1920,1922,1925,1927,1930,1932,1935,1937,1940,1943,1946,1948,1951,1953,1955],{"class":65,"line":76},[63,1921,952],{"class":69},[63,1923,1924],{"class":169}," pts",[63,1926,769],{"class":69},[63,1928,1929],{"class":72}," Array.",[63,1931,146],{"class":160},[63,1933,1934],{"class":72},"({ length: totalPoints ",[63,1936,1644],{"class":69},[63,1938,1939],{"class":169}," 1",[63,1941,1942],{"class":72}," }, (",[63,1944,1945],{"class":193},"_",[63,1947,734],{"class":72},[63,1949,1950],{"class":193},"i",[63,1952,841],{"class":72},[63,1954,1511],{"class":69},[63,1956,164],{"class":72},[63,1958,1959,1961,1964,1966,1969,1971,1974,1976],{"class":65,"line":92},[63,1960,763],{"class":69},[63,1962,1963],{"class":169}," t",[63,1965,769],{"class":69},[63,1967,1968],{"class":72}," (i ",[63,1970,775],{"class":69},[63,1972,1973],{"class":72}," totalPoints) ",[63,1975,824],{"class":69},[63,1977,1978],{"class":72}," totalAngle\n",[63,1980,1981,1983],{"class":65,"line":101},[63,1982,807],{"class":69},[63,1984,1985],{"class":72}," [\n",[63,1987,1988,1991,1993,1995,1997,1999,2001,2003,2005,2007,2009,2011,2013,2015,2017,2019,2021,2023,2025,2027,2029,2031,2033],{"class":65,"line":114},[63,1989,1990],{"class":72},"    cx ",[63,1992,1644],{"class":69},[63,1994,1625],{"class":72},[63,1996,1580],{"class":169},[63,1998,887],{"class":69},[63,2000,1632],{"class":72},[63,2002,824],{"class":69},[63,2004,846],{"class":72},[63,2006,849],{"class":160},[63,2008,1641],{"class":72},[63,2010,1644],{"class":69},[63,2012,1647],{"class":72},[63,2014,824],{"class":69},[63,2016,846],{"class":72},[63,2018,849],{"class":160},[63,2020,1656],{"class":72},[63,2022,1580],{"class":169},[63,2024,887],{"class":69},[63,2026,1632],{"class":72},[63,2028,775],{"class":69},[63,2030,1632],{"class":72},[63,2032,824],{"class":69},[63,2034,2035],{"class":72}," t),\n",[63,2037,2038,2041,2043,2045,2047,2049,2051,2053,2055,2057,2059,2061,2063,2065,2067,2069,2071,2073,2075,2077,2079,2081,2083],{"class":65,"line":229},[63,2039,2040],{"class":72},"    cy ",[63,2042,1644],{"class":69},[63,2044,1625],{"class":72},[63,2046,1580],{"class":169},[63,2048,887],{"class":69},[63,2050,1632],{"class":72},[63,2052,824],{"class":69},[63,2054,846],{"class":72},[63,2056,818],{"class":160},[63,2058,1641],{"class":72},[63,2060,1699],{"class":69},[63,2062,1647],{"class":72},[63,2064,824],{"class":69},[63,2066,846],{"class":72},[63,2068,818],{"class":160},[63,2070,1656],{"class":72},[63,2072,1580],{"class":169},[63,2074,887],{"class":69},[63,2076,1632],{"class":72},[63,2078,775],{"class":69},[63,2080,1632],{"class":72},[63,2082,824],{"class":69},[63,2084,2035],{"class":72},[63,2086,2087],{"class":65,"line":240},[63,2088,2089],{"class":72},"  ]\n",[63,2091,2092],{"class":65,"line":246},[63,2093,1551],{"class":72},[63,2095,2096],{"class":65,"line":270},[63,2097,279],{"emptyLinePlaceholder":278},[63,2099,2100,2103,2106,2108],{"class":65,"line":275},[63,2101,2102],{"class":69},"let",[63,2104,2105],{"class":72}," i ",[63,2107,979],{"class":69},[63,2109,2110],{"class":169}," 1\n",[63,2112,2113,2115,2118],{"class":65,"line":282},[63,2114,717],{"class":69},[63,2116,2117],{"class":160}," frame",[63,2119,1170],{"class":72},[63,2121,2122,2125,2127],{"class":65,"line":293},[63,2123,2124],{"class":72},"  ctx.",[63,2126,1391],{"class":160},[63,2128,1394],{"class":72},[63,2130,2131,2133,2135,2138,2140,2142,2145,2147,2150,2152,2154,2156,2159],{"class":65,"line":318},[63,2132,2124],{"class":72},[63,2134,1401],{"class":160},[63,2136,2137],{"class":72},"(pts[i ",[63,2139,1699],{"class":69},[63,2141,1939],{"class":169},[63,2143,2144],{"class":72},"][",[63,2146,1120],{"class":169},[63,2148,2149],{"class":72},"], pts[i ",[63,2151,1699],{"class":69},[63,2153,1939],{"class":169},[63,2155,2144],{"class":72},[63,2157,2158],{"class":169},"1",[63,2160,2161],{"class":72},"])\n",[63,2163,2165,2167,2169,2172,2174,2177,2179],{"class":65,"line":2164},14,[63,2166,2124],{"class":72},[63,2168,1419],{"class":160},[63,2170,2171],{"class":72},"(pts[i][",[63,2173,1120],{"class":169},[63,2175,2176],{"class":72},"], pts[i][",[63,2178,2158],{"class":169},[63,2180,2161],{"class":72},[63,2182,2184,2186,2188],{"class":65,"line":2183},15,[63,2185,2124],{"class":72},[63,2187,1447],{"class":160},[63,2189,1394],{"class":72},[63,2191,2193,2196],{"class":65,"line":2192},16,[63,2194,2195],{"class":72},"  i",[63,2197,2198],{"class":69},"++\n",[63,2200,2202,2205,2207,2209,2212,2215,2217,2219],{"class":65,"line":2201},17,[63,2203,2204],{"class":69},"  if",[63,2206,1968],{"class":72},[63,2208,1480],{"class":69},[63,2210,2211],{"class":72}," pts.",[63,2213,2214],{"class":169},"length",[63,2216,841],{"class":72},[63,2218,1234],{"class":160},[63,2220,2221],{"class":72},"(frame)\n",[63,2223,2225],{"class":65,"line":2224},18,[63,2226,117],{"class":72},[63,2228,2230,2233],{"class":65,"line":2229},19,[63,2231,2232],{"class":160},"frame",[63,2234,1394],{"class":72},[15,2236,2237,2239],{},[32,2238,1234],{}," はブラウザの描画タイミングに合わせてコールバックを呼ぶため、60fps でスムーズなアニメーションになります。",[2241,2242,2243],"h3",{"id":2243},"グロー効果",[15,2245,2246,2247,2250],{},"Canvas でも ",[32,2248,2249],{},"shadowBlur"," を設定すると発光感が出ます。",[54,2252,2254],{"className":708,"code":2253,"language":710,"meta":59,"style":59},"ctx.shadowBlur  = 8\nctx.shadowColor = '#00DC82'\n",[32,2255,2256,2266],{"__ignoreMap":59},[63,2257,2258,2261,2263],{"class":65,"line":66},[63,2259,2260],{"class":72},"ctx.shadowBlur  ",[63,2262,979],{"class":69},[63,2264,2265],{"class":169}," 8\n",[63,2267,2268,2271,2273],{"class":65,"line":76},[63,2269,2270],{"class":72},"ctx.shadowColor ",[63,2272,979],{"class":69},[63,2274,1440],{"class":1103},[15,2276,2277,2278,2281,2282,2285],{},"また ",[32,2279,2280],{},"progress","（描画の進行度）に合わせて ",[32,2283,2284],{},"strokeStyle"," の不透明度を上げることで、描かれていく線が徐々に明るくなるエフェクトを加えています。",[54,2287,2289],{"className":708,"code":2288,"language":710,"meta":59,"style":59},"const progress = i \u002F totalPoints\nctx.strokeStyle = `rgba(0, 220, 130, ${0.4 + 0.6 * progress})`\n",[32,2290,2291,2307],{"__ignoreMap":59},[63,2292,2293,2295,2298,2300,2302,2304],{"class":65,"line":66},[63,2294,952],{"class":69},[63,2296,2297],{"class":169}," progress",[63,2299,769],{"class":69},[63,2301,2105],{"class":72},[63,2303,775],{"class":69},[63,2305,2306],{"class":72}," totalPoints\n",[63,2308,2309,2311,2313,2316,2319,2321,2324,2326,2328],{"class":65,"line":76},[63,2310,1435],{"class":72},[63,2312,979],{"class":69},[63,2314,2315],{"class":1103}," `rgba(0, 220, 130, ${",[63,2317,2318],{"class":169},"0.4",[63,2320,830],{"class":69},[63,2322,2323],{"class":169}," 0.6",[63,2325,1858],{"class":69},[63,2327,2297],{"class":72},[63,2329,2330],{"class":1103},"})`\n",[22,2332],{},[11,2334,2336],{"id":2335},"retina-hidpi-対応","Retina \u002F HiDPI 対応",[15,2338,2339,2340,2343,2344,2347,2348,2351,2352,2355],{},"Canvas は ",[32,2341,2342],{},"width"," \u002F ",[32,2345,2346],{},"height"," 属性（物理ピクセル）と CSS サイズ（論理ピクセル）が分離しています。\n",[32,2349,2350],{},"devicePixelRatio"," を掛けてから ",[32,2353,2354],{},"scale()"," することでシャープな描画になります。",[54,2357,2359],{"className":708,"code":2358,"language":710,"meta":59,"style":59},"const dpr = window.devicePixelRatio || 1\ncanvas.width  = 400 * dpr\ncanvas.height = 400 * dpr\nctx.scale(dpr, dpr)\n\u002F\u002F 以降は 400×400 の座標系で描けば OK\n",[32,2360,2361,2378,2393,2406,2416],{"__ignoreMap":59},[63,2362,2363,2365,2368,2370,2373,2376],{"class":65,"line":66},[63,2364,952],{"class":69},[63,2366,2367],{"class":169}," dpr",[63,2369,769],{"class":69},[63,2371,2372],{"class":72}," window.devicePixelRatio ",[63,2374,2375],{"class":69},"||",[63,2377,2110],{"class":169},[63,2379,2380,2383,2385,2388,2390],{"class":65,"line":76},[63,2381,2382],{"class":72},"canvas.width  ",[63,2384,979],{"class":69},[63,2386,2387],{"class":169}," 400",[63,2389,1858],{"class":69},[63,2391,2392],{"class":72}," dpr\n",[63,2394,2395,2398,2400,2402,2404],{"class":65,"line":92},[63,2396,2397],{"class":72},"canvas.height ",[63,2399,979],{"class":69},[63,2401,2387],{"class":169},[63,2403,1858],{"class":69},[63,2405,2392],{"class":72},[63,2407,2408,2410,2413],{"class":65,"line":101},[63,2409,1112],{"class":72},[63,2411,2412],{"class":160},"scale",[63,2414,2415],{"class":72},"(dpr, dpr)\n",[63,2417,2418],{"class":65,"line":114},[63,2419,2420],{"class":88},"\u002F\u002F 以降は 400×400 の座標系で描けば OK\n",[22,2422],{},[11,2424,1210],{"id":1210},[560,2426,2427,2438],{},[563,2428,2429],{},[566,2430,2431,2433,2436],{},[569,2432,1219],{},[569,2434,2435],{},"描画モデル",[569,2437,580],{},[582,2439,2440,2451,2462],{},[566,2441,2442,2445,2448],{},[587,2443,2444],{},"CSS",[587,2446,2447],{},"宣言的・ボックスモデル",[587,2449,2450],{},"レイアウト・トランジション",[566,2452,2453,2456,2459],{},[587,2454,2455],{},"SVG",[587,2457,2458],{},"宣言的・ベクター",[587,2460,2461],{},"図形・パスアニメーション",[566,2463,2464,2469,2474],{},[587,2465,2466],{},[49,2467,2468],{},"Canvas 2D",[587,2470,2471],{},[49,2472,2473],{},"命令的・ラスター",[587,2475,2476],{},[49,2477,2478],{},"数学的曲線・粒子・ゲーム",[398,2480,2481],{"type":400},[15,2482,2483,2484,2486],{},"Canvas は一度描いた内容を「消す」ことができません（正確には ",[32,2485,1080],{}," で上書きするしかない）。そのため粒子エフェクトなど「前フレームを残しながら描く」表現も Canvas ならではです。",[643,2488,2489],{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":59,"searchDepth":76,"depth":76,"links":2491},[2492,2493,2494,2495,2496,2499,2500],{"id":13,"depth":76,"text":13},{"id":1323,"depth":76,"text":1324},{"id":1556,"depth":76,"text":1556},{"id":1728,"depth":76,"text":1729},{"id":1900,"depth":76,"text":1901,"children":2497},[2498],{"id":2243,"depth":92,"text":2243},{"id":2335,"depth":76,"text":2336},{"id":1210,"depth":76,"text":1210},"2026-05-01T20:00:00+09:00","HTML Canvas と requestAnimationFrame を使い、数学的な曲線「スピログラフ（ハイポトロコイド）」をアニメーション描画します。",{},"\u002Farticles\u002Fspirograph-art",{"title":1304,"description":2502},"articles\u002Fspirograph-art","4zgUl0xBoEesKmSIe69L660w-Ka7gD69F43ZJboUzGY",{"id":2509,"title":2510,"body":2511,"date":3455,"description":3456,"extension":656,"meta":3457,"navigation":278,"path":3458,"seo":3459,"stem":3460,"__hash__":3461},"articles\u002Farticles\u002Fhypercube-art.md","CSS 3D Transform で描くハイパーキューブ",{"type":8,"value":2512,"toc":3443},[2513,2515,2518,2521,2523,2527,2530,2598,2607,2609,2613,2624,2829,2843,2845,2849,2859,3065,3067,3071,3077,3081,3160,3163,3167,3248,3251,3255,3355,3358,3360,3363,3425,3440],[11,2514,13],{"id":13},[15,2516,2517],{},"3つの立方体（外・中・内）が、それぞれ異なる回転軸と速度で動き続けます。\n画像もライブラリも使わず、純粋な CSS だけで奥行きを持つ 3D 空間を作っています。",[2519,2520],"hyper-cube",{},[22,2522],{},[11,2524,2526],{"id":2525},"css-3d-の基本構造","CSS 3D の基本構造",[15,2528,2529],{},"CSS 3D は「カメラ（perspective）」と「3D 空間（preserve-3d）」の2つの設定で成立します。",[54,2531,2533],{"className":56,"code":2532,"language":58,"meta":59,"style":59},"\u002F* カメラの焦点距離。小さいほど歪みが強くなる *\u002F\n.scene {\n  perspective: 700px;\n}\n\n\u002F* 子要素の transform を 3D 空間に展開する *\u002F\n.cube {\n  transform-style: preserve-3d;\n}\n",[32,2534,2535,2540,2547,2562,2566,2570,2575,2582,2594],{"__ignoreMap":59},[63,2536,2537],{"class":65,"line":66},[63,2538,2539],{"class":88},"\u002F* カメラの焦点距離。小さいほど歪みが強くなる *\u002F\n",[63,2541,2542,2545],{"class":65,"line":76},[63,2543,2544],{"class":160},".scene",[63,2546,164],{"class":72},[63,2548,2549,2552,2554,2557,2560],{"class":65,"line":92},[63,2550,2551],{"class":169},"  perspective",[63,2553,173],{"class":72},[63,2555,2556],{"class":169},"700",[63,2558,2559],{"class":69},"px",[63,2561,267],{"class":72},[63,2563,2564],{"class":65,"line":101},[63,2565,117],{"class":72},[63,2567,2568],{"class":65,"line":114},[63,2569,279],{"emptyLinePlaceholder":278},[63,2571,2572],{"class":65,"line":229},[63,2573,2574],{"class":88},"\u002F* 子要素の transform を 3D 空間に展開する *\u002F\n",[63,2576,2577,2580],{"class":65,"line":240},[63,2578,2579],{"class":160},".cube",[63,2581,164],{"class":72},[63,2583,2584,2587,2589,2592],{"class":65,"line":246},[63,2585,2586],{"class":169},"  transform-style",[63,2588,173],{"class":72},[63,2590,2591],{"class":169},"preserve-3d",[63,2593,267],{"class":72},[63,2595,2596],{"class":65,"line":270},[63,2597,117],{"class":72},[15,2599,2600,2603,2604,2606],{},[32,2601,2602],{},"perspective"," は 1 つ上の祖先要素に設定し、",[32,2605,2591],{}," は 3D 変換する要素自身に設定します。\nこの 2 つがセットになって初めて立体に見えます。",[22,2608],{},[11,2610,2612],{"id":2611},"_6面の配置","6面の配置",[15,2614,2615,2616,2619,2620,2623],{},"立方体の 1 辺を ",[32,2617,2618],{},"S"," とすると、各面は ",[32,2621,2622],{},"translateZ(S\u002F2)"," だけ手前に押し出してから回転させます。",[54,2625,2627],{"className":56,"code":2626,"language":58,"meta":59,"style":59},".front  { transform: rotateY(0deg)   translateZ(80px); }\n.back   { transform: rotateY(180deg) translateZ(80px); }\n.right  { transform: rotateY(90deg)  translateZ(80px); }\n.left   { transform: rotateY(-90deg) translateZ(80px); }\n.top    { transform: rotateX(90deg)  translateZ(80px); }\n.bottom { transform: rotateX(-90deg) translateZ(80px); }\n",[32,2628,2629,2667,2700,2733,2765,2798],{"__ignoreMap":59},[63,2630,2631,2634,2637,2640,2642,2645,2647,2649,2651,2654,2657,2659,2662,2664],{"class":65,"line":66},[63,2632,2633],{"class":160},".front",[63,2635,2636],{"class":72},"  { ",[63,2638,2639],{"class":169},"transform",[63,2641,173],{"class":72},[63,2643,2644],{"class":169},"rotateY",[63,2646,190],{"class":72},[63,2648,1120],{"class":169},[63,2650,309],{"class":69},[63,2652,2653],{"class":72},")   ",[63,2655,2656],{"class":169},"translateZ",[63,2658,190],{"class":72},[63,2660,2661],{"class":169},"80",[63,2663,2559],{"class":69},[63,2665,2666],{"class":72},"); }\n",[63,2668,2669,2672,2675,2677,2679,2681,2683,2686,2688,2690,2692,2694,2696,2698],{"class":65,"line":76},[63,2670,2671],{"class":160},".back",[63,2673,2674],{"class":72},"   { ",[63,2676,2639],{"class":169},[63,2678,173],{"class":72},[63,2680,2644],{"class":169},[63,2682,190],{"class":72},[63,2684,2685],{"class":169},"180",[63,2687,309],{"class":69},[63,2689,841],{"class":72},[63,2691,2656],{"class":169},[63,2693,190],{"class":72},[63,2695,2661],{"class":169},[63,2697,2559],{"class":69},[63,2699,2666],{"class":72},[63,2701,2702,2705,2707,2709,2711,2713,2715,2718,2720,2723,2725,2727,2729,2731],{"class":65,"line":92},[63,2703,2704],{"class":160},".right",[63,2706,2636],{"class":72},[63,2708,2639],{"class":169},[63,2710,173],{"class":72},[63,2712,2644],{"class":169},[63,2714,190],{"class":72},[63,2716,2717],{"class":169},"90",[63,2719,309],{"class":69},[63,2721,2722],{"class":72},")  ",[63,2724,2656],{"class":169},[63,2726,190],{"class":72},[63,2728,2661],{"class":169},[63,2730,2559],{"class":69},[63,2732,2666],{"class":72},[63,2734,2735,2738,2740,2742,2744,2746,2748,2751,2753,2755,2757,2759,2761,2763],{"class":65,"line":101},[63,2736,2737],{"class":160},".left",[63,2739,2674],{"class":72},[63,2741,2639],{"class":169},[63,2743,173],{"class":72},[63,2745,2644],{"class":169},[63,2747,190],{"class":72},[63,2749,2750],{"class":169},"-90",[63,2752,309],{"class":69},[63,2754,841],{"class":72},[63,2756,2656],{"class":169},[63,2758,190],{"class":72},[63,2760,2661],{"class":169},[63,2762,2559],{"class":69},[63,2764,2666],{"class":72},[63,2766,2767,2770,2773,2775,2777,2780,2782,2784,2786,2788,2790,2792,2794,2796],{"class":65,"line":114},[63,2768,2769],{"class":160},".top",[63,2771,2772],{"class":72},"    { ",[63,2774,2639],{"class":169},[63,2776,173],{"class":72},[63,2778,2779],{"class":169},"rotateX",[63,2781,190],{"class":72},[63,2783,2717],{"class":169},[63,2785,309],{"class":69},[63,2787,2722],{"class":72},[63,2789,2656],{"class":169},[63,2791,190],{"class":72},[63,2793,2661],{"class":169},[63,2795,2559],{"class":69},[63,2797,2666],{"class":72},[63,2799,2800,2803,2805,2807,2809,2811,2813,2815,2817,2819,2821,2823,2825,2827],{"class":65,"line":229},[63,2801,2802],{"class":160},".bottom",[63,2804,299],{"class":72},[63,2806,2639],{"class":169},[63,2808,173],{"class":72},[63,2810,2779],{"class":169},[63,2812,190],{"class":72},[63,2814,2750],{"class":169},[63,2816,309],{"class":69},[63,2818,841],{"class":72},[63,2820,2656],{"class":169},[63,2822,190],{"class":72},[63,2824,2661],{"class":169},[63,2826,2559],{"class":69},[63,2828,2666],{"class":72},[398,2830,2831],{"type":400},[15,2832,2833,405,2835,2838,2839,2842],{},[32,2834,2639],{},[49,2836,2837],{},"右から左に適用","されます。",[32,2840,2841],{},"rotateY(90deg) translateZ(80px)"," は「まず Z 方向に 80px 移動し、その後 Y 軸で 90° 回転する」という意味になります。",[22,2844],{},[11,2846,2848],{"id":2847},"css-カスタムプロパティで3サイズを共通化","CSS カスタムプロパティで3サイズを共通化",[15,2850,2851,2852,2854,2855,2858],{},"外・中・内で辺の長さが異なるため、面ごとの ",[32,2853,2656],{}," が変わります。\nCSS カスタムプロパティ（",[32,2856,2857],{},"--half","）を親要素に定義することで、子要素がそれを参照できます。",[54,2860,2862],{"className":56,"code":2861,"language":58,"meta":59,"style":59},".outer { --half: 80px; width: 160px; height: 160px; }\n.mid   { --half: 48px; width:  96px; height:  96px; }\n.inner { --half: 20px; width:  40px; height:  40px; }\n\n\u002F* 3サイズ共通の face スタイル *\u002F\n.face.front { transform: rotateY(0deg)  translateZ(var(--half)); }\n.face.back  { transform: rotateY(180deg) translateZ(var(--half)); }\n\u002F* ...以下同様 *\u002F\n",[32,2863,2864,2904,2944,2983,2987,2992,3027,3060],{"__ignoreMap":59},[63,2865,2866,2869,2871,2873,2875,2877,2879,2882,2884,2886,2889,2891,2893,2895,2897,2899,2901],{"class":65,"line":66},[63,2867,2868],{"class":160},".outer",[63,2870,299],{"class":72},[63,2872,2857],{"class":193},[63,2874,173],{"class":72},[63,2876,2661],{"class":169},[63,2878,2559],{"class":69},[63,2880,2881],{"class":72},"; ",[63,2883,2342],{"class":169},[63,2885,173],{"class":72},[63,2887,2888],{"class":169},"160",[63,2890,2559],{"class":69},[63,2892,2881],{"class":72},[63,2894,2346],{"class":169},[63,2896,173],{"class":72},[63,2898,2888],{"class":169},[63,2900,2559],{"class":69},[63,2902,2903],{"class":72},"; }\n",[63,2905,2906,2909,2911,2913,2915,2918,2920,2922,2924,2927,2930,2932,2934,2936,2938,2940,2942],{"class":65,"line":76},[63,2907,2908],{"class":160},".mid",[63,2910,2674],{"class":72},[63,2912,2857],{"class":193},[63,2914,173],{"class":72},[63,2916,2917],{"class":169},"48",[63,2919,2559],{"class":69},[63,2921,2881],{"class":72},[63,2923,2342],{"class":169},[63,2925,2926],{"class":72},":  ",[63,2928,2929],{"class":169},"96",[63,2931,2559],{"class":69},[63,2933,2881],{"class":72},[63,2935,2346],{"class":169},[63,2937,2926],{"class":72},[63,2939,2929],{"class":169},[63,2941,2559],{"class":69},[63,2943,2903],{"class":72},[63,2945,2946,2949,2951,2953,2955,2958,2960,2962,2964,2966,2969,2971,2973,2975,2977,2979,2981],{"class":65,"line":92},[63,2947,2948],{"class":160},".inner",[63,2950,299],{"class":72},[63,2952,2857],{"class":193},[63,2954,173],{"class":72},[63,2956,2957],{"class":169},"20",[63,2959,2559],{"class":69},[63,2961,2881],{"class":72},[63,2963,2342],{"class":169},[63,2965,2926],{"class":72},[63,2967,2968],{"class":169},"40",[63,2970,2559],{"class":69},[63,2972,2881],{"class":72},[63,2974,2346],{"class":169},[63,2976,2926],{"class":72},[63,2978,2968],{"class":169},[63,2980,2559],{"class":69},[63,2982,2903],{"class":72},[63,2984,2985],{"class":65,"line":101},[63,2986,279],{"emptyLinePlaceholder":278},[63,2988,2989],{"class":65,"line":114},[63,2990,2991],{"class":88},"\u002F* 3サイズ共通の face スタイル *\u002F\n",[63,2993,2994,2997,2999,3001,3003,3005,3007,3009,3011,3013,3015,3017,3020,3022,3024],{"class":65,"line":229},[63,2995,2996],{"class":160},".face.front",[63,2998,299],{"class":72},[63,3000,2639],{"class":169},[63,3002,173],{"class":72},[63,3004,2644],{"class":169},[63,3006,190],{"class":72},[63,3008,1120],{"class":169},[63,3010,309],{"class":69},[63,3012,2722],{"class":72},[63,3014,2656],{"class":169},[63,3016,190],{"class":72},[63,3018,3019],{"class":169},"var",[63,3021,190],{"class":72},[63,3023,2857],{"class":193},[63,3025,3026],{"class":72},")); }\n",[63,3028,3029,3032,3034,3036,3038,3040,3042,3044,3046,3048,3050,3052,3054,3056,3058],{"class":65,"line":240},[63,3030,3031],{"class":160},".face.back",[63,3033,2636],{"class":72},[63,3035,2639],{"class":169},[63,3037,173],{"class":72},[63,3039,2644],{"class":169},[63,3041,190],{"class":72},[63,3043,2685],{"class":169},[63,3045,309],{"class":69},[63,3047,841],{"class":72},[63,3049,2656],{"class":169},[63,3051,190],{"class":72},[63,3053,3019],{"class":169},[63,3055,190],{"class":72},[63,3057,2857],{"class":193},[63,3059,3026],{"class":72},[63,3061,3062],{"class":65,"line":246},[63,3063,3064],{"class":88},"\u002F* ...以下同様 *\u002F\n",[22,3066],{},[11,3068,3070],{"id":3069},"_3種類の回転アニメーション","3種類の回転アニメーション",[15,3072,3073,3074,3076],{},"各立方体に異なる ",[32,3075,285],{}," を割り当てて、互いに異なる動きをさせています。",[2241,3078,3080],{"id":3079},"外側-y軸回転x軸に-20-傾けた状態で","外側 — Y軸回転（X軸に 20° 傾けた状態で）",[54,3082,3084],{"className":56,"code":3083,"language":58,"meta":59,"style":59},"@keyframes spin-y {\n  from { transform: rotateX(20deg) rotateY(0deg); }\n  to   { transform: rotateX(20deg) rotateY(360deg); }\n}\n",[32,3085,3086,3095,3126,3156],{"__ignoreMap":59},[63,3087,3088,3090,3093],{"class":65,"line":66},[63,3089,285],{"class":69},[63,3091,3092],{"class":193}," spin-y",[63,3094,164],{"class":72},[63,3096,3097,3100,3102,3104,3106,3108,3110,3112,3114,3116,3118,3120,3122,3124],{"class":65,"line":76},[63,3098,3099],{"class":160},"  from",[63,3101,299],{"class":72},[63,3103,2639],{"class":169},[63,3105,173],{"class":72},[63,3107,2779],{"class":169},[63,3109,190],{"class":72},[63,3111,2957],{"class":169},[63,3113,309],{"class":69},[63,3115,841],{"class":72},[63,3117,2644],{"class":169},[63,3119,190],{"class":72},[63,3121,1120],{"class":169},[63,3123,309],{"class":69},[63,3125,2666],{"class":72},[63,3127,3128,3130,3132,3134,3136,3138,3140,3142,3144,3146,3148,3150,3152,3154],{"class":65,"line":92},[63,3129,296],{"class":160},[63,3131,2674],{"class":72},[63,3133,2639],{"class":169},[63,3135,173],{"class":72},[63,3137,2779],{"class":169},[63,3139,190],{"class":72},[63,3141,2957],{"class":169},[63,3143,309],{"class":69},[63,3145,841],{"class":72},[63,3147,2644],{"class":169},[63,3149,190],{"class":72},[63,3151,306],{"class":169},[63,3153,309],{"class":69},[63,3155,2666],{"class":72},[63,3157,3158],{"class":65,"line":101},[63,3159,117],{"class":72},[15,3161,3162],{},"X 軸を 20° 傾けることで「斜め上から見た」自然な視点になります。",[2241,3164,3166],{"id":3165},"中間-xy逆回転","中間 — XY逆回転",[54,3168,3170],{"className":56,"code":3169,"language":58,"meta":59,"style":59},"@keyframes spin-xy-rev {\n  from { transform: rotateX(0deg)    rotateY(0deg); }\n  to   { transform: rotateX(-360deg) rotateY(-220deg); }\n}\n",[32,3171,3172,3181,3212,3244],{"__ignoreMap":59},[63,3173,3174,3176,3179],{"class":65,"line":66},[63,3175,285],{"class":69},[63,3177,3178],{"class":193}," spin-xy-rev",[63,3180,164],{"class":72},[63,3182,3183,3185,3187,3189,3191,3193,3195,3197,3199,3202,3204,3206,3208,3210],{"class":65,"line":76},[63,3184,3099],{"class":160},[63,3186,299],{"class":72},[63,3188,2639],{"class":169},[63,3190,173],{"class":72},[63,3192,2779],{"class":169},[63,3194,190],{"class":72},[63,3196,1120],{"class":169},[63,3198,309],{"class":69},[63,3200,3201],{"class":72},")    ",[63,3203,2644],{"class":169},[63,3205,190],{"class":72},[63,3207,1120],{"class":169},[63,3209,309],{"class":69},[63,3211,2666],{"class":72},[63,3213,3214,3216,3218,3220,3222,3224,3226,3229,3231,3233,3235,3237,3240,3242],{"class":65,"line":92},[63,3215,296],{"class":160},[63,3217,2674],{"class":72},[63,3219,2639],{"class":169},[63,3221,173],{"class":72},[63,3223,2779],{"class":169},[63,3225,190],{"class":72},[63,3227,3228],{"class":169},"-360",[63,3230,309],{"class":69},[63,3232,841],{"class":72},[63,3234,2644],{"class":169},[63,3236,190],{"class":72},[63,3238,3239],{"class":169},"-220",[63,3241,309],{"class":69},[63,3243,2666],{"class":72},[63,3245,3246],{"class":65,"line":101},[63,3247,117],{"class":72},[15,3249,3250],{},"X と Y の回転量を非整数比（360:220）にすると、同じポーズに戻らず変化し続けます。",[2241,3252,3254],{"id":3253},"内側-xyz全軸タンブリング","内側 — XYZ全軸タンブリング",[54,3256,3258],{"className":56,"code":3257,"language":58,"meta":59,"style":59},"@keyframes spin-tumble {\n  from { transform: rotateX(0deg)   rotateY(0deg)   rotateZ(0deg); }\n  to   { transform: rotateX(360deg) rotateY(540deg) rotateZ(180deg); }\n}\n",[32,3259,3260,3269,3310,3351],{"__ignoreMap":59},[63,3261,3262,3264,3267],{"class":65,"line":66},[63,3263,285],{"class":69},[63,3265,3266],{"class":193}," spin-tumble",[63,3268,164],{"class":72},[63,3270,3271,3273,3275,3277,3279,3281,3283,3285,3287,3289,3291,3293,3295,3297,3299,3302,3304,3306,3308],{"class":65,"line":76},[63,3272,3099],{"class":160},[63,3274,299],{"class":72},[63,3276,2639],{"class":169},[63,3278,173],{"class":72},[63,3280,2779],{"class":169},[63,3282,190],{"class":72},[63,3284,1120],{"class":169},[63,3286,309],{"class":69},[63,3288,2653],{"class":72},[63,3290,2644],{"class":169},[63,3292,190],{"class":72},[63,3294,1120],{"class":169},[63,3296,309],{"class":69},[63,3298,2653],{"class":72},[63,3300,3301],{"class":169},"rotateZ",[63,3303,190],{"class":72},[63,3305,1120],{"class":169},[63,3307,309],{"class":69},[63,3309,2666],{"class":72},[63,3311,3312,3314,3316,3318,3320,3322,3324,3326,3328,3330,3332,3334,3337,3339,3341,3343,3345,3347,3349],{"class":65,"line":92},[63,3313,296],{"class":160},[63,3315,2674],{"class":72},[63,3317,2639],{"class":169},[63,3319,173],{"class":72},[63,3321,2779],{"class":169},[63,3323,190],{"class":72},[63,3325,306],{"class":169},[63,3327,309],{"class":69},[63,3329,841],{"class":72},[63,3331,2644],{"class":169},[63,3333,190],{"class":72},[63,3335,3336],{"class":169},"540",[63,3338,309],{"class":69},[63,3340,841],{"class":72},[63,3342,3301],{"class":169},[63,3344,190],{"class":72},[63,3346,2685],{"class":169},[63,3348,309],{"class":69},[63,3350,2666],{"class":72},[63,3352,3353],{"class":65,"line":101},[63,3354,117],{"class":72},[15,3356,3357],{},"3軸同時かつ非整数比で回転させることで、完全にランダムに見える「タンブリング」になります。",[22,3359],{},[11,3361,3362],{"id":3362},"手法比較",[560,3364,3365,3376],{},[563,3366,3367],{},[566,3368,3369,3371,3374],{},[569,3370,1219],{},[569,3372,3373],{},"次元",[569,3375,580],{},[582,3377,3378,3389,3398,3408],{},[566,3379,3380,3383,3386],{},[587,3381,3382],{},"CSS gradient",[587,3384,3385],{},"2D",[587,3387,3388],{},"背景・光源",[566,3390,3391,3393,3395],{},[587,3392,589],{},[587,3394,3385],{},[587,3396,3397],{},"軌道・移動",[566,3399,3400,3403,3405],{},[587,3401,3402],{},"SVG stroke-dashoffset",[587,3404,3385],{},[587,3406,3407],{},"描画・ライン",[566,3409,3410,3415,3420],{},[587,3411,3412],{},[49,3413,3414],{},"CSS 3D transform",[587,3416,3417],{},[49,3418,3419],{},"3D",[587,3421,3422],{},[49,3423,3424],{},"立体・奥行き・回転体",[398,3426,3427],{"type":636},[15,3428,3429,405,3432,3435,3436,3439],{},[32,3430,3431],{},"transform-style: preserve-3d",[32,3433,3434],{},"overflow: hidden"," と併用できません。3D シーンのコンテナには ",[32,3437,3438],{},"overflow"," を設定しないよう注意してください。",[643,3441,3442],{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":59,"searchDepth":76,"depth":76,"links":3444},[3445,3446,3447,3448,3449,3454],{"id":13,"depth":76,"text":13},{"id":2525,"depth":76,"text":2526},{"id":2611,"depth":76,"text":2612},{"id":2847,"depth":76,"text":2848},{"id":3069,"depth":76,"text":3070,"children":3450},[3451,3452,3453],{"id":3079,"depth":92,"text":3080},{"id":3165,"depth":92,"text":3166},{"id":3253,"depth":92,"text":3254},{"id":3362,"depth":76,"text":3362},"2026-05-01T18:00:00+09:00","perspective と transform-style:preserve-3d を使い、3つの立方体が異なる軸と速度で回転する CSS 3D アートを制作します。",{},"\u002Farticles\u002Fhypercube-art",{"title":2510,"description":3456},"articles\u002Fhypercube-art","8_FvRialiE-_G_CJefd-oEkGpR_TKXNCLUpViEHcGuo",{"id":3463,"title":3464,"body":3465,"date":4304,"description":4305,"extension":656,"meta":4306,"navigation":278,"path":4307,"seo":4308,"stem":4309,"__hash__":4310},"articles\u002Farticles\u002Fmandala-art.md","SVG で描くマンダラ — stroke-dashoffset アニメーション",{"type":8,"value":3466,"toc":4294},[3467,3469,3472,3475,3477,3481,3488,3492,3502,3513,3524,3620,3623,3633,3810,3813,3879,3881,3884,3887,3898,4010,4025,4027,4030,4033,4217,4226,4228,4232,4291],[11,3468,13],{"id":13},[15,3470,3471],{},"ページを開いた瞬間、中心から外に向かってパスが順番に描かれていきます。\n描き終わると、六角形のペアが互いに逆方向へゆっくり回転し続けます。",[3473,3474],"drawing-mandala",{},[22,3476],{},[11,3478,3480],{"id":3479},"核心技術-stroke-dashoffset","核心技術 — stroke-dashoffset",[15,3482,3483,3484,3487],{},"SVG のパスには「破線のオフセット」を制御する ",[32,3485,3486],{},"stroke-dashoffset"," プロパティがあります。\nこれを使って「未描画 → 描画済み」を表現するのが、このアニメーションの核心です。",[2241,3489,3491],{"id":3490},"pathlength-で長さを正規化","pathLength で長さを正規化",[15,3493,3494,3495,3498,3499,3501],{},"すべてのパス（円・多角形・線）の長さはバラバラです。\n",[32,3496,3497],{},"pathLength=\"100\""," を指定すると、ブラウザがそのパスの総長さを ",[49,3500,1406],{}," として扱ってくれます。",[54,3503,3507],{"className":3504,"code":3505,"language":3506,"meta":59,"style":59},"language-svg shiki shiki-themes github-light github-dark","\u003Ccircle pathLength=\"100\" cx=\"200\" cy=\"200\" r=\"172\" \u002F>\n","svg",[32,3508,3509],{"__ignoreMap":59},[63,3510,3511],{"class":65,"line":66},[63,3512,3505],{},[15,3514,3515,3516,3519,3520,3523],{},"これで ",[32,3517,3518],{},"stroke-dasharray: 100; stroke-dashoffset: 100"," が「全部隠れた状態」、\n",[32,3521,3522],{},"stroke-dashoffset: 0"," が「全部描かれた状態」と統一できます。",[54,3525,3527],{"className":56,"code":3526,"language":58,"meta":59,"style":59},".draw {\n  stroke-dasharray: 100;\n  stroke-dashoffset: 100;            \u002F* 初期：全部隠す *\u002F\n  animation: draw 1s ease forwards;  \u002F* → 0 まで動かして描く *\u002F\n}\n\n@keyframes draw {\n  to { stroke-dashoffset: 0; }\n}\n",[32,3528,3529,3536,3547,3562,3585,3589,3593,3602,3616],{"__ignoreMap":59},[63,3530,3531,3534],{"class":65,"line":66},[63,3532,3533],{"class":160},".draw",[63,3535,164],{"class":72},[63,3537,3538,3541,3543,3545],{"class":65,"line":76},[63,3539,3540],{"class":169},"  stroke-dasharray",[63,3542,173],{"class":72},[63,3544,1406],{"class":169},[63,3546,267],{"class":72},[63,3548,3549,3552,3554,3556,3559],{"class":65,"line":92},[63,3550,3551],{"class":169},"  stroke-dashoffset",[63,3553,173],{"class":72},[63,3555,1406],{"class":169},[63,3557,3558],{"class":72},";            ",[63,3560,3561],{"class":88},"\u002F* 初期：全部隠す *\u002F\n",[63,3563,3564,3566,3569,3571,3573,3576,3579,3582],{"class":65,"line":101},[63,3565,249],{"class":169},[63,3567,3568],{"class":72},": draw ",[63,3570,2158],{"class":169},[63,3572,258],{"class":69},[63,3574,3575],{"class":169}," ease",[63,3577,3578],{"class":169}," forwards",[63,3580,3581],{"class":72},";  ",[63,3583,3584],{"class":88},"\u002F* → 0 まで動かして描く *\u002F\n",[63,3586,3587],{"class":65,"line":114},[63,3588,117],{"class":72},[63,3590,3591],{"class":65,"line":229},[63,3592,279],{"emptyLinePlaceholder":278},[63,3594,3595,3597,3600],{"class":65,"line":240},[63,3596,285],{"class":69},[63,3598,3599],{"class":193}," draw",[63,3601,164],{"class":72},[63,3603,3604,3606,3608,3610,3612,3614],{"class":65,"line":246},[63,3605,296],{"class":160},[63,3607,299],{"class":72},[63,3609,3486],{"class":169},[63,3611,173],{"class":72},[63,3613,1120],{"class":169},[63,3615,2903],{"class":72},[63,3617,3618],{"class":65,"line":270},[63,3619,117],{"class":72},[2241,3621,3622],{"id":3622},"遅延で順番を制御",[15,3624,3625,3628,3629,3632],{},[32,3626,3627],{},"animation-delay"," に CSS カスタムプロパティ（",[32,3630,3631],{},"--d","）を使い、要素ごとに描画タイミングをずらします。",[54,3634,3638],{"className":3635,"code":3636,"language":3637,"meta":59,"style":59},"language-vue shiki shiki-themes github-light github-dark","\u003C!-- 中心から外に向かって遅延を増やす -->\n\u003Ccircle class=\"draw\" style=\"--d: 0s;   --t: 0.6s\" r=\"24\" \u002F>   \u003C!-- 中心リング -->\n\u003Ccircle class=\"draw\" style=\"--d: 0.8s; --t: 1.0s\" r=\"100\" \u002F>  \u003C!-- 中間リング -->\n\u003Ccircle class=\"draw\" style=\"--d: 2.5s; --t: 1.2s\" r=\"172\" \u002F>  \u003C!-- 外側リング -->\n","vue",[32,3639,3640,3645,3705,3758],{"__ignoreMap":59},[63,3641,3642],{"class":65,"line":66},[63,3643,3644],{"class":88},"\u003C!-- 中心から外に向かって遅延を増やす -->\n",[63,3646,3647,3649,3652,3655,3657,3660,3663,3665,3668,3670,3672,3674,3676,3679,3682,3684,3687,3689,3691,3694,3696,3699,3702],{"class":65,"line":76},[63,3648,1480],{"class":72},[63,3650,3651],{"class":104},"circle",[63,3653,3654],{"class":160}," class",[63,3656,979],{"class":72},[63,3658,3659],{"class":1103},"\"draw\"",[63,3661,3662],{"class":160}," style",[63,3664,979],{"class":72},[63,3666,3667],{"class":1103},"\"",[63,3669,3631],{"class":193},[63,3671,173],{"class":72},[63,3673,1120],{"class":169},[63,3675,258],{"class":69},[63,3677,3678],{"class":72},";   ",[63,3680,3681],{"class":193},"--t",[63,3683,173],{"class":72},[63,3685,3686],{"class":169},"0.6",[63,3688,258],{"class":69},[63,3690,3667],{"class":1103},[63,3692,3693],{"class":160}," r",[63,3695,979],{"class":72},[63,3697,3698],{"class":1103},"\"24\"",[63,3700,3701],{"class":72}," \u002F>   ",[63,3703,3704],{"class":88},"\u003C!-- 中心リング -->\n",[63,3706,3707,3709,3711,3713,3715,3717,3719,3721,3723,3725,3727,3730,3732,3734,3736,3738,3741,3743,3745,3747,3749,3752,3755],{"class":65,"line":92},[63,3708,1480],{"class":72},[63,3710,3651],{"class":104},[63,3712,3654],{"class":160},[63,3714,979],{"class":72},[63,3716,3659],{"class":1103},[63,3718,3662],{"class":160},[63,3720,979],{"class":72},[63,3722,3667],{"class":1103},[63,3724,3631],{"class":193},[63,3726,173],{"class":72},[63,3728,3729],{"class":169},"0.8",[63,3731,258],{"class":69},[63,3733,2881],{"class":72},[63,3735,3681],{"class":193},[63,3737,173],{"class":72},[63,3739,3740],{"class":169},"1.0",[63,3742,258],{"class":69},[63,3744,3667],{"class":1103},[63,3746,3693],{"class":160},[63,3748,979],{"class":72},[63,3750,3751],{"class":1103},"\"100\"",[63,3753,3754],{"class":72}," \u002F>  ",[63,3756,3757],{"class":88},"\u003C!-- 中間リング -->\n",[63,3759,3760,3762,3764,3766,3768,3770,3772,3774,3776,3778,3780,3783,3785,3787,3789,3791,3794,3796,3798,3800,3802,3805,3807],{"class":65,"line":101},[63,3761,1480],{"class":72},[63,3763,3651],{"class":104},[63,3765,3654],{"class":160},[63,3767,979],{"class":72},[63,3769,3659],{"class":1103},[63,3771,3662],{"class":160},[63,3773,979],{"class":72},[63,3775,3667],{"class":1103},[63,3777,3631],{"class":193},[63,3779,173],{"class":72},[63,3781,3782],{"class":169},"2.5",[63,3784,258],{"class":69},[63,3786,2881],{"class":72},[63,3788,3681],{"class":193},[63,3790,173],{"class":72},[63,3792,3793],{"class":169},"1.2",[63,3795,258],{"class":69},[63,3797,3667],{"class":1103},[63,3799,3693],{"class":160},[63,3801,979],{"class":72},[63,3803,3804],{"class":1103},"\"172\"",[63,3806,3754],{"class":72},[63,3808,3809],{"class":88},"\u003C!-- 外側リング -->\n",[15,3811,3812],{},"12本の放射線も個別に遅延をずらして、「扇形に広がる」演出をしています。",[54,3814,3816],{"className":708,"code":3815,"language":710,"meta":59,"style":59},"const radialLines = Array.from({ length: 12 }, (_, i) => ({\n  delay: 0.4 + i * 0.04,  \u002F\u002F 0.04秒ずつずらす\n}))\n",[32,3817,3818,3852,3874],{"__ignoreMap":59},[63,3819,3820,3822,3825,3827,3829,3831,3834,3837,3839,3841,3843,3845,3847,3849],{"class":65,"line":66},[63,3821,952],{"class":69},[63,3823,3824],{"class":169}," radialLines",[63,3826,769],{"class":69},[63,3828,1929],{"class":72},[63,3830,146],{"class":160},[63,3832,3833],{"class":72},"({ length: ",[63,3835,3836],{"class":169},"12",[63,3838,1942],{"class":72},[63,3840,1945],{"class":193},[63,3842,734],{"class":72},[63,3844,1950],{"class":193},[63,3846,841],{"class":72},[63,3848,1511],{"class":69},[63,3850,3851],{"class":72}," ({\n",[63,3853,3854,3857,3859,3861,3863,3865,3868,3871],{"class":65,"line":76},[63,3855,3856],{"class":72},"  delay: ",[63,3858,2318],{"class":169},[63,3860,830],{"class":69},[63,3862,2105],{"class":72},[63,3864,824],{"class":69},[63,3866,3867],{"class":169}," 0.04",[63,3869,3870],{"class":72},",  ",[63,3872,3873],{"class":88},"\u002F\u002F 0.04秒ずつずらす\n",[63,3875,3876],{"class":65,"line":92},[63,3877,3878],{"class":72},"}))\n",[22,3880],{},[11,3882,3883],{"id":3883},"六角形の逆回転",[15,3885,3886],{},"描き終わった後、2つの六角形（30° ずらして重ねた Star of David 状のペア）が逆方向に回り続けます。",[15,3888,3889,3890,3893,3894,3897],{},"各六角形を ",[32,3891,3892],{},"\u003Cg>"," で包み、",[32,3895,3896],{},"transform-origin"," を SVG 中心（200px 200px）に設定します。",[54,3899,3901],{"className":56,"code":3900,"language":58,"meta":59,"style":59},".spin-cw  { animation: spin-cw  18s linear infinite; }\n.spin-ccw { animation: spin-ccw 18s linear infinite; }\n\n@keyframes spin-cw  { to { transform: rotate(360deg);  } }\n@keyframes spin-ccw { to { transform: rotate(-360deg); } }\n",[32,3902,3903,3926,3948,3952,3982],{"__ignoreMap":59},[63,3904,3905,3908,3910,3912,3915,3918,3920,3922,3924],{"class":65,"line":66},[63,3906,3907],{"class":160},".spin-cw",[63,3909,2636],{"class":72},[63,3911,42],{"class":169},[63,3913,3914],{"class":72},": spin-cw  ",[63,3916,3917],{"class":169},"18",[63,3919,258],{"class":69},[63,3921,261],{"class":169},[63,3923,264],{"class":169},[63,3925,2903],{"class":72},[63,3927,3928,3931,3933,3935,3938,3940,3942,3944,3946],{"class":65,"line":76},[63,3929,3930],{"class":160},".spin-ccw",[63,3932,299],{"class":72},[63,3934,42],{"class":169},[63,3936,3937],{"class":72},": spin-ccw ",[63,3939,3917],{"class":169},[63,3941,258],{"class":69},[63,3943,261],{"class":169},[63,3945,264],{"class":169},[63,3947,2903],{"class":72},[63,3949,3950],{"class":65,"line":92},[63,3951,279],{"emptyLinePlaceholder":278},[63,3953,3954,3956,3959,3961,3964,3966,3968,3970,3973,3975,3977,3979],{"class":65,"line":101},[63,3955,285],{"class":69},[63,3957,3958],{"class":193}," spin-cw",[63,3960,2636],{"class":72},[63,3962,3963],{"class":160},"to",[63,3965,299],{"class":72},[63,3967,2639],{"class":169},[63,3969,173],{"class":72},[63,3971,3972],{"class":169},"rotate",[63,3974,190],{"class":72},[63,3976,306],{"class":169},[63,3978,309],{"class":69},[63,3980,3981],{"class":72},");  } }\n",[63,3983,3984,3986,3989,3991,3993,3995,3997,3999,4001,4003,4005,4007],{"class":65,"line":114},[63,3985,285],{"class":69},[63,3987,3988],{"class":193}," spin-ccw",[63,3990,299],{"class":72},[63,3992,3963],{"class":160},[63,3994,299],{"class":72},[63,3996,2639],{"class":169},[63,3998,173],{"class":72},[63,4000,3972],{"class":169},[63,4002,190],{"class":72},[63,4004,3228],{"class":169},[63,4006,309],{"class":69},[63,4008,4009],{"class":72},"); } }\n",[15,4011,4012,4013,4016,4017,143,4019,4021,4022,4024],{},"ポイントは ",[32,4014,4015],{},"animation-delay: 4.2s"," で描画アニメーション終了まで回転を待つことです。\n",[32,4018,3892],{},[32,4020,3627],{}," と子要素の描画 ",[32,4023,3627],{}," は独立しているため、互いに干渉しません。",[22,4026],{},[11,4028,4029],{"id":4029},"座標の計算",[15,4031,4032],{},"マンダラは「円の上に等間隔で点を打つ」繰り返しです。\nJavaScript の三角関数で座標を求めます。",[54,4034,4036],{"className":708,"code":4035,"language":710,"meta":59,"style":59},"const pt = (r: number, deg: number) => ({\n  x: CX + r * Math.cos((deg * Math.PI) \u002F 180),\n  y: CY + r * Math.sin((deg * Math.PI) \u002F 180),\n})\n\n\u002F\u002F 正六角形（頂点6個、60°間隔）\nconst hexPoints = Array.from({ length: 6 }, (_, i) =>\n  pt(100, -90 + i * 60)  \u002F\u002F -90° = 真上から開始\n)\n",[32,4037,4038,4069,4106,4140,4144,4148,4153,4184,4213],{"__ignoreMap":59},[63,4039,4040,4042,4045,4047,4049,4051,4053,4055,4057,4059,4061,4063,4065,4067],{"class":65,"line":66},[63,4041,952],{"class":69},[63,4043,4044],{"class":160}," pt",[63,4046,769],{"class":69},[63,4048,1625],{"class":72},[63,4050,1590],{"class":193},[63,4052,728],{"class":69},[63,4054,731],{"class":169},[63,4056,734],{"class":72},[63,4058,309],{"class":193},[63,4060,728],{"class":69},[63,4062,731],{"class":169},[63,4064,841],{"class":72},[63,4066,1511],{"class":69},[63,4068,3851],{"class":72},[63,4070,4071,4074,4077,4079,4081,4083,4085,4087,4090,4092,4094,4096,4098,4100,4103],{"class":65,"line":76},[63,4072,4073],{"class":72},"  x: ",[63,4075,4076],{"class":169},"CX",[63,4078,830],{"class":69},[63,4080,1829],{"class":72},[63,4082,824],{"class":69},[63,4084,846],{"class":72},[63,4086,849],{"class":160},[63,4088,4089],{"class":72},"((deg ",[63,4091,824],{"class":69},[63,4093,846],{"class":72},[63,4095,1863],{"class":169},[63,4097,841],{"class":72},[63,4099,775],{"class":69},[63,4101,4102],{"class":169}," 180",[63,4104,4105],{"class":72},"),\n",[63,4107,4108,4111,4114,4116,4118,4120,4122,4124,4126,4128,4130,4132,4134,4136,4138],{"class":65,"line":92},[63,4109,4110],{"class":72},"  y: ",[63,4112,4113],{"class":169},"CY",[63,4115,830],{"class":69},[63,4117,1829],{"class":72},[63,4119,824],{"class":69},[63,4121,846],{"class":72},[63,4123,818],{"class":160},[63,4125,4089],{"class":72},[63,4127,824],{"class":69},[63,4129,846],{"class":72},[63,4131,1863],{"class":169},[63,4133,841],{"class":72},[63,4135,775],{"class":69},[63,4137,4102],{"class":169},[63,4139,4105],{"class":72},[63,4141,4142],{"class":65,"line":101},[63,4143,1551],{"class":72},[63,4145,4146],{"class":65,"line":114},[63,4147,279],{"emptyLinePlaceholder":278},[63,4149,4150],{"class":65,"line":229},[63,4151,4152],{"class":88},"\u002F\u002F 正六角形（頂点6個、60°間隔）\n",[63,4154,4155,4157,4160,4162,4164,4166,4168,4171,4173,4175,4177,4179,4181],{"class":65,"line":240},[63,4156,952],{"class":69},[63,4158,4159],{"class":169}," hexPoints",[63,4161,769],{"class":69},[63,4163,1929],{"class":72},[63,4165,146],{"class":160},[63,4167,3833],{"class":72},[63,4169,4170],{"class":169},"6",[63,4172,1942],{"class":72},[63,4174,1945],{"class":193},[63,4176,734],{"class":72},[63,4178,1950],{"class":193},[63,4180,841],{"class":72},[63,4182,4183],{"class":69},"=>\n",[63,4185,4186,4189,4191,4193,4195,4197,4199,4201,4203,4205,4208,4210],{"class":65,"line":246},[63,4187,4188],{"class":160},"  pt",[63,4190,190],{"class":72},[63,4192,1406],{"class":169},[63,4194,734],{"class":72},[63,4196,1699],{"class":69},[63,4198,2717],{"class":169},[63,4200,830],{"class":69},[63,4202,2105],{"class":72},[63,4204,824],{"class":69},[63,4206,4207],{"class":169}," 60",[63,4209,2722],{"class":72},[63,4211,4212],{"class":88},"\u002F\u002F -90° = 真上から開始\n",[63,4214,4215],{"class":65,"line":270},[63,4216,907],{"class":72},[398,4218,4219],{"type":400},[15,4220,4221,4222,4225],{},"SVG の Y 軸は下向きが正です。",[32,4223,4224],{},"-90°"," を開始角にすると頂点が真上に来て、幾何学的に自然な形になります。",[22,4227],{},[11,4229,4231],{"id":4230},"css-前作との比較","CSS 前作との比較",[560,4233,4234,4246],{},[563,4235,4236],{},[566,4237,4238,4240,4243],{},[569,4239,571],{},[569,4241,4242],{},"本記事 (SVG stroke)",[569,4244,4245],{},"前作 CSS (gradient)",[582,4247,4248,4258,4269,4280],{},[566,4249,4250,4252,4255],{},[587,4251,577],{},[587,4253,4254],{},"描画アニメーション",[587,4256,4257],{},"脈動・軌道回転",[566,4259,4260,4263,4266],{},[587,4261,4262],{},"形状の精度",[587,4264,4265],{},"数学的に正確",[587,4267,4268],{},"近似的",[566,4270,4271,4274,4277],{},[587,4272,4273],{},"インタラクティブ性",[587,4275,4276],{},"パスごとに制御可能",[587,4278,4279],{},"要素単位",[566,4281,4282,4285,4288],{},[587,4283,4284],{},"コード量",[587,4286,4287],{},"多め",[587,4289,4290],{},"少なめ",[643,4292,4293],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":59,"searchDepth":76,"depth":76,"links":4295},[4296,4297,4301,4302,4303],{"id":13,"depth":76,"text":13},{"id":3479,"depth":76,"text":3480,"children":4298},[4299,4300],{"id":3490,"depth":92,"text":3491},{"id":3622,"depth":92,"text":3622},{"id":3883,"depth":76,"text":3883},{"id":4029,"depth":76,"text":4029},{"id":4230,"depth":76,"text":4231},"2026-05-01T16:00:00+09:00","SVG の stroke-dashoffset を使ってパスが自己描画するマンダラアニメーションを作る手法を解説します。",{},"\u002Farticles\u002Fmandala-art",{"title":3464,"description":4305},"articles\u002Fmandala-art","h_epan9PlIxLQuYmrIDOuqdPa9R5olIkcbIcE0WWh2g",{"id":4312,"title":4313,"body":4314,"date":5088,"description":5089,"extension":656,"meta":5090,"navigation":278,"path":5091,"seo":5092,"stem":5093,"__hash__":5094},"articles\u002Farticles\u002Fcss-animation-art.md","CSS アニメーションと SVG で描くアート",{"type":8,"value":4315,"toc":5076},[4316,4320,4323,4326,4329,4332,4454,4461,4598,4604,4624,4627,4638,4810,4812,4816,4823,4826,4830,4840,4880,4883,4890,4915,4926,4929,4936,5005,5007,5009,5068,5073],[11,4317,4319],{"id":4318},"作品-1-solar-system","作品 1 — Solar System",[15,4321,4322],{},"CSS アニメーションだけで動く太陽系です。惑星・軌道・星空・太陽の光量変化をすべて CSS で実現しています。",[4324,4325],"solar-system",{},[2241,4327,4328],{"id":4328},"軌道アニメーションの仕組み",[15,4330,4331],{},"各惑星は「軌道リング（div）が回転し、その端に惑星が貼りついている」という構造です。",[54,4333,4335],{"className":56,"code":4334,"language":58,"meta":59,"style":59},"\u002F* 軌道リングが中心を原点に回転する *\u002F\n.orbit-ring {\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  border-radius: 50%;\n  animation: spin linear infinite;\n}\n\n@keyframes spin {\n  to { transform: rotate(360deg); }\n}\n",[32,4336,4337,4342,4349,4361,4375,4388,4401,4414,4418,4422,4430,4450],{"__ignoreMap":59},[63,4338,4339],{"class":65,"line":66},[63,4340,4341],{"class":88},"\u002F* 軌道リングが中心を原点に回転する *\u002F\n",[63,4343,4344,4347],{"class":65,"line":76},[63,4345,4346],{"class":160},".orbit-ring",[63,4348,164],{"class":72},[63,4350,4351,4354,4356,4359],{"class":65,"line":92},[63,4352,4353],{"class":169},"  position",[63,4355,173],{"class":72},[63,4357,4358],{"class":169},"absolute",[63,4360,267],{"class":72},[63,4362,4363,4366,4368,4371,4373],{"class":65,"line":101},[63,4364,4365],{"class":169},"  top",[63,4367,173],{"class":72},[63,4369,4370],{"class":169},"50",[63,4372,211],{"class":69},[63,4374,267],{"class":72},[63,4376,4377,4380,4382,4384,4386],{"class":65,"line":114},[63,4378,4379],{"class":169},"  left",[63,4381,173],{"class":72},[63,4383,4370],{"class":169},[63,4385,211],{"class":69},[63,4387,267],{"class":72},[63,4389,4390,4393,4395,4397,4399],{"class":65,"line":229},[63,4391,4392],{"class":169},"  border-radius",[63,4394,173],{"class":72},[63,4396,4370],{"class":169},[63,4398,211],{"class":69},[63,4400,267],{"class":72},[63,4402,4403,4405,4407,4410,4412],{"class":65,"line":240},[63,4404,249],{"class":169},[63,4406,252],{"class":72},[63,4408,4409],{"class":169},"linear",[63,4411,264],{"class":169},[63,4413,267],{"class":72},[63,4415,4416],{"class":65,"line":246},[63,4417,117],{"class":72},[63,4419,4420],{"class":65,"line":270},[63,4421,279],{"emptyLinePlaceholder":278},[63,4423,4424,4426,4428],{"class":65,"line":275},[63,4425,285],{"class":69},[63,4427,288],{"class":193},[63,4429,164],{"class":72},[63,4431,4432,4434,4436,4438,4440,4442,4444,4446,4448],{"class":65,"line":282},[63,4433,296],{"class":160},[63,4435,299],{"class":72},[63,4437,2639],{"class":169},[63,4439,173],{"class":72},[63,4441,3972],{"class":169},[63,4443,190],{"class":72},[63,4445,306],{"class":169},[63,4447,309],{"class":69},[63,4449,2666],{"class":72},[63,4451,4452],{"class":65,"line":293},[63,4453,117],{"class":72},[15,4455,4456,4457,4460],{},"惑星は軌道リングの上端（",[32,4458,4459],{},"top: -半径px","）に配置するだけ。リングが回れば惑星が円軌道を描きます。",[54,4462,4464],{"className":708,"code":4463,"language":710,"meta":59,"style":59},"\u002F\u002F 4惑星のデータ定義\nconst planets = [\n  { orbit: 55,  period: 2.5,  size: 7,  color: '#9ca3af' }, \u002F\u002F 水星\n  { orbit: 88,  period: 6,    size: 11, color: '#d97706' }, \u002F\u002F 金星\n  { orbit: 124, period: 11,   size: 12, color: '#00DC82' }, \u002F\u002F 地球\n  { orbit: 162, period: 19,   size: 9,  color: '#ef4444' }, \u002F\u002F 火星\n]\n",[32,4465,4466,4471,4482,4512,4539,4566,4593],{"__ignoreMap":59},[63,4467,4468],{"class":65,"line":66},[63,4469,4470],{"class":88},"\u002F\u002F 4惑星のデータ定義\n",[63,4472,4473,4475,4478,4480],{"class":65,"line":76},[63,4474,952],{"class":69},[63,4476,4477],{"class":169}," planets",[63,4479,769],{"class":69},[63,4481,1985],{"class":72},[63,4483,4484,4487,4490,4493,4495,4498,4500,4503,4506,4509],{"class":65,"line":92},[63,4485,4486],{"class":72},"  { orbit: ",[63,4488,4489],{"class":169},"55",[63,4491,4492],{"class":72},",  period: ",[63,4494,3782],{"class":169},[63,4496,4497],{"class":72},",  size: ",[63,4499,483],{"class":169},[63,4501,4502],{"class":72},",  color: ",[63,4504,4505],{"class":1103},"'#9ca3af'",[63,4507,4508],{"class":72}," }, ",[63,4510,4511],{"class":88},"\u002F\u002F 水星\n",[63,4513,4514,4516,4519,4521,4523,4526,4528,4531,4534,4536],{"class":65,"line":101},[63,4515,4486],{"class":72},[63,4517,4518],{"class":169},"88",[63,4520,4492],{"class":72},[63,4522,4170],{"class":169},[63,4524,4525],{"class":72},",    size: ",[63,4527,509],{"class":169},[63,4529,4530],{"class":72},", color: ",[63,4532,4533],{"class":1103},"'#d97706'",[63,4535,4508],{"class":72},[63,4537,4538],{"class":88},"\u002F\u002F 金星\n",[63,4540,4541,4543,4546,4549,4551,4554,4556,4558,4561,4563],{"class":65,"line":114},[63,4542,4486],{"class":72},[63,4544,4545],{"class":169},"124",[63,4547,4548],{"class":72},", period: ",[63,4550,509],{"class":169},[63,4552,4553],{"class":72},",   size: ",[63,4555,3836],{"class":169},[63,4557,4530],{"class":72},[63,4559,4560],{"class":1103},"'#00DC82'",[63,4562,4508],{"class":72},[63,4564,4565],{"class":88},"\u002F\u002F 地球\n",[63,4567,4568,4570,4573,4575,4578,4580,4583,4585,4588,4590],{"class":65,"line":229},[63,4569,4486],{"class":72},[63,4571,4572],{"class":169},"162",[63,4574,4548],{"class":72},[63,4576,4577],{"class":169},"19",[63,4579,4553],{"class":72},[63,4581,4582],{"class":169},"9",[63,4584,4502],{"class":72},[63,4586,4587],{"class":1103},"'#ef4444'",[63,4589,4508],{"class":72},[63,4591,4592],{"class":88},"\u002F\u002F 火星\n",[63,4594,4595],{"class":65,"line":240},[63,4596,4597],{"class":72},"]\n",[15,4599,4600,4603],{},[32,4601,4602],{},"animationDelay"," に負の値を設定することで、ビルド時点での惑星の開始位置をずらせます。",[54,4605,4607],{"className":708,"code":4606,"language":710,"meta":59,"style":59},"animationDelay: p.delay + 's'  \u002F\u002F 例: -4.5s → 4.5秒分進んだ状態から開始\n",[32,4608,4609],{"__ignoreMap":59},[63,4610,4611,4613,4616,4618,4621],{"class":65,"line":66},[63,4612,4602],{"class":160},[63,4614,4615],{"class":72},": p.delay ",[63,4617,1644],{"class":69},[63,4619,4620],{"class":1103}," 's'",[63,4622,4623],{"class":88},"  \u002F\u002F 例: -4.5s → 4.5秒分進んだ状態から開始\n",[2241,4625,4626],{"id":4626},"太陽の脈動",[15,4628,4629,1735,4631,4634,4635,4637],{},[32,4630,342],{},[32,4632,4633],{},"filter: blur"," の組み合わせで自然な光彩を表現し、 ",[32,4636,42],{}," で明滅させています。",[54,4639,4641],{"className":56,"code":4640,"language":58,"meta":59,"style":59},".sun-halo {\n  background: radial-gradient(circle, rgba(255,180,0,0.35) 0%, transparent 70%);\n  animation: pulse 3s ease-in-out infinite;\n}\n\n@keyframes pulse {\n  0%, 100% { transform: scale(1);   opacity: 0.5; }\n  50%       { transform: scale(1.4); opacity: 1;   }\n}\n",[32,4642,4643,4650,4704,4723,4727,4731,4740,4775,4806],{"__ignoreMap":59},[63,4644,4645,4648],{"class":65,"line":66},[63,4646,4647],{"class":160},".sun-halo",[63,4649,164],{"class":72},[63,4651,4652,4654,4656,4658,4660,4662,4664,4667,4669,4672,4675,4677,4679,4681,4683,4686,4688,4690,4692,4694,4697,4700,4702],{"class":65,"line":76},[63,4653,170],{"class":169},[63,4655,173],{"class":72},[63,4657,342],{"class":169},[63,4659,190],{"class":72},[63,4661,3651],{"class":169},[63,4663,734],{"class":72},[63,4665,4666],{"class":169},"rgba",[63,4668,190],{"class":72},[63,4670,4671],{"class":169},"255",[63,4673,4674],{"class":72},",",[63,4676,2685],{"class":169},[63,4678,4674],{"class":72},[63,4680,1120],{"class":169},[63,4682,4674],{"class":72},[63,4684,4685],{"class":169},"0.35",[63,4687,841],{"class":72},[63,4689,1120],{"class":169},[63,4691,211],{"class":69},[63,4693,734],{"class":72},[63,4695,4696],{"class":169},"transparent",[63,4698,4699],{"class":169}," 70",[63,4701,211],{"class":69},[63,4703,396],{"class":72},[63,4705,4706,4708,4711,4714,4716,4719,4721],{"class":65,"line":92},[63,4707,249],{"class":169},[63,4709,4710],{"class":72},": pulse ",[63,4712,4713],{"class":169},"3",[63,4715,258],{"class":69},[63,4717,4718],{"class":169}," ease-in-out",[63,4720,264],{"class":169},[63,4722,267],{"class":72},[63,4724,4725],{"class":65,"line":101},[63,4726,117],{"class":72},[63,4728,4729],{"class":65,"line":114},[63,4730,279],{"emptyLinePlaceholder":278},[63,4732,4733,4735,4738],{"class":65,"line":229},[63,4734,285],{"class":69},[63,4736,4737],{"class":193}," pulse",[63,4739,164],{"class":72},[63,4741,4742,4745,4747,4750,4752,4754,4756,4758,4760,4762,4765,4768,4770,4773],{"class":65,"line":240},[63,4743,4744],{"class":160},"  0%",[63,4746,734],{"class":72},[63,4748,4749],{"class":160},"100%",[63,4751,299],{"class":72},[63,4753,2639],{"class":169},[63,4755,173],{"class":72},[63,4757,2412],{"class":169},[63,4759,190],{"class":72},[63,4761,2158],{"class":169},[63,4763,4764],{"class":72},");   ",[63,4766,4767],{"class":169},"opacity",[63,4769,173],{"class":72},[63,4771,4772],{"class":169},"0.5",[63,4774,2903],{"class":72},[63,4776,4777,4780,4783,4785,4787,4789,4791,4794,4797,4799,4801,4803],{"class":65,"line":246},[63,4778,4779],{"class":160},"  50%",[63,4781,4782],{"class":72},"       { ",[63,4784,2639],{"class":169},[63,4786,173],{"class":72},[63,4788,2412],{"class":169},[63,4790,190],{"class":72},[63,4792,4793],{"class":169},"1.4",[63,4795,4796],{"class":72},"); ",[63,4798,4767],{"class":169},[63,4800,173],{"class":72},[63,4802,2158],{"class":169},[63,4804,4805],{"class":72},";   }\n",[63,4807,4808],{"class":65,"line":270},[63,4809,117],{"class":72},[22,4811],{},[11,4813,4815],{"id":4814},"作品-2-neon-city","作品 2 — Neon City",[15,4817,4818,4819,4822],{},"SVG で描いたネオン都市です。",[32,4820,4821],{},"\u003Cfilter>"," によるウィンドウの発光と、変換行列で作る水面リフレクションが特徴です。",[4824,4825],"neon-city",{},[2241,4827,4829],{"id":4828},"svg-フィルターでネオン発光","SVG フィルターでネオン発光",[15,4831,4832,4835,4836,4839],{},[32,4833,4834],{},"\u003CfeGaussianBlur>"," でぼかし画像を生成し、元画像と合成（",[32,4837,4838],{},"feMerge","）することでグロー効果を作ります。",[54,4841,4843],{"className":3504,"code":4842,"language":3506,"meta":59,"style":59},"\u003Cfilter id=\"win-glow\">\n  \u003CfeGaussianBlur stdDeviation=\"2.5\" result=\"blur\" \u002F>\n  \u003CfeMerge>\n    \u003CfeMergeNode in=\"blur\" \u002F>       \u003C!-- ぼかした光 -->\n    \u003CfeMergeNode in=\"SourceGraphic\" \u002F> \u003C!-- 元のウィンドウ -->\n  \u003C\u002FfeMerge>\n\u003C\u002Ffilter>\n",[32,4844,4845,4850,4855,4860,4865,4870,4875],{"__ignoreMap":59},[63,4846,4847],{"class":65,"line":66},[63,4848,4849],{},"\u003Cfilter id=\"win-glow\">\n",[63,4851,4852],{"class":65,"line":76},[63,4853,4854],{},"  \u003CfeGaussianBlur stdDeviation=\"2.5\" result=\"blur\" \u002F>\n",[63,4856,4857],{"class":65,"line":92},[63,4858,4859],{},"  \u003CfeMerge>\n",[63,4861,4862],{"class":65,"line":101},[63,4863,4864],{},"    \u003CfeMergeNode in=\"blur\" \u002F>       \u003C!-- ぼかした光 -->\n",[63,4866,4867],{"class":65,"line":114},[63,4868,4869],{},"    \u003CfeMergeNode in=\"SourceGraphic\" \u002F> \u003C!-- 元のウィンドウ -->\n",[63,4871,4872],{"class":65,"line":229},[63,4873,4874],{},"  \u003C\u002FfeMerge>\n",[63,4876,4877],{"class":65,"line":240},[63,4878,4879],{},"\u003C\u002Ffilter>\n",[2241,4881,4882],{"id":4882},"水面リフレクション",[15,4884,4885,4886,4889],{},"建物・窓を ",[32,4887,4888],{},"scale(1, -1)"," で上下反転し、地面ラインを軸に折り返すことで水面の映り込みを表現します。",[54,4891,4893],{"className":3504,"code":4892,"language":3506,"meta":59,"style":59},"\u003C!-- translate(0, GROUND*2) で反転後の位置を地面ラインに揃える -->\n\u003Cg transform=\"translate(0, 600) scale(1, -1)\" mask=\"url(#reflect-fade)\">\n  \u003C!-- 同じ建物・窓を再描画 -->\n\u003C\u002Fg>\n",[32,4894,4895,4900,4905,4910],{"__ignoreMap":59},[63,4896,4897],{"class":65,"line":66},[63,4898,4899],{},"\u003C!-- translate(0, GROUND*2) で反転後の位置を地面ラインに揃える -->\n",[63,4901,4902],{"class":65,"line":76},[63,4903,4904],{},"\u003Cg transform=\"translate(0, 600) scale(1, -1)\" mask=\"url(#reflect-fade)\">\n",[63,4906,4907],{"class":65,"line":92},[63,4908,4909],{},"  \u003C!-- 同じ建物・窓を再描画 -->\n",[63,4911,4912],{"class":65,"line":101},[63,4913,4914],{},"\u003C\u002Fg>\n",[15,4916,4917,4918,4921,4922,4925],{},"フェードマスクは ",[32,4919,4920],{},"linearGradient","（白→透明）を ",[32,4923,4924],{},"\u003Cmask>"," で適用して、水面が下に向かうほど薄くなるように制御しています。",[2241,4927,4928],{"id":4928},"ウィンドウの決定論的生成",[15,4930,4931,4932,4935],{},"JavaScript の乱数（",[32,4933,4934],{},"Math.random()","）は SSR とクライアントでズレてハイドレーションエラーになります。\nそのため、ビルドインデックスから計算する決定論的な式でウィンドウの点灯パターンを決めています。",[54,4937,4939],{"className":708,"code":4938,"language":710,"meta":59,"style":59},"const seed = (buildingIndex * 31 + row * 17 + col * 7) % 100\nconst isLit = seed > 38  \u002F\u002F 約 62% が点灯\n",[32,4940,4941,4985],{"__ignoreMap":59},[63,4942,4943,4945,4948,4950,4953,4955,4958,4960,4963,4965,4968,4970,4973,4975,4978,4980,4982],{"class":65,"line":66},[63,4944,952],{"class":69},[63,4946,4947],{"class":169}," seed",[63,4949,769],{"class":69},[63,4951,4952],{"class":72}," (buildingIndex ",[63,4954,824],{"class":69},[63,4956,4957],{"class":169}," 31",[63,4959,830],{"class":69},[63,4961,4962],{"class":72}," row ",[63,4964,824],{"class":69},[63,4966,4967],{"class":169}," 17",[63,4969,830],{"class":69},[63,4971,4972],{"class":72}," col ",[63,4974,824],{"class":69},[63,4976,4977],{"class":169}," 7",[63,4979,841],{"class":72},[63,4981,211],{"class":69},[63,4983,4984],{"class":169}," 100\n",[63,4986,4987,4989,4992,4994,4997,4999,5002],{"class":65,"line":76},[63,4988,952],{"class":69},[63,4990,4991],{"class":169}," isLit",[63,4993,769],{"class":69},[63,4995,4996],{"class":72}," seed ",[63,4998,82],{"class":69},[63,5000,5001],{"class":169}," 38",[63,5003,5004],{"class":88},"  \u002F\u002F 約 62% が点灯\n",[22,5006],{},[11,5008,558],{"id":558},[560,5010,5011,5022],{},[563,5012,5013],{},[566,5014,5015,5017,5019],{},[569,5016,571],{},[569,5018,580],{},[569,5020,5021],{},"難しい点",[582,5023,5024,5035,5046,5057],{},[566,5025,5026,5029,5032],{},[587,5027,5028],{},"CSS animation",[587,5030,5031],{},"繰り返し動作・軌道・脈動",[587,5033,5034],{},"複雑な形状の制御",[566,5036,5037,5040,5043],{},[587,5038,5039],{},"SVG filter",[587,5041,5042],{},"発光・ぼかし・影",[587,5044,5045],{},"フィルター定義の記述量",[566,5047,5048,5051,5054],{},[587,5049,5050],{},"SVG transform",[587,5052,5053],{},"反転・スケール・鏡像",[587,5055,5056],{},"座標計算が必要",[566,5058,5059,5062,5065],{},[587,5060,5061],{},"CSS radial-gradient",[587,5063,5064],{},"光源・オーブ・背景",[587,5066,5067],{},"ブラウザ差異がある場合も",[398,5069,5070],{"type":400},[15,5071,5072],{},"CSS と SVG を組み合わせると、互いの弱点を補い合えます。アニメーションは CSS、複雑なフィルターは SVG というように使い分けましょう。",[643,5074,5075],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":59,"searchDepth":76,"depth":76,"links":5077},[5078,5082,5087],{"id":4318,"depth":76,"text":4319,"children":5079},[5080,5081],{"id":4328,"depth":92,"text":4328},{"id":4626,"depth":92,"text":4626},{"id":4814,"depth":76,"text":4815,"children":5083},[5084,5085,5086],{"id":4828,"depth":92,"text":4829},{"id":4882,"depth":92,"text":4882},{"id":4928,"depth":92,"text":4928},{"id":558,"depth":76,"text":558},"2026-05-01T14:00:00+09:00","CSS @keyframes による太陽系アニメーションと、SVG フィルター・リフレクションを使ったネオン都市の制作過程を解説します。",{},"\u002Farticles\u002Fcss-animation-art",{"title":4313,"description":5089},"articles\u002Fcss-animation-art","VJnvJBALLbCuVIy-O_YmpCPaNPOQAP6cgz8X0pHEPGo",{"id":5096,"title":5097,"body":5098,"date":5421,"description":5422,"extension":656,"meta":5423,"navigation":278,"path":5424,"seo":5425,"stem":5426,"__hash__":5427},"articles\u002Farticles\u002Fcss-art.md","CSS と MDC でアートを描く",{"type":8,"value":5099,"toc":5413},[5100,5104,5117,5121,5124,5129,5140,5181,5189,5224,5228,5231,5235,5241,5355,5357,5361,5364,5370,5373,5379,5381,5385,5395,5407,5410],[11,5101,5103],{"id":5102},"css-アート","CSS アート",[15,5105,5106,5107,5110,5111,5110,5114,5116],{},"コードだけで絵を描けます。画像ファイルは一切使わず、CSS の ",[32,5108,5109],{},"background","・",[32,5112,5113],{},"border-radius",[32,5115,342],{}," だけで構成しています。",[2241,5118,5120],{"id":5119},"glow-光るオーブ","Glow — 光るオーブ",[15,5122,5123],{},"暗いキャンバスに同心円と放射グラデーションを重ねた作品です。",[5125,5126],"css-art",{"caption":5127,"type":5128},"Glow \u002F CSS radial-gradient + concentric rings","glow",[15,5130,5131,5132,5135,5136,5139],{},"グリッド線は ",[32,5133,5134],{},"background-image"," に2方向の ",[32,5137,5138],{},"linear-gradient"," を重ねて描いています。",[54,5141,5143],{"className":56,"code":5142,"language":58,"meta":59,"style":59},"background-image:\n  linear-gradient(rgba(0, 220, 130, 0.06) 1px, transparent 1px),\n  linear-gradient(90deg, rgba(0, 220, 130, 0.06) 1px, transparent 1px);\nbackground-size: 36px 36px;\n",[32,5144,5145,5152,5163,5173],{"__ignoreMap":59},[63,5146,5147,5149],{"class":65,"line":66},[63,5148,5134],{"class":104},[63,5150,5151],{"class":72},":\n",[63,5153,5154,5157,5160],{"class":65,"line":76},[63,5155,5156],{"class":72},"  linear-gradient(rgba(0, 220, 130, 0",[63,5158,5159],{"class":160},".06",[63,5161,5162],{"class":72},") 1px, transparent 1px),\n",[63,5164,5165,5168,5170],{"class":65,"line":92},[63,5166,5167],{"class":72},"  linear-gradient(90deg, rgba(0, 220, 130, 0",[63,5169,5159],{"class":160},[63,5171,5172],{"class":72},") 1px, transparent 1px);\n",[63,5174,5175,5178],{"class":65,"line":101},[63,5176,5177],{"class":104},"background-size",[63,5179,5180],{"class":72},": 36px 36px;\n",[15,5182,5183,5184,1735,5186,5188],{},"中心の光は ",[32,5185,342],{},[32,5187,4633],{}," の組み合わせです。",[54,5190,5192],{"className":56,"code":5191,"language":58,"meta":59,"style":59},"background: radial-gradient(circle, #00DC82 0%, rgba(0, 220, 130, 0.6) 40%, transparent 70%);\nfilter: blur(4px);\n",[32,5193,5194,5216],{"__ignoreMap":59},[63,5195,5196,5199,5201,5203,5207,5210,5213],{"class":65,"line":66},[63,5197,5198],{"class":72},"background: radial-gradient(",[63,5200,3651],{"class":104},[63,5202,734],{"class":72},[63,5204,5206],{"class":5205},"s7hpK","#00DC82",[63,5208,5209],{"class":72}," 0%, rgba(0, 220, 130, 0",[63,5211,5212],{"class":160},".6",[63,5214,5215],{"class":72},") 40%, transparent 70%);\n",[63,5217,5218,5221],{"class":65,"line":76},[63,5219,5220],{"class":104},"filter",[63,5222,5223],{"class":72},": blur(4px);\n",[2241,5225,5227],{"id":5226},"mondrian-モンドリアン風","Mondrian — モンドリアン風",[15,5229,5230],{},"ピエト・モンドリアンの抽象絵画にインスパイアされた作品です。CSS Grid で区画を分割し、白・黒・グリーンで塗り分けています。",[5125,5232],{"caption":5233,"type":5234},"Mondrian \u002F CSS Grid composition","mondrian",[15,5236,5237,5240],{},[32,5238,5239],{},"grid-area"," でそれぞれのブロックの位置とサイズを指定します。",[54,5242,5244],{"className":56,"code":5243,"language":58,"meta":59,"style":59},".green { grid-area: 1\u002F1\u002F3\u002F2; background: #00DC82; }\n.white { grid-area: 1\u002F2\u002F2\u002F4; background: #f9fafb; }\n.black { grid-area: 1\u002F4\u002F3\u002F5; background: #18181b; }\n",[32,5245,5246,5282,5318],{"__ignoreMap":59},[63,5247,5248,5251,5253,5255,5257,5259,5261,5263,5265,5267,5269,5272,5274,5276,5278,5280],{"class":65,"line":66},[63,5249,5250],{"class":160},".green",[63,5252,299],{"class":72},[63,5254,5239],{"class":169},[63,5256,173],{"class":72},[63,5258,2158],{"class":169},[63,5260,775],{"class":72},[63,5262,2158],{"class":169},[63,5264,775],{"class":72},[63,5266,4713],{"class":169},[63,5268,775],{"class":72},[63,5270,5271],{"class":169},"2",[63,5273,2881],{"class":72},[63,5275,5109],{"class":169},[63,5277,173],{"class":72},[63,5279,5206],{"class":169},[63,5281,2903],{"class":72},[63,5283,5284,5287,5289,5291,5293,5295,5297,5299,5301,5303,5305,5307,5309,5311,5313,5316],{"class":65,"line":76},[63,5285,5286],{"class":160},".white",[63,5288,299],{"class":72},[63,5290,5239],{"class":169},[63,5292,173],{"class":72},[63,5294,2158],{"class":169},[63,5296,775],{"class":72},[63,5298,5271],{"class":169},[63,5300,775],{"class":72},[63,5302,5271],{"class":169},[63,5304,775],{"class":72},[63,5306,255],{"class":169},[63,5308,2881],{"class":72},[63,5310,5109],{"class":169},[63,5312,173],{"class":72},[63,5314,5315],{"class":169},"#f9fafb",[63,5317,2903],{"class":72},[63,5319,5320,5323,5325,5327,5329,5331,5333,5335,5337,5339,5341,5344,5346,5348,5350,5353],{"class":65,"line":92},[63,5321,5322],{"class":160},".black",[63,5324,299],{"class":72},[63,5326,5239],{"class":169},[63,5328,173],{"class":72},[63,5330,2158],{"class":169},[63,5332,775],{"class":72},[63,5334,255],{"class":169},[63,5336,775],{"class":72},[63,5338,4713],{"class":169},[63,5340,775],{"class":72},[63,5342,5343],{"class":169},"5",[63,5345,2881],{"class":72},[63,5347,5109],{"class":169},[63,5349,173],{"class":72},[63,5351,5352],{"class":169},"#18181b",[63,5354,2903],{"class":72},[22,5356],{},[11,5358,5360],{"id":5359},"ascii-アート","ASCII アート",[15,5362,5363],{},"文字だけで絵を描く ASCII アートも、Markdown のコードブロックで表現できます。",[54,5365,5368],{"className":5366,"code":5367,"language":691},[689],"    ██████╗ ██╗      ██████╗  ██╗    ██╗\n   ██╔════╝ ██║     ██╔═══██╗ ██║    ██║\n   ██║  ███╗██║     ██║   ██║ ██║ █╗ ██║\n   ██║   ██║██║     ██║   ██║ ██║███╗██║\n   ╚██████╔╝███████╗╚██████╔╝ ╚███╔███╔╝\n    ╚═════╝ ╚══════╝ ╚═════╝   ╚══╝╚══╝\n",[32,5369,5367],{"__ignoreMap":59},[15,5371,5372],{},"シンプルな図形を文字で描くこともできます。",[54,5374,5377],{"className":5375,"code":5376,"language":691},[689],"        *\n       ***\n      *****\n     *******\n    *********\n       |||\n",[32,5378,5376],{"__ignoreMap":59},[22,5380],{},[11,5382,5384],{"id":5383},"mdc-がアートを可能にする","MDC がアートを可能にする",[15,5386,5387,5390,5391,5394],{},[32,5388,5389],{},"::css-art{type=\"glow\"}"," のように書くだけで、Vue コンポーネントを Markdown の中に埋め込めます。\n",[32,5392,5393],{},"components\u002Fcontent\u002F"," に置いたコンポーネントは自動的に MDC で使えるようになります。",[398,5396,5397],{"type":400},[15,5398,5399,5400,5402,5403,5406],{},"コンポーネント名はケバブケース（",[32,5401,5125],{},"）で呼び出します。ファイル名 ",[32,5404,5405],{},"CssArt.vue"," が自動的に変換されます。",[15,5408,5409],{},"コードとデザインを1ファイルに閉じ込められるのが、CSS アートと MDC の組み合わせの強みです。",[643,5411,5412],{},"html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s7hpK, html code.shiki .s7hpK{--shiki-default:#B31D28;--shiki-default-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":59,"searchDepth":76,"depth":76,"links":5414},[5415,5419,5420],{"id":5102,"depth":76,"text":5103,"children":5416},[5417,5418],{"id":5119,"depth":92,"text":5120},{"id":5226,"depth":92,"text":5227},{"id":5359,"depth":76,"text":5360},{"id":5383,"depth":76,"text":5384},"2026-05-01T10:00:00+09:00","Nuxt Content の MDC コンポーネントと CSS だけで、コードからアートを表現する試みです。",{},"\u002Farticles\u002Fcss-art",{"title":5097,"description":5422},"articles\u002Fcss-art","UwgqeWxMeK2RwXHWM0yQq4tbL3qYGwIKPJ4hgU2j38Q",{"id":5429,"title":5430,"body":5431,"date":6203,"description":6204,"extension":656,"meta":6205,"navigation":278,"path":6206,"seo":6207,"stem":6208,"__hash__":6209},"articles\u002Farticles\u002Fnuxt-content-features.md","Nuxt Content でできる表現方法まとめ",{"type":8,"value":5432,"toc":6177},[5433,5436,5460,5463,5467,5470,5475,5478,5481,5485,5520,5523,5550,5554,5563,5566,5580,5583,5667,5670,5672,5684,5688,5872,5876,5988,5992,6034,6038,6041,6043,6046,6050,6060,6064,6070,6079,6086,6093,6101,6105,6111,6121,6125,6165,6168,6174],[11,5434,5435],{"id":5435},"テキスト装飾",[15,5437,5438,5439,5110,5442,5110,5446,5110,5450,5453,5454,5459],{},"通常のテキストに加えて、",[49,5440,5441],{},"太字",[5443,5444,5445],"em",{},"イタリック",[5447,5448,5449],"del",{},"打ち消し線",[32,5451,5452],{},"インラインコード"," が使えます。\n組み合わせも可能で、",[5443,5455,5456],{},[49,5457,5458],{},"太字かつイタリック"," のような表現もできます。",[11,5461,5462],{"id":5462},"見出しレベル",[2241,5464,5466],{"id":5465},"h3-セクションの小見出し","h3 — セクションの小見出し",[15,5468,5469],{},"h3 は記事内のセクションをさらに細分化するときに使います。",[5471,5472,5474],"h4",{"id":5473},"h4-さらに細かい区分け","h4 — さらに細かい区分け",[15,5476,5477],{},"h4 は補足説明や用語の定義など、特定のトピックを掘り下げる際に便利です。",[11,5479,5480],{"id":5480},"リスト",[2241,5482,5484],{"id":5483},"箇条書き順不同","箇条書き（順不同）",[5486,5487,5488,5492,5498],"ul",{},[5489,5490,5491],"li",{},"Nuxt 4 はファイルベースルーティングを採用している",[5489,5493,5494,5497],{},[32,5495,5496],{},"pages\u002F"," にファイルを置くだけでルートが生成される",[5489,5499,5500,5501],{},"ネストしたディレクトリで階層的なURLも作れる\n",[5486,5502,5503,5512],{},[5489,5504,5505,5506,127,5509],{},"例：",[32,5507,5508],{},"pages\u002Farticles\u002F[slug].vue",[32,5510,5511],{},"\u002Farticles\u002Fhello",[5489,5513,5505,5514,127,5517],{},[32,5515,5516],{},"pages\u002Fsettings\u002Fprofile.vue",[32,5518,5519],{},"\u002Fsettings\u002Fprofile",[2241,5521,5522],{"id":5522},"番号付きリスト",[5524,5525,5526,5532,5538,5544],"ol",{},[5489,5527,5528,5531],{},[32,5529,5530],{},"nuxi init"," でプロジェクトを作成する",[5489,5533,5534,5537],{},[32,5535,5536],{},"npm install"," で依存関係をインストールする",[5489,5539,5540,5543],{},[32,5541,5542],{},"npm run dev"," で開発サーバーを起動する",[5489,5545,5546,5549],{},[32,5547,5548],{},"http:\u002F\u002Flocalhost:3000"," にアクセスして確認する",[11,5551,5553],{"id":5552},"引用blockquote","引用（blockquote）",[5555,5556,5557,5560],"blockquote",{},[15,5558,5559],{},"Nuxt は「設定より規約」の思想で設計されており、ファイルを置くだけで多くのことが自動化されます。",[15,5561,5562],{},"— Nuxt 公式ドキュメントより",[11,5564,5565],{"id":5565},"リンク",[15,5567,5568,39,5574,5579],{},[1755,5569,5573],{"href":5570,"rel":5571},"https:\u002F\u002Fnuxt.com",[5572],"nofollow","Nuxt 公式サイト",[1755,5575,5578],{"href":5576,"rel":5577},"https:\u002F\u002Fcontent.nuxt.com",[5572],"Nuxt Content ドキュメント"," へのリンクをテキスト内に埋め込めます。",[11,5581,5582],{"id":5582},"テーブル",[560,5584,5585,5601],{},[563,5586,5587],{},[566,5588,5589,5592,5595,5598],{},[569,5590,5591],{},"機能",[569,5593,5594],{},"SSR",[569,5596,5597],{},"SSG",[569,5599,5600],{},"SPA",[582,5602,5603,5617,5630,5643,5654],{},[566,5604,5605,5608,5611,5614],{},[587,5606,5607],{},"初回表示速度",[587,5609,5610],{},"速い",[587,5612,5613],{},"最速",[587,5615,5616],{},"遅い",[566,5618,5619,5622,5625,5628],{},[587,5620,5621],{},"サーバー負荷",[587,5623,5624],{},"高い",[587,5626,5627],{},"なし",[587,5629,5627],{},[566,5631,5632,5635,5638,5640],{},[587,5633,5634],{},"SEO",[587,5636,5637],{},"◎",[587,5639,5637],{},[587,5641,5642],{},"△",[566,5644,5645,5648,5650,5652],{},[587,5646,5647],{},"リアルタイム性",[587,5649,5637],{},[587,5651,5642],{},[587,5653,5637],{},[566,5655,5656,5659,5662,5665],{},[587,5657,5658],{},"ビルド時間",[587,5660,5661],{},"短い",[587,5663,5664],{},"長くなる",[587,5666,5661],{},[11,5668,5669],{"id":5669},"コードブロック",[2241,5671,5452],{"id":5452},[15,5673,5674,5110,5677,5110,5680,5683],{},[32,5675,5676],{},"useAsyncData",[32,5678,5679],{},"useFetch",[32,5681,5682],{},"defineEventHandler"," のような関数名はインラインコードで表記します。",[2241,5685,5687],{"id":5686},"vue-コンポーネント","Vue コンポーネント",[54,5689,5691],{"className":3635,"code":5690,"language":3637,"meta":59,"style":59},"\u003Cscript setup lang=\"ts\">\nconst { data: articles } = await useAsyncData('articles', () =>\n  queryCollection('articles').order('date', 'DESC').all()\n)\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cul>\n    \u003Cli v-for=\"article in articles\" :key=\"article.path\">\n      {{ article.title }}\n    \u003C\u002Fli>\n  \u003C\u002Ful>\n\u003C\u002Ftemplate>\n",[32,5692,5693,5714,5749,5781,5785,5794,5798,5807,5816,5841,5846,5855,5864],{"__ignoreMap":59},[63,5694,5695,5697,5700,5703,5706,5708,5711],{"class":65,"line":66},[63,5696,1480],{"class":72},[63,5698,5699],{"class":104},"script",[63,5701,5702],{"class":160}," setup",[63,5704,5705],{"class":160}," lang",[63,5707,979],{"class":72},[63,5709,5710],{"class":1103},"\"ts\"",[63,5712,5713],{"class":72},">\n",[63,5715,5716,5718,5720,5723,5725,5728,5731,5733,5736,5739,5741,5744,5747],{"class":65,"line":76},[63,5717,952],{"class":69},[63,5719,299],{"class":72},[63,5721,5722],{"class":193},"data",[63,5724,173],{"class":72},[63,5726,5727],{"class":169},"articles",[63,5729,5730],{"class":72}," } ",[63,5732,979],{"class":69},[63,5734,5735],{"class":69}," await",[63,5737,5738],{"class":160}," useAsyncData",[63,5740,190],{"class":72},[63,5742,5743],{"class":1103},"'articles'",[63,5745,5746],{"class":72},", () ",[63,5748,4183],{"class":69},[63,5750,5751,5754,5756,5758,5761,5764,5766,5769,5771,5774,5776,5779],{"class":65,"line":92},[63,5752,5753],{"class":160},"  queryCollection",[63,5755,190],{"class":72},[63,5757,5743],{"class":1103},[63,5759,5760],{"class":72},").",[63,5762,5763],{"class":160},"order",[63,5765,190],{"class":72},[63,5767,5768],{"class":1103},"'date'",[63,5770,734],{"class":72},[63,5772,5773],{"class":1103},"'DESC'",[63,5775,5760],{"class":72},[63,5777,5778],{"class":160},"all",[63,5780,1394],{"class":72},[63,5782,5783],{"class":65,"line":101},[63,5784,907],{"class":72},[63,5786,5787,5790,5792],{"class":65,"line":114},[63,5788,5789],{"class":72},"\u003C\u002F",[63,5791,5699],{"class":104},[63,5793,5713],{"class":72},[63,5795,5796],{"class":65,"line":229},[63,5797,279],{"emptyLinePlaceholder":278},[63,5799,5800,5802,5805],{"class":65,"line":240},[63,5801,1480],{"class":72},[63,5803,5804],{"class":104},"template",[63,5806,5713],{"class":72},[63,5808,5809,5812,5814],{"class":65,"line":246},[63,5810,5811],{"class":72},"  \u003C",[63,5813,5486],{"class":104},[63,5815,5713],{"class":72},[63,5817,5818,5821,5823,5826,5828,5831,5834,5836,5839],{"class":65,"line":270},[63,5819,5820],{"class":72},"    \u003C",[63,5822,5489],{"class":104},[63,5824,5825],{"class":160}," v-for",[63,5827,979],{"class":72},[63,5829,5830],{"class":1103},"\"article in articles\"",[63,5832,5833],{"class":160}," :key",[63,5835,979],{"class":72},[63,5837,5838],{"class":1103},"\"article.path\"",[63,5840,5713],{"class":72},[63,5842,5843],{"class":65,"line":275},[63,5844,5845],{"class":72},"      {{ article.title }}\n",[63,5847,5848,5851,5853],{"class":65,"line":282},[63,5849,5850],{"class":72},"    \u003C\u002F",[63,5852,5489],{"class":104},[63,5854,5713],{"class":72},[63,5856,5857,5860,5862],{"class":65,"line":293},[63,5858,5859],{"class":72},"  \u003C\u002F",[63,5861,5486],{"class":104},[63,5863,5713],{"class":72},[63,5865,5866,5868,5870],{"class":65,"line":318},[63,5867,5789],{"class":72},[63,5869,5804],{"class":104},[63,5871,5713],{"class":72},[2241,5873,5875],{"id":5874},"typescript","TypeScript",[54,5877,5879],{"className":708,"code":5878,"language":710,"meta":59,"style":59},"interface Article {\n  title: string\n  description: string\n  date: string\n  path: string\n}\n\nfunction formatDate(dateStr: string): string {\n  return new Date(dateStr).toLocaleDateString('ja-JP')\n}\n",[32,5880,5881,5891,5901,5910,5919,5928,5932,5936,5961,5984],{"__ignoreMap":59},[63,5882,5883,5886,5889],{"class":65,"line":66},[63,5884,5885],{"class":69},"interface",[63,5887,5888],{"class":160}," Article",[63,5890,164],{"class":72},[63,5892,5893,5896,5898],{"class":65,"line":76},[63,5894,5895],{"class":193},"  title",[63,5897,728],{"class":69},[63,5899,5900],{"class":169}," string\n",[63,5902,5903,5906,5908],{"class":65,"line":92},[63,5904,5905],{"class":193},"  description",[63,5907,728],{"class":69},[63,5909,5900],{"class":169},[63,5911,5912,5915,5917],{"class":65,"line":101},[63,5913,5914],{"class":193},"  date",[63,5916,728],{"class":69},[63,5918,5900],{"class":169},[63,5920,5921,5924,5926],{"class":65,"line":114},[63,5922,5923],{"class":193},"  path",[63,5925,728],{"class":69},[63,5927,5900],{"class":169},[63,5929,5930],{"class":65,"line":229},[63,5931,117],{"class":72},[63,5933,5934],{"class":65,"line":240},[63,5935,279],{"emptyLinePlaceholder":278},[63,5937,5938,5940,5943,5945,5948,5950,5953,5955,5957,5959],{"class":65,"line":246},[63,5939,717],{"class":69},[63,5941,5942],{"class":160}," formatDate",[63,5944,190],{"class":72},[63,5946,5947],{"class":193},"dateStr",[63,5949,728],{"class":69},[63,5951,5952],{"class":169}," string",[63,5954,752],{"class":72},[63,5956,728],{"class":69},[63,5958,5952],{"class":169},[63,5960,164],{"class":72},[63,5962,5963,5965,5968,5971,5974,5977,5979,5982],{"class":65,"line":270},[63,5964,807],{"class":69},[63,5966,5967],{"class":69}," new",[63,5969,5970],{"class":160}," Date",[63,5972,5973],{"class":72},"(dateStr).",[63,5975,5976],{"class":160},"toLocaleDateString",[63,5978,190],{"class":72},[63,5980,5981],{"class":1103},"'ja-JP'",[63,5983,907],{"class":72},[63,5985,5986],{"class":65,"line":275},[63,5987,117],{"class":72},[2241,5989,5991],{"id":5990},"shell-コマンド","Shell コマンド",[54,5993,5997],{"className":5994,"code":5995,"language":5996,"meta":59,"style":59},"language-bash shiki shiki-themes github-light github-dark","# @nuxt\u002Fcontent をインストール\nnpm install @nuxt\u002Fcontent\n\n# ビルドして静的ファイルを生成\nnpm run build\n","bash",[32,5998,5999,6004,6015,6019,6024],{"__ignoreMap":59},[63,6000,6001],{"class":65,"line":66},[63,6002,6003],{"class":88},"# @nuxt\u002Fcontent をインストール\n",[63,6005,6006,6009,6012],{"class":65,"line":76},[63,6007,6008],{"class":160},"npm",[63,6010,6011],{"class":1103}," install",[63,6013,6014],{"class":1103}," @nuxt\u002Fcontent\n",[63,6016,6017],{"class":65,"line":92},[63,6018,279],{"emptyLinePlaceholder":278},[63,6020,6021],{"class":65,"line":101},[63,6022,6023],{"class":88},"# ビルドして静的ファイルを生成\n",[63,6025,6026,6028,6031],{"class":65,"line":114},[63,6027,6008],{"class":160},[63,6029,6030],{"class":1103}," run",[63,6032,6033],{"class":1103}," build\n",[11,6035,6037],{"id":6036},"水平線区切り","水平線（区切り）",[15,6039,6040],{},"上のセクションと下のセクションを視覚的に区切るには、水平線を使います。",[22,6042],{},[15,6044,6045],{},"水平線はコンテンツの大きな切れ目に使うのが一般的です。",[11,6047,6049],{"id":6048},"mdc-markdown-components","MDC — Markdown Components",[15,6051,6052,6053,6056,6057,6059],{},"@nuxt\u002Fcontent v3 では ",[49,6054,6055],{},"MDC（Markdown Components）"," 記法を使って、Markdown の中から Vue コンポーネントを直接呼び出せます。",[32,6058,5393],{}," に置いたコンポーネントが自動的に利用可能になります。",[2241,6061,6063],{"id":6062},"callout-コンポーネント","Callout コンポーネント",[15,6065,6066,6069],{},[32,6067,6068],{},"::コンポーネント名"," で囲むとブロックコンポーネントとして展開されます。",[398,6071,6073],{"type":6072},"info",[15,6074,6075,6076,6078],{},"これは ",[49,6077,6072],{}," タイプの Callout です。補足情報や背景知識を伝えるときに使います。",[398,6080,6081],{"type":400},[15,6082,6075,6083,6085],{},[49,6084,400],{}," タイプの Callout です。ベストプラクティスや便利な使い方を紹介するときに使います。",[398,6087,6088],{"type":636},[15,6089,6075,6090,6092],{},[49,6091,636],{}," タイプの Callout です。ハマりやすいポイントや注意事項を伝えるときに使います。",[398,6094,6096],{"type":6095},"danger",[15,6097,6075,6098,6100],{},[49,6099,6095],{}," タイプの Callout です。データ消失や破壊的操作など、特に注意が必要な情報に使います。",[2241,6102,6104],{"id":6103},"title-プロパティで見出しをカスタマイズ","title プロパティで見出しをカスタマイズ",[15,6106,6107,6110],{},[32,6108,6109],{},"title"," プロパティを渡すと、ラベル文字列を自由に変更できます。",[398,6112,6114],{"type":400,"title":6113},"✨ ポイント",[15,6115,6116,6117,6120],{},"MDC では ",[32,6118,6119],{},"{prop=\"value\"}"," の形式でコンポーネントに props を渡せます。文字列・数値・真偽値に対応しています。",[2241,6122,6124],{"id":6123},"mdc-の書き方まとめ","MDC の書き方まとめ",[54,6126,6129],{"className":6127,"code":6128,"language":656,"meta":59,"style":59},"language-md shiki shiki-themes github-light github-dark","\u002F\u002F ブロックコンポーネント（props あり）\n::callout{type=\"warning\"}\n本文テキスト\n::\n\n\u002F\u002F インラインコンポーネント（将来の拡張例）\n:badge{label=\"NEW\"}\n",[32,6130,6131,6136,6141,6146,6151,6155,6160],{"__ignoreMap":59},[63,6132,6133],{"class":65,"line":66},[63,6134,6135],{"class":72},"\u002F\u002F ブロックコンポーネント（props あり）\n",[63,6137,6138],{"class":65,"line":76},[63,6139,6140],{"class":72},"::callout{type=\"warning\"}\n",[63,6142,6143],{"class":65,"line":92},[63,6144,6145],{"class":72},"本文テキスト\n",[63,6147,6148],{"class":65,"line":101},[63,6149,6150],{"class":72},"::\n",[63,6152,6153],{"class":65,"line":114},[63,6154,279],{"emptyLinePlaceholder":278},[63,6156,6157],{"class":65,"line":229},[63,6158,6159],{"class":72},"\u002F\u002F インラインコンポーネント（将来の拡張例）\n",[63,6161,6162],{"class":65,"line":240},[63,6163,6164],{"class":72},":badge{label=\"NEW\"}\n",[11,6166,6167],{"id":6167},"まとめ",[15,6169,6170,6171,6173],{},"@nuxt\u002Fcontent v3 では、標準的な Markdown 記法に加えて MDC による Vue コンポーネントの埋め込みができます。",[32,6172,5393],{}," にコンポーネントを置くだけで Markdown ファイルから参照でき、デザインの統一されたリッチなコンテンツを簡単に作れます。",[643,6175,6176],{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":59,"searchDepth":76,"depth":76,"links":6178},[6179,6180,6183,6187,6188,6189,6190,6196,6197,6202],{"id":5435,"depth":76,"text":5435},{"id":5462,"depth":76,"text":5462,"children":6181},[6182],{"id":5465,"depth":92,"text":5466},{"id":5480,"depth":76,"text":5480,"children":6184},[6185,6186],{"id":5483,"depth":92,"text":5484},{"id":5522,"depth":92,"text":5522},{"id":5552,"depth":76,"text":5553},{"id":5565,"depth":76,"text":5565},{"id":5582,"depth":76,"text":5582},{"id":5669,"depth":76,"text":5669,"children":6191},[6192,6193,6194,6195],{"id":5452,"depth":92,"text":5452},{"id":5686,"depth":92,"text":5687},{"id":5874,"depth":92,"text":5875},{"id":5990,"depth":92,"text":5991},{"id":6036,"depth":76,"text":6037},{"id":6048,"depth":76,"text":6049,"children":6198},[6199,6200,6201],{"id":6062,"depth":92,"text":6063},{"id":6103,"depth":92,"text":6104},{"id":6123,"depth":92,"text":6124},{"id":6167,"depth":76,"text":6167},"2026-04-30T23:30:00+09:00","見出し・コード・テーブル・引用・MDC コンポーネントなど、@nuxt\u002Fcontent v3 で使えるMarkdown 記法と表現方法を網羅的に紹介します。",{},"\u002Farticles\u002Fnuxt-content-features",{"title":5430,"description":6204},"articles\u002Fnuxt-content-features","fvAUEGlLAYc44jGhXXGhMYJHuyXstL7HEf4E1XeU2Qw",{"id":6211,"title":6212,"body":6213,"date":6562,"description":6563,"extension":656,"meta":6564,"navigation":278,"path":6565,"seo":6566,"stem":6567,"__hash__":6568},"articles\u002Farticles\u002Fseo-with-nuxt.md","Nuxt で SEO を強化する",{"type":8,"value":6214,"toc":6555},[6215,6218,6225,6324,6327,6337,6410,6414,6427,6479,6483,6490,6547,6549,6552],[11,6216,6217],{"id":6217},"メタ情報の設定",[15,6219,6220,6221,6224],{},"Nuxt では ",[32,6222,6223],{},"useSeoMeta"," を使うと、タイトル・description・OGP を型安全に設定できます。",[54,6226,6228],{"className":3635,"code":6227,"language":3637,"meta":59,"style":59},"\u003Cscript setup lang=\"ts\">\nuseSeoMeta({\n  title: 'ページタイトル',\n  description: 'このページの説明文（160文字以内）',\n  ogTitle: 'ページタイトル',\n  ogDescription: 'OGP 用の説明文',\n  ogImage: 'https:\u002F\u002Fexample.com\u002Fog.png',\n  twitterCard: 'summary_large_image',\n})\n\u003C\u002Fscript>\n",[32,6229,6230,6246,6253,6263,6273,6282,6292,6302,6312,6316],{"__ignoreMap":59},[63,6231,6232,6234,6236,6238,6240,6242,6244],{"class":65,"line":66},[63,6233,1480],{"class":72},[63,6235,5699],{"class":104},[63,6237,5702],{"class":160},[63,6239,5705],{"class":160},[63,6241,979],{"class":72},[63,6243,5710],{"class":1103},[63,6245,5713],{"class":72},[63,6247,6248,6250],{"class":65,"line":76},[63,6249,6223],{"class":160},[63,6251,6252],{"class":72},"({\n",[63,6254,6255,6258,6261],{"class":65,"line":92},[63,6256,6257],{"class":72},"  title: ",[63,6259,6260],{"class":1103},"'ページタイトル'",[63,6262,214],{"class":72},[63,6264,6265,6268,6271],{"class":65,"line":101},[63,6266,6267],{"class":72},"  description: ",[63,6269,6270],{"class":1103},"'このページの説明文（160文字以内）'",[63,6272,214],{"class":72},[63,6274,6275,6278,6280],{"class":65,"line":114},[63,6276,6277],{"class":72},"  ogTitle: ",[63,6279,6260],{"class":1103},[63,6281,214],{"class":72},[63,6283,6284,6287,6290],{"class":65,"line":229},[63,6285,6286],{"class":72},"  ogDescription: ",[63,6288,6289],{"class":1103},"'OGP 用の説明文'",[63,6291,214],{"class":72},[63,6293,6294,6297,6300],{"class":65,"line":240},[63,6295,6296],{"class":72},"  ogImage: ",[63,6298,6299],{"class":1103},"'https:\u002F\u002Fexample.com\u002Fog.png'",[63,6301,214],{"class":72},[63,6303,6304,6307,6310],{"class":65,"line":246},[63,6305,6306],{"class":72},"  twitterCard: ",[63,6308,6309],{"class":1103},"'summary_large_image'",[63,6311,214],{"class":72},[63,6313,6314],{"class":65,"line":270},[63,6315,1551],{"class":72},[63,6317,6318,6320,6322],{"class":65,"line":275},[63,6319,5789],{"class":72},[63,6321,5699],{"class":104},[63,6323,5713],{"class":72},[11,6325,6326],{"id":6326},"サイトマップの自動生成",[15,6328,6329,6332,6333,6336],{},[32,6330,6331],{},"@nuxtjs\u002Fsitemap"," を使うと ",[32,6334,6335],{},"sitemap.xml"," が自動生成されます。",[54,6338,6340],{"className":708,"code":6339,"language":710,"meta":59,"style":59},"\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  modules: ['@nuxtjs\u002Fsitemap'],\n  site: { url: 'https:\u002F\u002Fyour-site.com' },\n  sitemap: {\n    sources: ['\u002Fapi\u002F__sitemap__\u002Furls'], \u002F\u002F 動的ルートを追加\n  },\n})\n",[32,6341,6342,6347,6360,6371,6382,6387,6401,6406],{"__ignoreMap":59},[63,6343,6344],{"class":65,"line":66},[63,6345,6346],{"class":88},"\u002F\u002F nuxt.config.ts\n",[63,6348,6349,6352,6355,6358],{"class":65,"line":76},[63,6350,6351],{"class":69},"export",[63,6353,6354],{"class":69}," default",[63,6356,6357],{"class":160}," defineNuxtConfig",[63,6359,6252],{"class":72},[63,6361,6362,6365,6368],{"class":65,"line":92},[63,6363,6364],{"class":72},"  modules: [",[63,6366,6367],{"class":1103},"'@nuxtjs\u002Fsitemap'",[63,6369,6370],{"class":72},"],\n",[63,6372,6373,6376,6379],{"class":65,"line":101},[63,6374,6375],{"class":72},"  site: { url: ",[63,6377,6378],{"class":1103},"'https:\u002F\u002Fyour-site.com'",[63,6380,6381],{"class":72}," },\n",[63,6383,6384],{"class":65,"line":114},[63,6385,6386],{"class":72},"  sitemap: {\n",[63,6388,6389,6392,6395,6398],{"class":65,"line":229},[63,6390,6391],{"class":72},"    sources: [",[63,6393,6394],{"class":1103},"'\u002Fapi\u002F__sitemap__\u002Furls'",[63,6396,6397],{"class":72},"], ",[63,6399,6400],{"class":88},"\u002F\u002F 動的ルートを追加\n",[63,6402,6403],{"class":65,"line":240},[63,6404,6405],{"class":72},"  },\n",[63,6407,6408],{"class":65,"line":246},[63,6409,1551],{"class":72},[11,6411,6413],{"id":6412},"robotstxt-の設定","robots.txt の設定",[15,6415,6416,6419,6420,6422,6423,6426],{},[32,6417,6418],{},"@nuxtjs\u002Frobots"," を ",[32,6421,6331],{}," と一緒に使うと、",[32,6424,6425],{},"Sitemap:"," 行が自動で追記されます。",[54,6428,6430],{"className":708,"code":6429,"language":710,"meta":59,"style":59},"robots: {\n  groups: [\n    { userAgent: '*', allow: '\u002F', disallow: ['\u002Fadmin'] }\n  ]\n}\n",[32,6431,6432,6440,6448,6471,6475],{"__ignoreMap":59},[63,6433,6434,6437],{"class":65,"line":66},[63,6435,6436],{"class":160},"robots",[63,6438,6439],{"class":72},": {\n",[63,6441,6442,6445],{"class":65,"line":76},[63,6443,6444],{"class":160},"  groups",[63,6446,6447],{"class":72},": [\n",[63,6449,6450,6453,6456,6459,6462,6465,6468],{"class":65,"line":92},[63,6451,6452],{"class":72},"    { userAgent: ",[63,6454,6455],{"class":1103},"'*'",[63,6457,6458],{"class":72},", allow: ",[63,6460,6461],{"class":1103},"'\u002F'",[63,6463,6464],{"class":72},", disallow: [",[63,6466,6467],{"class":1103},"'\u002Fadmin'",[63,6469,6470],{"class":72},"] }\n",[63,6472,6473],{"class":65,"line":101},[63,6474,2089],{"class":72},[63,6476,6477],{"class":65,"line":114},[63,6478,117],{"class":72},[11,6480,6482],{"id":6481},"canonical-url-の設定","Canonical URL の設定",[15,6484,6485,6486,6489],{},"動的ルートでは ",[32,6487,6488],{},"useHead"," で canonical を設定して重複コンテンツを防ぎます。",[54,6491,6493],{"className":708,"code":6492,"language":710,"meta":59,"style":59},"const route = useRoute()\nuseHead({\n  link: [{ rel: 'canonical', href: `https:\u002F\u002Fyour-site.com${route.path}` }]\n})\n",[32,6494,6495,6509,6515,6543],{"__ignoreMap":59},[63,6496,6497,6499,6502,6504,6507],{"class":65,"line":66},[63,6498,952],{"class":69},[63,6500,6501],{"class":169}," route",[63,6503,769],{"class":69},[63,6505,6506],{"class":160}," useRoute",[63,6508,1394],{"class":72},[63,6510,6511,6513],{"class":65,"line":76},[63,6512,6488],{"class":160},[63,6514,6252],{"class":72},[63,6516,6517,6520,6523,6526,6529,6532,6534,6537,6540],{"class":65,"line":92},[63,6518,6519],{"class":72},"  link: [{ rel: ",[63,6521,6522],{"class":1103},"'canonical'",[63,6524,6525],{"class":72},", href: ",[63,6527,6528],{"class":1103},"`https:\u002F\u002Fyour-site.com${",[63,6530,6531],{"class":72},"route",[63,6533,1530],{"class":1103},[63,6535,6536],{"class":72},"path",[63,6538,6539],{"class":1103},"}`",[63,6541,6542],{"class":72}," }]\n",[63,6544,6545],{"class":65,"line":101},[63,6546,1551],{"class":72},[11,6548,6167],{"id":6167},[15,6550,6551],{},"SEO 対策は「コンテンツが HTML に含まれているか（SSR\u002FSSG）」「メタ情報が適切か」「サイトマップが存在するか」の3点が基本です。Nuxt はこれらをすべてサポートしています。",[643,6553,6554],{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":59,"searchDepth":76,"depth":76,"links":6556},[6557,6558,6559,6560,6561],{"id":6217,"depth":76,"text":6217},{"id":6326,"depth":76,"text":6326},{"id":6412,"depth":76,"text":6413},{"id":6481,"depth":76,"text":6482},{"id":6167,"depth":76,"text":6167},"2026-04-28T23:30:00+09:00","useSeoMeta・sitemap・robots.txt を組み合わせて検索エンジン対策を行う方法を解説します。",{},"\u002Farticles\u002Fseo-with-nuxt",{"title":6212,"description":6563},"articles\u002Fseo-with-nuxt","F1gW1bO1db6woj7N3WCJL87dKyhHqi5gP2fZDPLtce4",{"id":6570,"title":6571,"body":6572,"date":6792,"description":6793,"extension":656,"meta":6794,"navigation":278,"path":6795,"seo":6796,"stem":6797,"__hash__":6798},"articles\u002Farticles\u002Fssg-vs-ssr.md","SSG と SSR の違い",{"type":8,"value":6573,"toc":6786},[6574,6577,6650,6654,6661,6744,6748,6755,6757,6783],[11,6575,6576],{"id":6576},"レンダリング方式の比較",[560,6578,6579,6594],{},[563,6580,6581],{},[566,6582,6583,6586,6589,6591],{},[569,6584,6585],{},"方式",[569,6587,6588],{},"タイミング",[569,6590,5634],{},[569,6592,6593],{},"向いているページ",[582,6595,6596,6610,6623,6636],{},[566,6597,6598,6601,6604,6607],{},[587,6599,6600],{},"CSR",[587,6602,6603],{},"ブラウザで描画",[587,6605,6606],{},"弱い",[587,6608,6609],{},"管理画面・ダッシュボード",[566,6611,6612,6614,6617,6620],{},[587,6613,5594],{},[587,6615,6616],{},"リクエスト時にサーバーで描画",[587,6618,6619],{},"強い",[587,6621,6622],{},"動的コンテンツ・ユーザー固有ページ",[566,6624,6625,6627,6630,6633],{},[587,6626,5597],{},[587,6628,6629],{},"ビルド時に静的 HTML を生成",[587,6631,6632],{},"最強・高速",[587,6634,6635],{},"ブログ・LP・ドキュメント",[566,6637,6638,6641,6644,6647],{},[587,6639,6640],{},"ISR",[587,6642,6643],{},"ビルド後も一定時間ごとに再生成",[587,6645,6646],{},"強い・更新可能",[587,6648,6649],{},"頻繁に更新される記事",[11,6651,6653],{"id":6652},"nuxt-での設定方法","Nuxt での設定方法",[15,6655,6656,6657,6660],{},"Nuxt はデフォルト SSR です。",[32,6658,6659],{},"routeRules"," を使うとページごとに切り替えられます。",[54,6662,6664],{"className":708,"code":6663,"language":710,"meta":59,"style":59},"\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  routeRules: {\n    '\u002Farticles\u002F**': { prerender: true }, \u002F\u002F SSG\n    '\u002Fdashboard\u002F**': { ssr: false },     \u002F\u002F CSR（SPA）\n    '\u002Fnews\u002F**': { isr: 3600 },           \u002F\u002F ISR（1時間ごとに再生成）\n  }\n})\n",[32,6665,6666,6670,6680,6685,6701,6718,6735,6740],{"__ignoreMap":59},[63,6667,6668],{"class":65,"line":66},[63,6669,6346],{"class":88},[63,6671,6672,6674,6676,6678],{"class":65,"line":76},[63,6673,6351],{"class":69},[63,6675,6354],{"class":69},[63,6677,6357],{"class":160},[63,6679,6252],{"class":72},[63,6681,6682],{"class":65,"line":92},[63,6683,6684],{"class":72},"  routeRules: {\n",[63,6686,6687,6690,6693,6696,6698],{"class":65,"line":101},[63,6688,6689],{"class":1103},"    '\u002Farticles\u002F**'",[63,6691,6692],{"class":72},": { prerender: ",[63,6694,6695],{"class":169},"true",[63,6697,4508],{"class":72},[63,6699,6700],{"class":88},"\u002F\u002F SSG\n",[63,6702,6703,6706,6709,6712,6715],{"class":65,"line":114},[63,6704,6705],{"class":1103},"    '\u002Fdashboard\u002F**'",[63,6707,6708],{"class":72},": { ssr: ",[63,6710,6711],{"class":169},"false",[63,6713,6714],{"class":72}," },     ",[63,6716,6717],{"class":88},"\u002F\u002F CSR（SPA）\n",[63,6719,6720,6723,6726,6729,6732],{"class":65,"line":229},[63,6721,6722],{"class":1103},"    '\u002Fnews\u002F**'",[63,6724,6725],{"class":72},": { isr: ",[63,6727,6728],{"class":169},"3600",[63,6730,6731],{"class":72}," },           ",[63,6733,6734],{"class":88},"\u002F\u002F ISR（1時間ごとに再生成）\n",[63,6736,6737],{"class":65,"line":240},[63,6738,6739],{"class":72},"  }\n",[63,6741,6742],{"class":65,"line":246},[63,6743,1551],{"class":72},[11,6745,6747],{"id":6746},"ssr-を確認する方法","SSR を確認する方法",[15,6749,6750,6751,6754],{},"ブラウザの「ページのソースを表示」を開いて、記事本文が HTML に含まれていれば SSR（または SSG）が正しく動作しています。CSR の場合、JS 実行前は空の ",[32,6752,6753],{},"\u003Cdiv>"," しか存在しません。",[11,6756,6167],{"id":6167},[5486,6758,6759,6765,6771,6777],{},[5489,6760,6761,6764],{},[49,6762,6763],{},"ブログ・ドキュメント"," → SSG（速くて SEO 最強）",[5489,6766,6767,6770],{},[49,6768,6769],{},"EC サイト商品ページ"," → ISR（キャッシュしつつ鮮度を保つ）",[5489,6772,6773,6776],{},[49,6774,6775],{},"ニュースフィード"," → SSR（常に最新を返す）",[5489,6778,6779,6782],{},[49,6780,6781],{},"管理画面"," → CSR（SEO 不要・インタラクション重視）",[643,6784,6785],{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":59,"searchDepth":76,"depth":76,"links":6787},[6788,6789,6790,6791],{"id":6576,"depth":76,"text":6576},{"id":6652,"depth":76,"text":6653},{"id":6746,"depth":76,"text":6747},{"id":6167,"depth":76,"text":6167},"2026-04-28T23:15:00+09:00","それぞれのレンダリング方式の特徴と、Nuxt での使い分けを整理します。",{},"\u002Farticles\u002Fssg-vs-ssr",{"title":6571,"description":6793},"articles\u002Fssg-vs-ssr","WVl3BADGFnzPWQ9OtqJGW4wRrU_dsOUa_CO3fUO27GM",{"id":6800,"title":6801,"body":6802,"date":6949,"description":6950,"extension":656,"meta":6951,"navigation":278,"path":6952,"seo":6953,"stem":6954,"__hash__":6955},"articles\u002Farticles\u002Fhello-nuxt.md","Nuxt をはじめよう",{"type":8,"value":6803,"toc":6943},[6804,6808,6814,6817,6859,6865,6868,6931,6933,6940],[11,6805,6807],{"id":6806},"nuxt-とは","Nuxt とは",[15,6809,6810,6811,6813],{},"Nuxt は Vue 3 ベースのフルスタックフレームワークです。",[32,6812,5496],{}," にファイルを置くだけでルーティングが自動生成され、SSR・SSG・ISR を設定ひとつで切り替えられます。",[11,6815,6816],{"id":6816},"プロジェクトの作成",[54,6818,6820],{"className":5994,"code":6819,"language":5996,"meta":59,"style":59},"npx nuxi@latest init my-app\ncd my-app\nnpm install\nnpm run dev\n",[32,6821,6822,6836,6843,6850],{"__ignoreMap":59},[63,6823,6824,6827,6830,6833],{"class":65,"line":66},[63,6825,6826],{"class":160},"npx",[63,6828,6829],{"class":1103}," nuxi@latest",[63,6831,6832],{"class":1103}," init",[63,6834,6835],{"class":1103}," my-app\n",[63,6837,6838,6841],{"class":65,"line":76},[63,6839,6840],{"class":169},"cd",[63,6842,6835],{"class":1103},[63,6844,6845,6847],{"class":65,"line":92},[63,6846,6008],{"class":160},[63,6848,6849],{"class":1103}," install\n",[63,6851,6852,6854,6856],{"class":65,"line":101},[63,6853,6008],{"class":160},[63,6855,6030],{"class":1103},[63,6857,6858],{"class":1103}," dev\n",[15,6860,6861,6862,6864],{},"ブラウザで ",[32,6863,5548],{}," にアクセスすると、デフォルトのウェルカムページが表示されます。",[11,6866,6867],{"id":6867},"ディレクトリ構成",[560,6869,6870,6880],{},[563,6871,6872],{},[566,6873,6874,6877],{},[569,6875,6876],{},"ディレクトリ",[569,6878,6879],{},"役割",[582,6881,6882,6891,6901,6911,6921],{},[566,6883,6884,6888],{},[587,6885,6886],{},[32,6887,5496],{},[587,6889,6890],{},"URL に対応するページ",[566,6892,6893,6898],{},[587,6894,6895],{},[32,6896,6897],{},"components\u002F",[587,6899,6900],{},"再利用できる UI パーツ",[566,6902,6903,6908],{},[587,6904,6905],{},[32,6906,6907],{},"composables\u002F",[587,6909,6910],{},"再利用できるロジック",[566,6912,6913,6918],{},[587,6914,6915],{},[32,6916,6917],{},"server\u002Fapi\u002F",[587,6919,6920],{},"サーバー API エンドポイント",[566,6922,6923,6928],{},[587,6924,6925],{},[32,6926,6927],{},"content\u002F",[587,6929,6930],{},"Markdown などのコンテンツファイル",[11,6932,6167],{"id":6167},[15,6934,6935,6936,6939],{},"Nuxt は「設定より規約」の思想で設計されており、ファイルを置くだけで多くのことが自動化されます。まずは ",[32,6937,6938],{},"pages\u002Findex.vue"," を編集してみましょう。",[643,6941,6942],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":59,"searchDepth":76,"depth":76,"links":6944},[6945,6946,6947,6948],{"id":6806,"depth":76,"text":6807},{"id":6816,"depth":76,"text":6816},{"id":6867,"depth":76,"text":6867},{"id":6167,"depth":76,"text":6167},"2026-04-28T23:00:00+09:00","Nuxt の基本的なセットアップ方法と、プロジェクト構造の概要を解説します。",{},"\u002Farticles\u002Fhello-nuxt",{"title":6801,"description":6950},"articles\u002Fhello-nuxt","dJgeWR8Jp-wvIT2KoxdDWbpEeYEhJmxCGw9-NhVxxGI",1777568741854]