16-案例练习(云雷纹)

43 阅读3分钟

云雷纹案例

  • 如下图 image.png

  • main.js

import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import "./style.css";
import mesh from "./ylw.js";

const scene = new THREE.Scene();

scene.add(mesh);

const light = new THREE.DirectionalLight(0xffffff);
light.position.set(500, 300, 600);
scene.add(light);

const light2 = new THREE.AmbientLight();
scene.add(light2);

const axesHelper = new THREE.AxesHelper(1000);
scene.add(axesHelper);

const width = window.innerWidth;
const height = window.innerHeight;

const camera = new THREE.PerspectiveCamera(60, width / height, 1, 10000);
camera.position.set(0, 200, 600);
camera.lookAt(0, 0, 0);

const renderer = new THREE.WebGLRenderer({
  antialias: true,
});
renderer.setSize(width, height);

console.log(mesh);
function render() {
  renderer.render(scene, camera);
  requestAnimationFrame(render);
}

render();

document.body.append(renderer.domElement);

const controls = new OrbitControls(camera, renderer.domElement);

第一步画圈

image.png

  • lyw.js
import * as THREE from "three";

// 用来画粗线
import { Line2 } from "three/examples/jsm/lines/Line2";
import { LineGeometry } from "three/examples/jsm/lines/LineGeometry.js";
import { LineMaterial } from "three/examples/jsm/lines/LineMaterial";

const group = new THREE.Group();

const arc1 = new THREE.EllipseCurve(0, 0, 110, 110, 0, Math.PI * 2);
const pointsArr1 = arc1.getPoints(50);

const geometry1 = new LineGeometry();
geometry1.setFromPoints(pointsArr1);
const material1 = new LineMaterial({
  color: new THREE.Color("white"),
  linewidth: 4,
});
const line1 = new Line2(geometry1, material1);
group.add(line1);

const arc2 = new THREE.EllipseCurve(0, 0, 120, 120, 0, Math.PI * 2);
const pointsArr2 = arc2.getPoints(50);
const geometry2 = new THREE.BufferGeometry();
geometry2.setFromPoints(pointsArr2);
const material2 = new THREE.LineBasicMaterial({
  color: new THREE.Color("white"),
});
const line2 = new THREE.Line(geometry2, material2);
group.add(line2);

// 创建一个 group,里面单独画一些圆
const circleGroup = new THREE.Group();
for (let angle = 0; angle < Math.PI * 2; angle += Math.PI / 12) {
  const R = 130;
  const x = R * Math.cos(angle);
  const y = R * Math.sin(angle);
  const arc = new THREE.EllipseCurve(x, y, 10, 10, 0, Math.PI * 2);
  const pointsArr = arc.getPoints(50);
  const geometry = new THREE.BufferGeometry();
  geometry.setFromPoints(pointsArr);
  const material = new THREE.LineBasicMaterial({
    color: new THREE.Color("white"),
  });
  const line = new THREE.Line(geometry, material);
  circleGroup.add(line);
}
group.add(circleGroup);

// 再画一个圈包裹一下
const arc3 = new THREE.EllipseCurve(0, 0, 142.5, 142.5, 0, Math.PI * 2);
const pointsArr3 = arc3.getPoints(50);
const geometry3 = new LineGeometry();
geometry3.setFromPoints(pointsArr3);
const material3 = new LineMaterial({
  color: new THREE.Color("white"),
  linewidth: 5,
});
const line3 = new Line2(geometry3, material3);
group.add(line3);

export default group;
  • 如下图: image.png

第二步画中间的小圈圈并循环构建出来并添加到group中

image.png

  • 计算x轴离原点的距离
    • 第二个圆: 120
    • 第三个圆: 142.5 并且线的LineWidth为5
    • 计算的位置就是 142.5 - 5 / 2 - 120 => 130
