threejs-day1(响应式设计/图元)

响应式设计

1.使用css使canvas填充页面


  1. 调整画布大小
function resizeRendererToDisplaySize(renderer) {
  const canvas = renderer.domElement;
  const width = canvas.clientWidth;
  const height = canvas.clientHeight;
  const needResize = canvas.width !== width || canvas.height !== height;
  if (needResize) {
    renderer.setSize(width, height, false);
  }
  return needResize;
}
  • 如果尺寸没变最好不要设置相同大小。
  • render.setSize第三个参数传入false,可以看下面的代码,内部默认会设置canvas的css属性。
if ( updateStyle !== false ) {
    _canvas.style.width = width + 'px';
    _canvas.style.height = height + 'px';
}
  1. HD-DPI显示器
renderer.setPixelRatio(window.devicePixelRatio);

解决方法1调用setPixelRatio设置设备像素比。通常用于避免HiDPI设备上绘图模糊。

function resizeRendererToDisplaySize(renderer) {
      const canvas = renderer.domElement;
      const pixelRatio = window.devicePixelRatio;
      const width = canvas.clientWidth * pixelRatio | 0;
      const height = canvas.clientHeight * pixelRatio | 0;
      const needResize = canvas.width !== width || canvas.height !== height;
      if (needResize) {
        renderer.setSize(width, height, false);
      }
      return needResize;
    }

解决方法2自己处理。
第二种方式更好,因为可以知道绘图缓冲区的确切尺寸。

图元

  1. GeometryBufferGeometry对比
    基于BufferGeometry的图元是面向性能的类型。几何体的顶点是直接生成为一个高效的类型数组形式,可以被上传到GPU进行渲染。意味着更快的启动,占用更少的内存。但如果想修改数据就需要复杂的编程。
    基于 Geometry 的图元更灵活、更易修改。 它们根据 JavaScript 的类而来。它们需要更多的内存,在被渲染前,Three.js 会将它们转换成相应的 BufferGeometry
QQ截图20210430005439.png
import * as THREE from "../three";

const canvas = document.querySelector("#canvas");
const renderer = new THREE.WebGLRenderer({ canvas });

const scene = new THREE.Scene();
scene.background = new THREE.Color(0xaaaaaa);

const fov = 40;
const aspect = 2;
const near = 0.1;
const far = 1000;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.z = 120;

{
  const color = 0xffffff;
  const intensity = 1;
  const light = new THREE.DirectionalLight(color, intensity);
  light.position.set(-1, 2, 4);
  scene.add(light);
}

{
  const color = 0xffffff;
  const intensity = 1;
  const light = new THREE.DirectionalLight(color, intensity);
  light.position.set(1, -2, -4);
  scene.add(light);
}

const objects = [];
const spread = 15;

function addObject(x, y, obj) {
  obj.position.x = x * spread;
  obj.position.y = y * spread;
  scene.add(obj);
  objects.push(obj);
}

function createMaterial() {
  const material = new THREE.MeshPhongMaterial({
    side: THREE.DoubleSide,
  });

  // 0-1 红色0 绿色.33 蓝色.66
  const hue = Math.random();
  // 0-1 没有颜色0 饱和度最高1
  const saturation = 1;
  // 0-1 黑色0 白色1 最大数量颜色0.5
  // luminance 从0到0.5 表示颜色从黑到hue,从0.5到1.0表示颜色从hue到白。
  const luminance = 0.5;
  material.color.setHSL(hue, saturation, luminance);
  return material;
}

function addSolidGeometry(x, y, geometry) {
  const mesh = new THREE.Mesh(geometry, createMaterial());
  addObject(x, y, mesh);
}

function addLineGeometry(x, y, geometry) {
  const material = new THREE.LineBasicMaterial({ color: 0x000000 });
  const mesh = new THREE.LineSegments(geometry, material);
  addObject(x, y, mesh);
}

{
  const width = 8;
  const height = 8;
  const depth = 8;
  addSolidGeometry(-2, 2, new THREE.BoxGeometry(width, height, depth));
}

{
  const radius = 7;
  const segments = 24;
  addSolidGeometry(-1, 2, new THREE.CircleGeometry(radius, segments));
}

{
  const radius = 6;
  const height = 8;
  const segments = 16;
  addSolidGeometry(0, 2, new THREE.ConeGeometry(radius, height, segments));
}

