赞
踩
webGL.js封装的代码。
- const THREE = window.THREE;
- // webGL对象配置
- export const webglOBJ = {
- renderDom: null,
- Scene: null, // 场景
- camera: null, // 摄像头
- renderer: null, // 渲染器
- senceAdd (objList = []) {
- objList.forEach(v => {
- webglOBJ.Scene.add(v);
- });
- },
- // 创建场景
- createSence (renderDom) {
- this.renderDom = renderDom;
- webglOBJ.Scene = new THREE.Scene();
- return webglOBJ.Scene;
- },
- // 创建摄像机
- createCamera ({innerWidth, innerHeight, position} = {}) {
- const { width, height } = this.renderDom.getBoundingClientRect();
- let camera = new THREE.PerspectiveCamera(45, 1, 0.1, 1000);
- camera.position.x = -50;
- camera.position.y = 30;
- camera.position.z = 50;
- camera.lookAt(webglOBJ.Scene.position); // 视角
- webglOBJ.camera = camera; // 视角
- return webglOBJ.camera;
- },
- createRenderer () {
- let renderer = new THREE.WebGLRenderer();
- const {width, height} = this.renderDom.getBoundingClientRect();
- renderer.setSize(width, height);
- renderer.setClearColor(new THREE.Color(0xcccccc));
- renderer.shadowMap.enabled = true;
- this.renderDom.appendChild(renderer.domElement);
- webglOBJ.renderer = renderer;
- return webglOBJ.renderer;
- },
- createPlane (textureLoaderUrl, textureNormalUrl) {
- let planeGeometry = new THREE.PlaneGeometry(60, 60, 1, 1); // 平面网格
- let textureLoader = new THREE.TextureLoader();
- let texture = textureLoader.load(textureLoaderUrl);
- let textureNormal = textureLoader.load(textureNormalUrl);
- // 加载高光贴图
- let planeMaterial = new THREE.MeshPhongMaterial({
- // specular: 0xff0000,//高光部分的颜色
- shininess: 30, //高光部分的亮度,默认30
- map: texture, // 普通纹理贴图
- roughness: 0.3,
- lightMap: textureNormal,
- // normalMap: textureNormal, //法线贴图
- bumpScale: 3
- }); // 材质对象Material
- // let planeMaterial = new THREE.MeshLambertMaterial({color: 0xcccccc});
- let plane = new THREE.Mesh(planeGeometry, planeMaterial);
- plane.rotation.x = -0.5 * Math.PI;
- plane.position.x = 0;
- plane.name = '平面物体ID=' + 1;
- plane.position.y = 0;
- plane.position.z = 0;
- plane.receiveShadow = true;
- return plane;
- },
- createBoxGeometry (textureLoaderUrl, {x, y, z}) {
- // 创建立方体
- let textureLoader = new THREE.TextureLoader();
- let textureNormal = textureLoader.load(textureLoaderUrl);
- let boxGeometry = new THREE.BoxGeometry(10, 10, 10, 200);
- let texture1 = textureLoader.load(textureLoaderUrl);
- let boxGeometryMaterial = new THREE.MeshLambertMaterial({
- // specular: 0xff0000,//高光部分的颜色
- shininess: 10, //高光部分的亮度,默认30
- normalScale: new THREE.Vector2(2.2, 2.2),
- map: texture1, // 普通纹理贴图
- normalMap: textureNormal, //法线贴图
- bumpMap: textureNormal,
- bumpScale: 0.3
- });
- let box = new THREE.Mesh(boxGeometry, boxGeometryMaterial);
- box.name = '正方物体ID=' + 2;
- box.position.x = x;
- box.position.y = y;
- box.position.z = z;
- box.castShadow = true;
- return box;
- },
- // 点光源
- createSpotLight () {
- // 点光源
- let spotLight = new THREE.SpotLight(0xffffff);
- spotLight.position.set(-60, 40, -20);
- spotLight.castShadow = true;
- return spotLight;
- },
- // 平行光
- createDirectionalLight (target) {
- // 平行光
- let directionalLight = new THREE.DirectionalLight(0xffffff, 1);
- // 设置光源的方向:通过光源position属性和目标指向对象的position属性计算
- directionalLight.position.set(-90, 80, -20);
- // 方向光指向对象网格模型mesh2,可以不设置,默认的位置是0,0,0
- // directionalLight.target = target;
- return directionalLight;
- },
- // 环境光
- createAmbient (color = 0x444444) {
- let ambient = new THREE.AmbientLight(color);
- // ambient.castShadow = true;
- return ambient;
- },
- createDatGui () {
- let gui = {
- bump: 0.03,
- animation: false,
- };
- let datGui = new dat.GUI();
- //将设置属性添加到gui当中,gui.add(对象,属性,最小值,最大值)
- datGui.add(gui, "bump", -1, 1).onChange(function (e) {
- box.material.bumpScale = e;
- });
- datGui.add(gui, "animation");
- return datGui;
- },
- // 创建控制轴
- createControls () {
- let controls = new THREE.OrbitControls(webglOBJ.camera, webglOBJ.renderDom);
- return controls;
- },
- // 创建帮助
- createAxisHelper () {
- let axisHelper = new THREE.AxisHelper(250);
- return axisHelper;
- },
- // 初始化webGL对象
- webglRender (Scene, camera) {
- webglOBJ.renderer.render(Scene, camera);
- window.requestAnimationFrame(webglOBJ.webglRender);
- }
- };
-
- /**
- * 添加标签:dom方式
- * @param {*} targePosition :需要传递当前标签的位置
- * @param {*} targetId :标签对应的dom的唯一ID,暂且用时间戳代替,避免重复
- * @param {*} innerHTML :标签对应html
- */
- export function labelTag (camera, targePosition, targetId, innerHTML, webGLdom) {
- const { width, height } = webGLdom.getBoundingClientRect();
- let worldVector = new THREE.Vector3(targePosition.x, targePosition.y, targePosition.z);
- let vector = worldVector.project(camera);
- let halfWidth = width / 2,
- halfHeight = height / 2;
- let x = Math.round(vector.x * halfWidth + halfWidth);
- let y = Math.round(-vector.y * halfHeight + halfHeight);
- /**
- * 更新立方体元素位置
- */
- let div = document.getElementById(targetId);
- div.style.left = x + 'px';
- div.style.top = y + 'px';
- // div.innerHTML = `uuid:${innerHTML.uuid}`;
- }
vue中引用:
- <template>
- <div>
- <div class="three-box_wrapper"></div>
- <div :id="`sign${idx + 1}`" style="position: absolute;" v-for="(v, idx) in labels" :key="idx">
- <div class="sign" :uuid="v.uuid">
- <div class="name">我是标签1</div>
- <div class="data">数据: {{v.uuid}}</div>
- </div>
- </div>
- </div>
- </template>
-
- <script>
- import {webglOBJ, labelTag} from '@/utils/webGL/webGL.js';
- export default {
- name: 'threeBox',
- data () {
- return {
- labels: []
- };
- },
- mounted () {
- this.int();
- },
- methods: {
- createLabel () {
-
- },
- int () {
- const imgBG = require('./img.jpg');
- const webGLdom = document.querySelector('.three-box_wrapper');
- const sence = webglOBJ.createSence(webGLdom);
- const camera = webglOBJ.createCamera();
- const renderer = webglOBJ.createRenderer();
- const plane = webglOBJ.createPlane(imgBG, imgBG);
- const boxGeometry = webglOBJ.createBoxGeometry(imgBG, {x: 10, y: 5, z: 10});
- const boxGeometry1 = webglOBJ.createBoxGeometry(imgBG, {x: -10, y: 5, z: 10});
- const spotLight = webglOBJ.createSpotLight();
- const directionalLight = webglOBJ.createDirectionalLight(boxGeometry);
- const ambient = webglOBJ.createAmbient();
- const datGui = webglOBJ.createDatGui();
- const controls = webglOBJ.createControls();
- const axisHelper = webglOBJ.createAxisHelper();
- // 将对象添加到场景中去
- webglOBJ.senceAdd([plane, boxGeometry, boxGeometry1, spotLight, directionalLight, ambient, datGui, controls, axisHelper]);
- // webglOBJ.webglRender(sence, camera, renderer);
- console.log(sence, 'sence');
- const vm = this;
- function render(html) {
- vm.labels = sence.children.filter(v => v.type == 'Mesh');
- vm.$nextTick(() => {
- sence.children.forEach((val, idx) => {
- if (val.type == 'Mesh') {
- const {x, y, z} = val.position;
- labelTag(camera, {x, y, z}, `sign${idx + 1}`, val, webGLdom);
- }
- });
- });
-
- renderer.render(sence, camera);
- requestAnimationFrame(render);
- };
- render();
-
- // 监听点击事件查看点击的元素
- let raycaster = new THREE.Raycaster();
- let mouse = new THREE.Vector2();
- // 点击了哪个模型
- function clickEvent() {
- if (event.target.tagName == 'CANVAS') {
- mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
- mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
- sence.updateMatrixWorld(true);
- // 通过鼠标点的位置和当前相机的矩阵计算出raycaster
- raycaster.setFromCamera(mouse, camera);
- // 获取raycaster直线和所有模型相交的数组集合
- let intersects = raycaster.intersectObjects(sence.children, true);
- if (intersects[0]) {
- console.log(intersects[0]);
- }
- }
- }
- window.addEventListener('click', clickEvent, false);
- }
- }
- };
- </script>
-
- <style lang="scss" scoped>
- .three-box_wrapper {
- position: relative;
- width: 100%;
- height: 800px;
- border: 1px solid #ccc;
- }
- div[id *= "sign"] {
- width: 250px;
- height: 100px;
- background: rgba(0, 0, 0, .65);
- .sign{
- div {
- color: #fff;
- text-align: left;
- padding: 0 5px;
- }
- }
- }
- </style>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。