功能源地址: Vans定制功能页面,建议先查看并使用一下vans网站功能。
使用 Three.js+vue
实现
demo演示如下:
仿写Vans定制鞋子
思路讲解:
引入模型-->找到需要改变的模型面-->创建新的纹理赋给新材质-->将旧的材质替换掉
纹理大小绑定动态数据值-->用户调整数值-->将更新的值转换后赋值给纹理-->重新替换纹理+材质
代码贴在了下面
模型背后光晕效果在代码中有体现出来。CSS代码也贴出来了
源码展示:html部分
<div class="main">
<div class="modelConfig">
<div class="block">
<span class="demonstration">贴图大小</span>
<el-slider v-model="Texturesize"></el-slider>
</div>
<div class="block">
<span class="demonstration">贴图距离右边位置</span>
<el-slider v-model="left"></el-slider>
</div>
<div class="block">
<span class="demonstration">贴图距离下边位置</span>
<el-slider v-model="top"></el-slider>
</div>
</div>
<div id="container"></div>
</div>
源码展示:
JS部分
欢迎各位提意见交流
import * as THREE from "three";
import { GLTFLoader } from "@/common/GLTFLoader.js";
import { OrbitControls } from "@/common/OrbitControls.js";
export default {
data() {
return {
controls: null,
container: null,
scene: null,
renderer: null,
value: 1,
loader: null,
Texturesize: 1,
left: 50,
top: 50,
timer: null,
};
},
mounted() {
this.init();
},
watch: {
Texturesize() {
clearTimeout(this.timer);
this.timer = setTimeout(() => {
let three = document.querySelector("#container > canvas");
three.remove(1);
this.init();
}, 1000);
},
left() {
clearTimeout(this.timer);
this.timer = setTimeout(() => {
let three = document.querySelector("#container > canvas");
three.remove(1);
this.init();
}, 1000);
},
top() {
clearTimeout(this.timer);
this.timer = setTimeout(() => {
let three = document.querySelector("#container > canvas");
three.remove(1);
this.init();
}, 1000);
},
},
methods: {
init() {
this.container = document.querySelector("#container");
this.camera = new THREE.PerspectiveCamera(45, 1920 / 685, 0.1, 2000);
this.camera.position.set(0.5, 0.7, 6);
this.scene = new THREE.Scene();
var texture = new THREE.TextureLoader().load("texture/433.png");
texture.generateMipmaps = false;
texture.anisotropy = true;
texture.encoding = THREE.sRGBEncoding;
texture.flipY = false;
texture.matrix.set(0, 0, 0, 0, 0, 0, 0);
texture.needsUpdate = true;
texture.center.set(this.left / 100, this.top / 100);
texture.repeat.set(
0.01 /
(this.Texturesize === 1 ? this.Texturesize : this.Texturesize / 10),
0.009 /
(this.Texturesize === 1 ? this.Texturesize : this.Texturesize / 10)
);
var tmaterial = new THREE.MeshStandardMaterial({
map: texture,
polygonOffset: false,
});
new GLTFLoader().setPath("loader/").load("329.glb", (gltf) => {
console.log(gltf);
gltf.scene.children[0].children[8].children.forEach((item, index) => {
if (index == 21) {
item.material = tmaterial;
}
});
gltf.scene.traverse(function (child) {
if (child.isMesh) {
child.material.emissive = child.material.color;
child.material.emissiveMap = child.material.map;
}
});
this.scene.add(gltf.scene);
});
// 此处配置设置背景透明然后css3设置光晕
this.renderer = new THREE.WebGLRenderer({
alpha: true,
antialias: true,
precision: "highp",
});
this.renderer.setClearAlpha(0.0);
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.renderer.outputEncoding = THREE.sRGBEncoding;
this.container.appendChild(this.renderer.domElement);
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
this.controls.update();
// 右键拖拽
this.controls.enablePan = true;
this.controls.enableDamping = true;
window.addEventListener("resize", this.resize);
this.animate();
},
resize() {
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(window.innerWidth, window.innerHeight);
},
animate() {
this.controls.update();
this.renderer.render(this.scene, this.camera);
requestAnimationFrame(this.animate);
},
},
};
源码展示:
CSS代码
.modelConfig {
position: absolute;
left: 20px;
}
.demonstration {
color: #fff;
}
.block {
width: 300px;
}
/* 背景光晕 */
#container {
background: radial-gradient(
circle at 50%,
rgb(255, 255, 255),
rgba(214, 214, 214),
rgb(97, 97, 97)
);
}
想要GLB模型的同学可以私信博主(如果有学到干货请动动小手点点赞谢谢)