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

响应式设计

1.使用css使canvas填充页面

<style>
html, body {
   margin: 0;  //body默认有5个像素的margin值
   height: 100%; //高度充满窗口
}
#canvas {
   width: 100%;
   height: 100%;
   display: block; //默认为inline,行内元素末尾有空格,通过块级消除空格
}
</style>
  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);

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容