1- import { useCallback, useEffect, useRef } from 'react';
21import styled from 'styled-components';
3- import { Mesh, OrthographicCamera, PlaneGeometry, Scene, ShaderMaterial, TextureLoader, WebGLRenderer } from 'three';
42
53import { IMAGE_SRC } from './ImageSrc';
64
@@ -15,107 +13,9 @@ const _Image = styled.img`
1513`;
1614
1715export const HeroImage: React.FC = () => {
18- const imageRef = useRef<HTMLImageElement | null>(null);
19- const canvasRef = useRef<HTMLCanvasElement>(document.createElement('canvas'));
20-
21- const updateImage = useCallback(({ height, src, width }: { height: number; src: string; width: number }) => {
22- const image = imageRef.current;
23- if (image == null) {
24- return;
25- }
26- image.width = width;
27- image.height = height;
28- image.src = src;
29- }, []);
30-
31- useEffect(() => {
32- const image = imageRef.current;
33- if (image == null) {
34- return;
35- }
36-
37- // width が 4096 / dpr の 16:9 の画像として描画する。
38- const width = 4096 / window.devicePixelRatio;
39- const height = (width / 16) * 9;
40- const imageWidth = image.clientWidth;
41- const imageHeight = (imageWidth / 16) * 9;
42-
43- const scene = new Scene();
44- const camera = new OrthographicCamera(-1, 1, 1, -1, 1, 1000);
45- camera.position.set(0, 0, 100);
46- camera.lookAt(scene.position);
47-
48- const textureLoader = new TextureLoader();
49-
50- textureLoader.load(IMAGE_SRC, (texture) => {
51- const geometry = new PlaneGeometry(2, 2);
52- const material = new ShaderMaterial({
53- fragmentShader: `uniform sampler2D tImage;
54- varying vec2 vUv;
55- void main() {
56- float aspectRatio = float(textureSize(tImage, 0).x / textureSize(tImage, 0).y);
57- vec2 uv = vec2(
58- (vUv.x - 0.5) / min(aspectRatio, 1.0) + 0.5,
59- (vUv.y - 0.5) / min(1.0 / aspectRatio, 1.0) + 0.5
60- );
61- gl_FragColor = texture2D(tImage, vUv);
62- }`,
63- uniforms: {
64- tImage: { value: texture },
65- },
66- vertexShader: `varying vec2 vUv;
67- void main() {
68- vUv = uv;
69- gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
70- }`,
71- });
72- const mesh = new Mesh(geometry, material);
73- scene.add(mesh);
74-
75- const renderer = new WebGLRenderer({ alpha: true, antialias: true, canvas: canvasRef.current });
76- renderer.setPixelRatio(window.devicePixelRatio);
77- renderer.setSize(width, height);
78-
79- const animate = () => {
80- requestAnimationFrame(animate);
81- renderer.render(scene, camera);
82- };
83- animate();
84-
85- updateImage({
86- height: imageHeight,
87- src: canvasRef.current.toDataURL(),
88- width: imageWidth,
89- });
90- });
91- }, [imageRef, updateImage]);
92-
93- useEffect(() => {
94- const resize = () => {
95- const image = imageRef.current;
96- if (image == null) {
97- return;
98- }
99-
100- const width = image.clientWidth;
101- const height = (image.clientWidth / 16) * 9;
102- updateImage({
103- height,
104- src: canvasRef.current.toDataURL(),
105- width,
106- });
107- };
108-
109- window.addEventListener('resize', resize);
110-
111- return () => {
112- window.removeEventListener('resize', resize);
113- };
114- }, [updateImage]);
115-
11616 return (
11717 <_Wrapper>
118- <_Image ref={imageRef} alt="Cyber TOON" />
18+ <_Image alt="Cyber TOON" loading="eager" src={IMAGE_SRC} />
11919 </_Wrapper>
12020 );
12121};
0 commit comments