motionsites中文站 / Country Towers
Country Towers
aadmin2026-09-16 发布3D9 阅读

Country Towers

类型:3D · 分类:Three.js · 收录:2026-09-16 21:09:01 · 源码:会员可见

付费可阅读内容 · 可复制
# Country Towers
Six country-specific towers assembling above a procedural landscape: Japanese, Chinese, Vietnamese, Thai, Khmer, and Ottoman.

> 来源:ThreeUI Community · https://threeui.com · MIT License(Meng To / Design+Code)
> 组件页:https://threeui.com/component/japanese-tower · 预览动画:https://threeui.com/previews/japanese-tower.webm
> 分类:Three.js
> 包含变体(6):japan、china、vietnam、thailand、cambodia、turkey

/* ===== src/shaders/japanese-tower/JapaneseTowerLandscape.tsx (tsx) ===== */
import { useEffect, useMemo, useState } from "react";

export const TOWER_COUNTRIES = ["japan", "china", "vietnam", "thailand", "cambodia", "turkey"] as const;
export type TowerCountry = (typeof TOWER_COUNTRIES)[number];

const COUNTRY_LABELS: Record<TowerCountry, string> = {
  japan: "Japanese tenshu",
  china: "Chinese pagoda",
  vietnam: "Vietnamese tháp",
  thailand: "Thai prang",
  cambodia: "Khmer prasat",
  turkey: "Ottoman mosque",
};

export type JapaneseTowerLandscapeProps = {
  className?: string;
  sourceUrl?: string;
  country?: TowerCountry;
};

export function JapaneseTowerLandscape({
  className = "",
  sourceUrl = "/japanese-tower.html",
  country = "japan",
}: JapaneseTowerLandscapeProps) {
  const [ready, setReady] = useState(false);
  const frameSource = useMemo(() => {
    const hashIndex = sourceUrl.indexOf("#");
    const base = hashIndex >= 0 ? sourceUrl.slice(0, hashIndex) : sourceUrl;
    const hash = hashIndex >= 0 ? sourceUrl.slice(hashIndex) : "";
    return `${base}${base.includes("?") ? "&" : "?"}country=${country}${hash}`;
  }, [country, sourceUrl]);

  useEffect(() => setReady(false), [frameSource]);

  return (
    <div
      className={`japanese-tower-landscape${className ? ` ${className}` : ""}`}
      data-state={ready ? "ready" : "loading"}
    >
      <iframe
        key={country}
        className={`japanese-tower-landscape__frame${ready ? " is-ready" : ""}`}
        title={`${COUNTRY_LABELS[country]} in a procedural landscape`}
        src={frameSource}
        sandbox="allow-scripts"
        loading="eager"
        onLoad={() => setReady(true)}
      />
    </div>
  );
}
[/hidecontent]
← 返回首页