// 角度从 0 到 2π,每个角度的位置用 R * Math.cos(angle) 和 R * Math.sin(angle) 确定圆心位置。
// 创建一个 group,里面单独画一些圆
const circleGroup = new THREE.Group();
for (let angle = 0; angle < Math.PI * 2; angle += Math.PI / 12) {
  const R = 130;
  const x = R * Math.cos(angle);
  const y = R * Math.sin(angle);
  const arc = new THREE.EllipseCurve(x, y, 10, 10, 0, Math.PI * 2);
  const pointsArr = arc.getPoints(50);
  const geometry = new THREE.BufferGeometry();
  geometry.setFromPoints(pointsArr);
  const material = new THREE.LineBasicMaterial({
    color: new THREE.Color("white"),
  });
  const line = new THREE.Line(geometry, material);
  circleGroup.add(line);
}
group.add(circleGroup);

第三步:做不规则的图形

  • 如下图: image.png
  • 基础就是用点来确定形态用线来串联
// 画图形
const figureGroup = new THREE.Group();
// 360 ° 每次加 10弧度
for (let angle = 0; angle < Math.PI * 2; angle += Math.PI / 10) {
  const R = 200;
  const x = R * Math.cos(angle);
  const y = R * Math.sin(angle);

  // 用11点画线
  const pointsArr = [
    new THREE.Vector3(0, 0, 0),
    new THREE.Vector3(10, 0, 0),
    new THREE.Vector3(10, 10, 0),
    new THREE.Vector3(-10, 10, 0),
    new THREE.Vector3(-10, -10, 0),
    new THREE.Vector3(20, -10, 0),
    new THREE.Vector3(20, 20, 0),
    new THREE.Vector3(-20, 20, 0),
    new THREE.Vector3(-20, -20, 0),
    new THREE.Vector3(20, -20, 0),
  ];

  const geometry = new THREE.BufferGeometry();
  geometry.setFromPoints(pointsArr);
  const material = new THREE.LineBasicMaterial({
    color: new THREE.Color("white"),
  });
  const line = new THREE.Line(geometry, material);

  line.position.set(x, y, 0);
  line.rotation.z = angle;

  figureGroup.add(line);
}
group.add(figureGroup);
  • 效果如下图 image.png

第四步再来一圈调一下位置

const figureGroup2 = new THREE.Group();
for (let angle = 0; angle < Math.PI * 2; angle += Math.PI / 10) {
  const R = 260;
  const x = R * Math.cos(angle);
  const y = R * Math.sin(angle);

  const pointsArr = [
    new THREE.Vector3(0, 0, 0),
    new THREE.Vector3(15, 0, 0),
    new THREE.Vector3(15, 15, 0),
    new THREE.Vector3(-15, 15, 0),
    new THREE.Vector3(-15, -15, 0),
    new THREE.Vector3(30, -15, 0),
    new THREE.Vector3(30, 30, 0),
    new THREE.Vector3(-30, 30, 0),
    new THREE.Vector3(-30, -30, 0),
    new THREE.Vector3(30, -30, 0),
  ];

  const geometry = new THREE.BufferGeometry();
  geometry.setFromPoints(pointsArr);
  const material = new THREE.LineBasicMaterial({
    color: new THREE.Color("white"),
  });
  const line = new THREE.Line(geometry, material);

  line.position.set(x, y, 0);
  line.rotation.z = angle;

  figureGroup2.add(line);
}
group.add(figureGroup2);
  • 如下图 image.png

第五步:来点动画每一个child都间隔反向转动

image.png

  • main.js 的render方法处理一下
function render() {
  renderer.render(scene, camera);
  requestAnimationFrame(render);
  mesh.children.forEach((item, index) => {
    const flag = index % 2 === 0 ? 1 : -1;
    item.rotation.z += 0.001 * index * flag;
  });
}
render();
  • 上述就会转动啦
//这个是按照半径生成位置点位的要理解一下
const R = 130;
const x = R * Math.cos(angle);
const y = R * Math.sin(angle);