当前位置: 首页 > 工具软件 > fragment.js > 使用案例 >

Three.js 拓扑图

孟振
2023-12-01

概述

这篇文章主要介绍一下如何使用three.js 制作拓扑图

three.js拓扑图

合并切图绘制

// 合并两张图片 img1、img2,其中图片占比 a:b(需要两张图片同高)
export function mergeImage(imgSrc1, imgSrc2, a, b) {
  return new Promise((res) => {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    const img1 = new Image();
    img1.src = imgSrc1;
    img1.onload = function () {
      const img2 = new Image();
      img2.src = imgSrc2;
      img2.onload = function () {
        canvas.width = img1.width * a + img2.width * b;
        canvas.height = img1.height;
        ctx.rect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = '#fff';
        ctx.fill();

        let width = 0;
        // 绘制img1
        for (let i = 0; i < a; i++) {
          ctx.drawImage(img1, width, 0, img1.width, img1.height);
          width += img1.width;
        }

        // 绘制img2
        for (let i = 0; i < b; i++) {
          ctx.drawImage(img2, width, 0, img2.width, img2.height);
          width += img2.width;
        }

        // 合并
        const base64 = canvas.toDataURL('image/png');
        res(base64);
      };
    };
  });
}
import * as THREE from 'three';

// 高亮材质
export const activeModelMaterial = new THREE.MeshPhongMaterial({
  color: '#66b1ff',
  transparent: true,
  opacity: 0.8
});

const vertexShader = [
  'varying vec2 vUv;',
  'void main()',
  '{',
  ' vUv = uv;',
  ' vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );',
  ' gl_Position = projectionMatrix * mvPosition;',
  '}'
].join('');

const fragmentShader = [
  'uniform float r;',
  'uniform float g;',
  'uniform float b;',
  'uniform float a;',
  'uniform float distanceZ;',
  'uniform float distanceX;',
  'uniform float pulse;',
  'uniform float speed;',
  'varying vec2 vUv;',
  'void main( void ) {',
  ' vec2 position = abs(-1.0 + 2.0 * vUv);',
  ' float edging = abs((pow(position.y, 5.0) + pow(position.x, 5.0)) / 2.0);',
  ' float perc = (0.2 * pow(speed + 1.0, 2.0) + edging * 0.8) * distanceZ * distanceX;',
  ' float red = r * perc + pulse;',
  ' float green = g * perc + pulse;',
  ' float blue = b * perc + pulse;',
  ' gl_FragColor = vec4(red, green, blue, a);',
  '}'
].join('');

export const baseUniforms = {
  r: { type: 'f', value: 0.1 },
  g: { type: 'f', value: 0.1 },
  b: { type: 'f', value: 0.8 },
  a: { type: 'f', value: 1.0 },
  distanceX: { type: 'f', value: 1 },
  distanceZ: { type: 'f', value: 1 },
  pulse: { type: 'f', value: 0.1 },
  speed: { type: 'f', value: 0.5 }
};

export const waringUniforms = {
  r: { type: 'f', value: 0.9 },
  g: { type: 'f', value: 0.1 },
  b: { type: 'f', value: 0.1 },
  a: { type: 'f', value: 1.0 },
  distanceX: { type: 'f', value: 1 },
  distanceZ: { type: 'f', value: 1 },
  pulse: { type: 'f', value: 0.1 },
  speed: { type: 'f', value: 0.5 }
};

export const boxBaseMaterial = new THREE.ShaderMaterial({
  uniforms: baseUniforms,
  vertexShader: vertexShader,
  fragmentShader: fragmentShader,
  transparent: true,
  opacity: 1
});

export const boxWaringMaterial = new THREE.ShaderMaterial({
  uniforms: waringUniforms,
  vertexShader: vertexShader,
  fragmentShader: fragmentShader,
  transparent: true,
  opacity: 1
});

export function createLineMaterial(number, color) {
  const shader = {
    vs: `
        varying vec2 v_uv;
        varying float v_z;
        void main() {
            v_z = position.z;
            gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position, 1.0 );
        }
    `,
    fs: `
       uniform float number;
       uniform vec3 color;
       varying float v_z;
       void main() {
          if(v_z < number) {
            gl_FragColor = vec4(color, 1.0);
          }else{
            gl_FragColor = vec4(1.0, 1.0, 1.0, 0.0);
          }
       }
    `,
    uniform: {
      number: {
        value: number
      },
      color: {
        value: new THREE.Color(color)
      }
    }
  };

  return new THREE.ShaderMaterial({
    vertexShader: shader.vs,
    fragmentShader: shader.fs,
    uniforms: shader.uniform,
    transparent: true
  });
}

 类似资料: