Hello, I’m a newer Tree.js, I have a very difficult problem that has taken a long time to solve. I need your help.
I want to put pictures of any size in a fixed size (100 * 150) area, but I don’t know how to do. The code I now implement is as follows:
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - KTX2 texture loader</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script>
<script type="importmap">
{
"imports": {
"three": "../build/three.module.js",
"three/addons/": "./jsm/",
"three-text2d": "../node_modules/three-text2d/tr"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
const width = window.innerWidth;
const height = window.innerHeight;
const renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( width, height );
renderer.outputEncoding = THREE.sRGBEncoding;
document.body.appendChild( renderer.domElement );
const scene = new THREE.Scene();
scene.background = new THREE.Color( 'rgba(59,130,246,0.5)' );
const camera = new THREE.PerspectiveCamera( 60, width / height, 0.1, 100 );
camera.position.set( 2, 1.5, 1 );
camera.lookAt( scene.position );
scene.add( camera );
const controls = new OrbitControls( camera, renderer.domElement );
controls.autoRotate = true;
animate();
try {
const width = 100;
const height = 150;
const imageLoader = new THREE.ImageLoader();
imageLoader.load( 'textures/images/3.png', image => {
const canvas = document.createElement( 'canvas' );
const context = canvas.getContext( '2d' );
const imgRect = coverImg( width, height, image.width, image.height );
context.drawImage( image, imgRect.sx, imgRect.sy, imgRect.sWidth, imgRect.sHeight, 0, 0, width, height );
const geometry = new THREE.PlaneGeometry( width, height );
const material = new THREE.MeshBasicMaterial( {} );
const mesh = new THREE.Mesh( geometry, material );
const texture = new THREE.CanvasTexture( canvas );
texture.encoding = THREE.sRGBEncoding;
material.map = texture;
material.needsUpdate = true;
material.transparent = true;
mesh.scale.set(1/width,1/height,1);
mesh.position.set( 0, 0, 0.01 );
scene.add( mesh );
} );
} catch (e) {
console.error( e );
}
function coverImg( box_w, box_h, source_w, source_h ) {
var sx = 0,
sy = 0,
sWidth = source_w,
sHeight = source_h;
if (source_w > source_h || ( source_w == source_h && box_w < box_h )) {
sWidth = box_w * sHeight / box_h;
sx = ( source_w - sWidth ) / 2;
} else if (source_w < source_h || ( source_w == source_h && box_w > box_h )) {
sHeight = box_h * sWidth / box_w;
sy = ( source_h - sHeight ) / 2;
}
return {
sx,
sy,
sWidth,
sHeight
};
}
function getSize( model ) {
const box = new THREE.Box3().setFromObject( model );
const size = box.getSize( new THREE.Vector3() );
console.log( 'size=', size );
}
function animate() {
requestAnimationFrame( animate );
controls.update();
renderer.render( scene, camera );
}
window.addEventListener( 'resize', onWindowResize );
function onWindowResize() {
const width = window.innerWidth;
const height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize( width, height );
}
</script>
</body>
</html>
They key code is here:
try {
const width = 100;
const height = 150;
const imageLoader = new THREE.ImageLoader();
imageLoader.load( 'textures/images/3.png', image => {
const canvas = document.createElement( 'canvas' );
const context = canvas.getContext( '2d' );
const imgRect = coverImg( width, height, image.width, image.height );
context.drawImage( image, imgRect.sx, imgRect.sy, imgRect.sWidth, imgRect.sHeight, 0, 0, width, height );
const geometry = new THREE.PlaneGeometry( width, height );
const material = new THREE.MeshBasicMaterial( {} );
const mesh = new THREE.Mesh( geometry, material );
const texture = new THREE.CanvasTexture( canvas );
texture.encoding = THREE.sRGBEncoding;
material.map = texture;
material.needsUpdate = true;
material.transparent = true;
mesh.scale.set(1/width,1/height,1);
mesh.position.set( 0, 0, 0.01 );
scene.add( mesh );
} );
} catch (e) {
console.error( e );
}
I feel that my code is too complicated and the direction is wrong. Thank you very much for your help.