Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 58 additions & 42 deletions .vitepress/theme/components/CustomLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,57 +9,74 @@ const enableTransitions = () =>
"startViewTransition" in document &&
window.matchMedia("(prefers-reduced-motion: no-preference)").matches;

provide("toggle-appearance", async () => {
provide("toggle-appearance", async (event) => {
if (!enableTransitions()) {
isDark.value = !isDark.value;
return;
}

const innerWidth = window.innerWidth + 10;
const innerHeight = window.innerHeight + 10;
const x = event?.clientX ?? window.innerWidth / 2;
const y = event?.clientY ?? 0;

const vw = innerWidth / 100;
const vh = innerHeight / 100;
// 星の凹み(内側頂点)が画面の最遠隅より外に出れば全面を覆える
const innerRate = 0.45;
const maxRadius =
(Math.hypot(
Math.max(x, window.innerWidth - x),
Math.max(y, window.innerHeight - y),
) /
0.38) *
1.05;

const maskImage =
`url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${200 * vw} ${100 * vh}">
<defs>
<filter id="blur">
<feGaussianBlur stdDeviation="30"/>
</filter>
</defs>
<polygon points="
${90 * vw} 0 ${200 * vw},0 ${200 * vw},${100 * vh}
${30 * vw},${100 * vh} ${30 * vw},${66 * vh}
${60 * vw},${66 * vh} ${60 * vw},${33 * vh}
${90 * vw},${33 * vh}
" fill="white" filter="url(%23blur)" />
</svg>')`.replace(/\s+/gu, " ");
const star = (radius, rotate) => {
const points = [];
for (let i = 0; i < 10; i++) {
const r = i % 2 === 0 ? radius : radius * innerRate;
const a = (Math.PI / 5) * i + rotate;
points.push(
`${(x + r * Math.sin(a)).toFixed(1)}px ${(y - r * Math.cos(a)).toFixed(1)}px`,
);
}
return `polygon(${points.join(",")})`;
};

await document.startViewTransition(async () => {
isDark.value = !isDark.value;
await nextTick();
}).ready;
// 回転を先行させ、半径は後から追いつかせて「ひねりながら開く」動きにする
const keyframes = [
[0, 0],
[0.12, 0.4],
[0.35, 0.7],
[0.68, 0.9],
[1, 1],
].map(([growth, spin]) => ({
clipPath: star(maxRadius * growth, Math.PI * 0.8 * spin),
}));

const maskPosition = [
`${100 * vw}px -${5 * vh}px`,
`-${100 * vw}px -${5 * vh}px`,
];
const maskSize = `${220 * vw}px ${110 * vh}px`;
let starAnimation;
try {
const transition = document.startViewTransition(async () => {
isDark.value = !isDark.value;
await nextTick();
});
await transition.ready;

document.documentElement.animate(
{
maskImage: [maskImage, maskImage],
maskPosition: isDark.value ? maskPosition.reverse() : maskPosition,
maskSize: [maskSize, maskSize],
},
{
duration: 300,
easing: "ease-in",
fill: "forwards",
pseudoElement: `::view-transition-${isDark.value ? "old" : "new"}(root)`,
},
);
starAnimation = document.documentElement.animate(
isDark.value ? keyframes.reverse() : keyframes,
{
duration: 500,
easing: "ease-in-out",
fill: "forwards",
pseudoElement: `::view-transition-${isDark.value ? "old" : "new"}(root)`,
},
);
await transition.finished;
} catch {
// ページ遷移などでトランジションが破棄された場合。テーマ自体は切り替え済み
} finally {
// fill: forwards のアニメーションはトランジション終了後も残留し、
// 次回のトグルで同名の擬似要素が再生成された瞬間に前回の最終状態
// (全面表示のクリップ)が再適用されて画面が一瞬素通しになるため、必ず破棄する
starAnimation?.cancel();
}
});
</script>

Expand All @@ -72,7 +89,6 @@ provide("toggle-appearance", async () => {
::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
mask-repeat: no-repeat;
}

::view-transition-old(root),
Expand Down
52 changes: 42 additions & 10 deletions .vitepress/theme/components/FutureStar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ const starPath = `path("M 0 ${starSize / 2} l ${starSize * lengthRate} -${starSi
left: v-bind(-starWidth + "px");
filter: blur(3px);
transform-origin: left 50%;
opacity: 0.1;
opacity: 0.15;
}
.dark .future-star__container {
opacity: 0.2;
opacity: 0.3;
}
.future-star--kind-1 {
transform: rotate(-6deg);
Expand All @@ -42,29 +42,61 @@ const starPath = `path("M 0 ${starSize / 2} l ${starSize * lengthRate} -${starSi
}
.future-star {
position: absolute;
background-color: #da0058;
/* 尾に向かって透明になるグラデーションで彗星らしい残像を出す */
background: linear-gradient(
90deg,
transparent,
#da0058 45%,
#ff4d88 90%,
#ffb3cd
);
height: v-bind(starSize + "px");
width: v-bind(starWidth + "px");
clip-path: v-bind(starPath);
transform-origin: right center; /* 先端(右)を基点に尾が伸縮する */
opacity: 0;

animation-composition: add;
animation-name: slide-to-right;
animation-duration: 10s;
animation-name: star-streak;
animation-duration: 9s;
animation-iteration-count: infinite;
animation-timing-function: linear;
/* 加速して飛び込み、減速して抜ける */
animation-timing-function: cubic-bezier(0.45, 0, 0.4, 1);
}
.future-star--kind-2 .future-star {
animation-delay: 250ms;
/* 2本目はわずかに遅らせて並走させる(飛翔中に必ず2本同時に見えるずれ幅) */
animation-delay: 150ms;
}
@keyframes slide-to-right {
@keyframes star-streak {
0% {
left: 0;
opacity: 0;
transform: scaleX(0.5);
}
50% {
2% {
opacity: 1;
}
8% {
/* 最高速付近で尾が伸びる */
transform: scaleX(1.2);
}
13% {
opacity: 1;
}
15% {
left: 100%;
opacity: 0;
transform: scaleX(0.6);
}
100% {
left: 100%;
opacity: 0;
}
}
@media (prefers-reduced-motion: reduce) {
.future-star {
animation: none;
left: 30%;
opacity: 0.6;
}
}
</style>
94 changes: 94 additions & 0 deletions .vitepress/theme/style.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
:root {
--vp-home-hero-name-color: transparent;
/* ヒーロー背景を漂うオーロラの色斑(ライトは朝焼け風の淡いトーン) */
--hero-aurora-pink: rgba(229, 0, 79, 0.14);
--hero-aurora-blue: rgba(40, 70, 190, 0.12);
--vp-home-hero-name-background: -webkit-linear-gradient(
120deg,
#0a1561 30%,
Expand All @@ -13,6 +16,9 @@
#fff 30%,
#e5004f
);
/* ダークは夜空のオーロラ風に少し強める */
--hero-aurora-pink: rgba(229, 0, 79, 0.26);
--hero-aurora-blue: rgba(110, 130, 255, 0.18);
/* 背景が透過である画像が、ダークモードで視認性が下がるための対応 */
.img-bg-transparent img {
filter: invert(1);
Expand Down Expand Up @@ -51,6 +57,94 @@
white-space: nowrap;
}

/* オーロラ背景: ブランドカラーの色斑がヒーロー背景をゆっくり漂う */
.standards-home .VPHero {
position: relative;
/* 色斑のはみ出しを閉じ込め、擬似要素の z-index: -1 をヒーロー内に留める */
overflow: hidden;
isolation: isolate;
}
.standards-home .VPHero::before,
.standards-home .VPHero::after {
content: "";
position: absolute;
z-index: -1;
border-radius: 50%;
filter: blur(48px);
pointer-events: none;
}
.standards-home .VPHero::before {
width: 560px;
height: 360px;
left: 48%;
top: -80px;
background: radial-gradient(
circle at 45% 45%,
var(--hero-aurora-pink),
transparent 70%
);
}
.standards-home .VPHero::after {
width: 480px;
height: 380px;
left: 4%;
top: 120px;
background: radial-gradient(
circle at 55% 50%,
var(--hero-aurora-blue),
transparent 70%
);
}

/* ヒーロー要素の登場アニメーション */
@media (prefers-reduced-motion: no-preference) {
.standards-home .VPHero .name,
.standards-home .VPHero .tagline,
.standards-home .VPHero .actions {
animation: hero-rise 0.8s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.standards-home .VPHero .tagline {
animation-delay: 0.15s;
}
.standards-home .VPHero .actions {
animation-delay: 0.3s;
}

/* オーロラのドリフト(reduced-motion時は静止表示のまま) */
.standards-home .VPHero::before {
animation: hero-aurora-a 13s ease-in-out infinite alternate;
}
.standards-home .VPHero::after {
animation: hero-aurora-b 17s ease-in-out infinite alternate;
}
}
@keyframes hero-aurora-a {
from {
transform: translate(0, 0) scale(1);
}
to {
transform: translate(-120px, 40px) scale(1.25);
}
}
@keyframes hero-aurora-b {
from {
transform: translate(0, 0) scale(1.1);
}
to {
transform: translate(140px, -30px) scale(0.9);
}
}
@keyframes hero-rise {
from {
opacity: 0;
transform: translateY(18px);
}
to {
opacity: 1;
transform: translateY(0);
}
}

/* メインコンテンツの幅を広げます。最大1920pxまでを許可します。 */
#app .VPDoc.has-aside .content-container {
max-width: 1280px;
Expand Down
2 changes: 2 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ export default defineConfig([
ignoreUrls: [
// TODO なぜか Proxy環境で SocketError: other side closed となる。。。
"http://www.oracle.com/technetwork/java/codeconvtoc-136057.html",
// ログインなしではみられなくなった?
"https://github.com/future-architect/coding-standards/stargazers",
// サイトは削除されているがドキュメントとしては残すリンク
"https://www.acroquest.co.jp/webworkshop/javacordingrule/Acroquest_JavaCodingStandard_6_7.pdf",
"http://www.fedict.belgium.be/sites/default/files/downloads/Java_J2EE_conventions_and_guidelines_EN.pdf",
Expand Down