{
  const radiusTop = 4;
  const radiusBottom = 4;
  const height = 8;
  const radialSegments = 12;
  addSolidGeometry(
    1,
    2,
    new THREE.CylinderGeometry(radiusTop, radiusBottom, height, radialSegments)
  );
}

{
  const radius = 7;
  addSolidGeometry(2, 2, new THREE.DodecahedronGeometry(radius));
}

{
  const shape = new THREE.Shape();
  const x = -2.5;
  const y = -5;
  shape.moveTo(x + 2.5, y + 2.5);
  shape.bezierCurveTo(x + 2.5, y + 2.5, x + 2, y, x, y);
  shape.bezierCurveTo(x - 3, y, x - 3, y + 3.5, x - 3, y + 3.5);
  shape.bezierCurveTo(x - 3, y + 5.5, x - 1.5, y + 7.7, x + 2.5, y + 9.5);
  shape.bezierCurveTo(x + 6, y + 7.7, x + 8, y + 4.5, x + 8, y + 3.5);
  shape.bezierCurveTo(x + 8, y + 3.5, x + 8, y, x + 5, y);
  shape.bezierCurveTo(x + 3.5, y, x + 2.5, y + 2.5, x + 2.5, y + 2.5);

  const extrudeSettings = {
    steps: 2,
    depth: 2,
    bevelEnabled: true,
    bevelThickness: 1,
    bevelSize: 1,
    bevelSegments: 2,
  };

  addSolidGeometry(-2, 1, new THREE.ExtrudeGeometry(shape, extrudeSettings));
}

{
  const radius = 7;
  addSolidGeometry(-1, 1, new THREE.IcosahedronGeometry(radius));
}

{
  const points = [];
  for (let i = 0; i < 10; ++i) {
    points.push(new THREE.Vector2(Math.sin(i * 0.2) * 3 + 3, (i - 5) * 0.8));
  }
  addSolidGeometry(0, 1, new THREE.LatheGeometry(points));
}

{
  const radius = 7;
  addSolidGeometry(1, 1, new THREE.OctahedronGeometry(radius));
}

{
  function klein(v, u, target) {
    u *= Math.PI;
    v *= 2 * Math.PI;
    u = u * 2;

    let x;
    let z;

    if (u < Math.PI) {
      x =
        3 * Math.cos(u) * (1 + Math.sin(u)) +
        2 * (1 - Math.cos(u) / 2) * Math.cos(u) * Math.cos(v);
      z =
        -8 * Math.sin(u) -
        2 * (1 - Math.cos(u) / 2) * Math.sin(u) * Math.cos(v);
    } else {
      x =
        3 * Math.cos(u) * (1 + Math.sin(u)) +
        2 * (1 - Math.cos(u) / 2) * Math.cos(v + Math.PI);
      z = -8 * Math.sin(u);
    }

    const y = -2 * (1 - Math.cos(u) / 2) * Math.sin(v);

    target.set(x, y, z).multiplyScalar(0.75);
  }

  const slices = 25;
  const stacks = 25;
  addSolidGeometry(2, 1, new THREE.ParametricGeometry(klein, slices, stacks));
}

{
  const width = 9;
  const height = 9;
  const widthSegments = 2;
  const heightSegments = 2;
  addSolidGeometry(
    -2,
    0,
    new THREE.PlaneGeometry(width, height, widthSegments, heightSegments)
  );
}

{
  const verticesOfCube = [
    -1,
    -1,
    -1,
    1,
    -1,
    -1,
    1,
    1,
    -1,
    -1,
    1,
    -1,
    -1,
    -1,
    1,
    1,
    -1,
    1,
    1,
    1,
    1,
    -1,
    1,
    1,
  ];
  const indicesOfFaces = [
    2,
    1,
    0,
    0,
    3,
    2,
    0,
    4,
    7,
    7,
    3,
    0,
    0,
    1,
    5,
    5,
    4,
    0,
    1,
    2,
    6,
    6,
    5,
    1,
    2,
    3,
    7,
    7,
    6,
    2,
    4,
    5,
    6,
    6,
    7,
    4,
  ];
  const radius = 7;
  const detail = 2;
  addSolidGeometry(
    -1,
    0,
    new THREE.PolyhedronGeometry(verticesOfCube, indicesOfFaces, radius, detail)
  );
}

{
  const innerRadius = 2;
  const outerRadius = 7;
  const segments = 18;
  addSolidGeometry(
    0,
    0,
    new THREE.RingGeometry(innerRadius, outerRadius, segments)
  );
}

