Three.js——贴图在模型上移动

该代码示例展示了如何在three.js环境中,当用户按住Shift键并移动鼠标时,能在模型上自由拖动纹理的效果。通过监听键盘和鼠标事件,结合OrbitControls,动态调整材质的offset属性来实现这一交互功能。
摘要由CSDN通过智能技术生成

效果如下图所示:

 模型正常交互,当按下键盘上的shift键的时候,按住鼠标可以自由的在模型上拖动纹理

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <!-- 导入three.js -->
    <script src="/libs/build/three.js"></script>
    <script src="/libs/js/controls/OrbitControls.js"></script>
    <script src="/libs/js/controls/PointerLockControls.js"></script>
    <script src="/libs/js/loaders/GLTFLoader.js"></script>
    <script src="/libs/js/renderers/CSS2DRenderer.js"></script>
    <script src="/libs/js/loaders/FBXLoader.js"></script>
    <script src="/libs/js/loaders/OBJLoader.js"></script>
    <script src="/libs/js/loaders/MTLLoader.js"></script>
    <script src="/libs/js/libs/fflate.min.js"></script>
    <script src="/libs/js/loaders/DRACOLoader.js"></script>

</head>
<body>
    
    <div id="webgl-output"></div>
    <script src="./textrueMove.js"></script>
</body>
</html>

 


var scene;          //----场景
var camera;         //----摄像机
var renderer;       //----渲染器
var mouse = new THREE.Vector2();
function init() {

    //----------------------基础设置------------------------

    //页面宽高
	var innerWidth=window.innerWidth;   
	var innerHeight=window.innerHeight;

	// 创建场景
	scene = new THREE.Scene();
	// 设置摄像机
	camera = new THREE.PerspectiveCamera(45, innerWidth / innerHeight, 0.1, 2000)

	// 创建渲染器
	renderer = new THREE.WebGLRenderer({ logarithmicDepthBuffer: true });
	// 设置渲染器的初始颜色
	renderer.setClearColor(new THREE.Color(0xeeeeee));
	// 设置输出canvas画面的大小
	renderer.setSize(innerWidth, innerHeight)
	// 设置渲染物体阴影
	renderer.shadowMapEnabled = true;
    //设置为RGB颜色
	renderer.outputEncoding = THREE.sRGBEncoding;

	// 添加三维坐标系(红:x、绿:y、蓝:z)
	var axes = new THREE.AxisHelper(20)
	scene.add(axes);
    
    //添加环境光
	var ambientLight = new THREE.AmbientLight('#1f1f1f'); 
    scene.add(ambientLight);
    //添加平行光
	directionalLight = new THREE.DirectionalLight("#858585");
	directionalLight.position.set(500, 500, 500);
	directionalLight.shadow.camera.near = 20; //产生阴影的最近距离
	directionalLight.shadow.camera.far = 200; //产生阴影的最远距离
	directionalLight.shadow.camera.left = -50; //产生阴影距离位置的最左边位置
	directionalLight.shadow.camera.right = 50; //最右边
	directionalLight.shadow.camera.top = 50; //最上边
	directionalLight.shadow.camera.bottom = -50; //最下面
    //开启阴影投射
	directionalLight.castShadow = true;
	scene.add(directionalLight);

    // 设置相机位置和朝向
	camera.position.x = 300;
	camera.position.y = 300;
	camera.position.z = 0;

	let v = new THREE.Vector3(0, -200, 0);//向量
	camera.lookAt(v)

    //定义OrbitControls控制器,用于场景交互
	var controls = new THREE.OrbitControls( camera, renderer.domElement );
	//控制缩放范围
	controls.minDistance = 2;
	//相机距离观察目标点极大距离——模型最小状态
	controls.maxDistance = 500;
	// 上下旋转范围
	controls.minPolarAngle = -Math.PI/2;
	controls.maxPolarAngle = Math.PI/2;
    // controls.target = v;//可以设置控制器的交互中心,默认是原点

    // 将渲染器输出添加html元素中
	document.getElementById('webgl-output').appendChild(renderer.domElement);

    //------------------------加载模型和贴图-----------------------

    //创建一个纹理对象
    const texture = new THREE.TextureLoader().load('/model/image.png',function(){
        renderer.render(scene, camera); //材质导入后渲染一下,保证出来的初始画面有贴图
    });

    // 创建材料,并将贴图应用到其map属性上
    const material = new THREE.MeshBasicMaterial({
        map: texture,
    });
   
    //加载obj模型
    const loader = new THREE.OBJLoader();
    loader.load('/model/123.obj', function(object) {
        scene.add(object);
        //将材质应用到模型上
        object.traverse(function(child) {
            if (child instanceof THREE.Mesh) {
              child.material = material; 
            }
        });
        renderer.render(scene, camera)
    })
    renderer.render(scene, camera);
    //-----------------------交互控制&移动贴图-----------------------

    // 标记是否按下Shift键
    let isShiftKeyDown = false;

    //监听鼠标按下事件若按下鼠标的同时按下了shift键则禁用OrbitControls的交互
    document.addEventListener('mousedown', event => {
        //当监听的事件是鼠标事件的时候可以用event.shiftKey、event.ctrlKey,而event.key==''这个是监听键盘事件的时候才有用
        if (event.shiftKey) {
            isShiftKeyDown = true;
            controls.enablePan = false;//(用于控制OrbitControls控制器的平移缩放)
            controls.enableZoom = false;
        }
    });

    //监听鼠标松开事件
    //若前面按下了shift键,状态复原(鼠标按下时会再设置)
    document.addEventListener('mouseup', () => {
        if (isShiftKeyDown) {
            isShiftKeyDown = false;
            controls.enablePan = true;
            controls.enableZoom = true;
        }
    });

    //若按下了shift键移动,则改变material.map.offset属性
    document.addEventListener('mousemove', event => {
    if (isShiftKeyDown) {
        
        const { width, height } = texture.image;
        const scaleX = 1 / width;
        const scaleY = 1 / height;

        material.map.offset.x -= event.movementX * scaleX;
        material.map.offset.y += event.movementY * scaleY;
        renderer.render(scene, camera)

    }
    });

    controls.addEventListener('change', () => {
        renderer.render(scene, camera)
    });

}
	
window.onload = init

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值