{
  const shape = new THREE.Shape();
  const x = -2.5;
  const y = -5;
  shape.moveTo(x + 2.5, y + 2.5);
  shape.bezierCurveTo(x + 2.5, y + 2.5, x + 2, y, x, y);
  shape.bezierCurveTo(x - 3, y, x - 3, y + 3.5, x - 3, y + 3.5);
  shape.bezierCurveTo(x - 3, y + 5.5, x - 1.5, y + 7.7, x + 2.5, y + 9.5);
  shape.bezierCurveTo(x + 6, y + 7.7, x + 8, y + 4.5, x + 8, y + 3.5);
  shape.bezierCurveTo(x + 8, y + 3.5, x + 8, y, x + 5, y);
  shape.bezierCurveTo(x + 3.5, y, x + 2.5, y + 2.5, x + 2.5, y + 2.5);
  addSolidGeometry(1, 0, new THREE.ShapeGeometry(shape));
}

{
  const radius = 7;
  const widthSegments = 12;
  const heightSegments = 8;
  addSolidGeometry(
    2,
    0,
    new THREE.SphereGeometry(radius, widthSegments, heightSegments)
  );
}

{
  const radius = 7;
  addSolidGeometry(-2, -1, new THREE.TetrahedronGeometry(radius));
}

{
  const radius = 5;
  const tubeRadius = 2;
  const radialSegments = 8;
  const tubularSegments = 24;
  addSolidGeometry(
    0,
    -1,
    new THREE.TorusGeometry(radius, tubeRadius, radialSegments, tubularSegments)
  );
}

{
  const radius = 3.5;
  const tube = 1.5;
  const radialSegments = 8;
  const tubularSegments = 64;
  const p = 2;
  const q = 3;
  addSolidGeometry(
    1,
    -1,
    new THREE.TorusKnotGeometry(
      radius,
      tube,
      tubularSegments,
      radialSegments,
      p,
      q
    )
  );
}

{
  class CustomSinCurve extends THREE.Curve {
    constructor(scale) {
      super();
      this.scale = scale;
    }
    getPoint(t) {
      const tx = t * 3 - 1.5;
      const ty = Math.sin(2 * Math.PI * t);
      const tz = 0;
      return new THREE.Vector3(tx, ty, tz).multiplyScalar(this.scale);
    }
  }

  const path = new CustomSinCurve(4);
  const tubularSegments = 20;
  const radius = 1;
  const radialSegments = 8;
  const closed = false;
  addSolidGeometry(
    2,
    -1,
    new THREE.TubeGeometry(
      path,
      tubularSegments,
      radius,
      radialSegments,
      closed
    )
  );
}

{
  const width = 8;
  const height = 8;
  const depth = 8;
  const thresholdAngle = 15;
  addLineGeometry(
    -1,
    -2,
    new THREE.EdgesGeometry(
      new THREE.BoxGeometry(width, height, depth),
      thresholdAngle
    )
  );
}

{
  const width = 8;
  const height = 8;
  const depth = 8;
  addLineGeometry(
    1,
    -2,
    new THREE.WireframeGeometry(new THREE.BoxGeometry(width, height, depth))
  );
}

{
  const radius = 7;
  const widthSegments = 12;
  const heightSegments = 8;
  const geometry = new THREE.SphereGeometry(
    radius,
    widthSegments,
    heightSegments
  );
  const material = new THREE.PointsMaterial({
    color: "red",
    size: 0.2, // in world units
  });
  const points = new THREE.Points(geometry, material);
  scene.add(points);
  points.position.set(-15, -15, 0);
  objects.push(points);
}

function resizeRendererToDisplaySize(renderer) {
  const canvas = renderer.domElement;
  const width = canvas.clientWidth;
  const height = canvas.clientHeight;
  const needResize = canvas.width !== width || canvas.height !== height;
  if (needResize) {
    renderer.setSize(width, height, false);
  }
  return needResize;
}

function render(time) {
  time *= 0.001;
  if (resizeRendererToDisplaySize(renderer)) {
    const canvas = renderer.domElement;
    camera.aspect = canvas.clientWidth / canvas.clientHeight;
    camera.updateProjectionMatrix();
  }
  objects.forEach((obj, index) => {
    const speed = 0.1 + index * 0.05;
    const rot = time * speed;
    obj.rotation.x = rot;
    obj.rotation.y = rot;
  });

  renderer.render(scene, camera);
  requestAnimationFrame(render);
}

requestAnimationFrame(render);

你可能感兴趣的:(threejs-day1(响应式设计/图元))