我的编程空间,编程开发者的网络收藏夹
学习永远不晚

three.js响应式设计的方法

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

three.js响应式设计的方法

这篇“three.js响应式设计的方法”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“three.js响应式设计的方法”文章吧。

1-canvas 的响应式布局

canvas 画布的尺寸有两种:

  • 像素尺寸,即canvas画布在高度和宽度上有多少个像素,默认是300*150

  • css 尺寸,即css 里的width和height

在web前端,dom元素的响应式布局一般是通过css 实现的。

而canvas 则并非如此,canvas 的响应式布局需要考虑其像素尺寸。

接下来,咱们就通过让canvas 画布自适应浏览器的窗口的尺寸,来说一下canvas 的响应式布局。

将之前的RenderStructure.tsx 复制粘贴一份,改名ResponsiveDesign.tsx,用于写响应式布局。

将ResponsiveDesign.tsx 页面添加到路由中。

  • class="lazy" data-src/app.tsx

import React from "react";import { useRoutes } from "react-router-dom";import "./App.css";import MainLayout from "./view/MainLayout";import Fundamentals from "./view/Fundamentals";import ResponsiveDesign from "./view/ResponsiveDesign";const App: React.FC = (): JSX.Element => {  const routing = useRoutes([    {      path: "/",      element: <MainLayout />,    },    {      path: "Fundamentals",      element: <Fundamentals />,    },    {      path: "ResponsiveDesign",      element: <ResponsiveDesign />,    },  ]);  return <>{routing}</>;};export default App;

在ResponsiveDesign.tsx中先取消renderer 的尺寸设置。

//renderer.setSize(innerWidth, innerHeight);

用css 设置canvas 画布及其父元素的尺寸,使其充满窗口。

  • class="lazy" data-src/view/ResponsiveDesign

const ResponsiveDesign: React.FC = (): JSX.Element => {  ……  return <div ref={divRef} className="canvasWrapper"></div>;};
  • class="lazy" data-src/view/fullScreen.css

html {  height: 100%;}body {  margin: 0;  overflow: hidden;  height: 100%;}#root,.canvasWrapper,canvas{  width: 100%;  height: 100%;}

将fullScreen.css 导入ResponsiveDesign.tsx

import "./fullScreen.css";

效果如下:

three.js响应式设计的方法

由上图可见,立方体的边界出现了锯齿,这就是位图被css拉伸后失真导致的,默认canvas 画布的尺寸只有300*150。

因此,我们需要用canvas 画布的像素尺寸自适应窗口。

建立一个让canvas 像素尺寸随css 尺寸同步更新的方法。

resizeRendererToDisplaySize(renderer);// 将渲染尺寸设置为其显示的尺寸,返回画布像素尺寸是否等于其显示(css)尺寸的布尔值function resizeRendererToDisplaySize(renderer) {  const { width, height, clientWidth, clientHeight } = renderer.domElement;  const needResize = width !== clientWidth || height !== clientHeight;  if (needResize) {    renderer.setSize(clientWidth, clientHeight, false);  }  return needResize;}
  • renderer.setSize(w,h,bool) 是重置渲染尺寸的方法,在此方法里会根据w,h参数重置canvas 画布的尺寸。

    this.setSize = function ( width, height, updateStyle ) {        if ( xr.isPresenting ) {            console.warn( 'THREE.WebGLRenderer: Can't change size while VR device is presenting.' );            return;        }        _width = width;        _height = height;        _canvas.width = Math.floor( width * _pixelRatio );        _canvas.height = Math.floor( height * _pixelRatio );        if ( updateStyle !== false ) {            _canvas.style.width = width + 'px';            _canvas.style.height = height + 'px';        }        this.setViewport( 0, 0, width, height );    };

setSize() 方法中的bool 参数很重要,会用于判断是否设置canvas 画布的css 尺寸。

当canvas 画布的尺寸变化了,相机视口的宽高比也需要同步调整。这样我们拖拽浏览器的边界,缩放浏览器的时候,就可以看到canvas 画布自适应浏览器的尺寸了。

function animate() {  requestAnimationFrame(animate);  if (resizeRendererToDisplaySize(renderer)) {    const { clientWidth, clientHeight } = renderer.domElement;    camera.aspect = clientWidth / clientHeight;    camera.updateProjectionMatrix();  }  cubes.forEach((cube) => {    cube.rotation.x += 0.01;    cube.rotation.y += 0.01;  });  renderer.render(scene, camera);}
  • camera.aspect 属性是相机视口的宽高比

  • 我们在WebGL 里说透视投影矩阵的时候说过,当相机视口的宽高比变了,相机的透视投影矩阵也会随之改变,因此我们需要使用camera.updateProjectionMatrix() 方法更新透视投影矩阵。

  • 至于我们为什么不把更新相机视口宽高比的方法一起放进resizeRendererToDisplaySize()里,这是为了降低resizeRendererToDisplaySize() 方法和相机的耦合度。具体要不要这么做视项目需求而定。

接下来咱们可以举个例子,说一下canvas 画布响应式布局的应用场合。

示例:三维插图

在下面的例子里,我们会给三维插图一个缩放功能,从而更好的观察细节。

three.js响应式设计的方法

新建一个Illustration 页。

  • class="lazy" data-src/view/Illustration.tsx

import React, { useRef, useEffect, useState } from "react";import { BoxGeometry, DirectionalLight, Mesh, MeshPhongMaterial, PerspectiveCamera, Scene, WebGLRenderer } from "three";import "./Illustration.css";const { innerWidth, innerHeight } = window;const scene = new Scene();const camera = new PerspectiveCamera(75, innerWidth / innerHeight, 0.1, 1000);const renderer = new WebGLRenderer();// renderer.setSize(innerWidth, innerHeight, false);// 光源const color = 0xffffff;const intensity = 1;const light = new DirectionalLight(color, intensity);light.position.set(-1, 2, 4);scene.add(light);const geometry = new BoxGeometry();const material = new MeshPhongMaterial({ color: 0x44aa88 });camera.position.z = 5;const cubes = [-2, 0, 2].map((num) => makeInstance(num));scene.add(...cubes);// 将渲染尺寸设置为其显示的尺寸,返回画布像素尺寸是否等于其显示(css)尺寸的布尔值function resizeRendererToDisplaySize(renderer: WebGLRenderer) {  const { width, height, clientWidth, clientHeight } = renderer.domElement;  const needResize = width !== clientWidth || height !== clientHeight;  if (needResize) {    renderer.setSize(clientWidth, clientHeight, false);  }  return needResize;}function makeInstance(x: number) {  const cube = new Mesh(geometry, material);  cube.position.x = x;  return cube;}function animate() {  requestAnimationFrame(animate);  if (resizeRendererToDisplaySize(renderer)) {    const { clientWidth, clientHeight } = renderer.domElement;    camera.aspect = clientWidth / clientHeight;    camera.updateProjectionMatrix();  }  cubes.forEach((cube) => {    cube.rotation.x += 0.01;    cube.rotation.y += 0.01;  });  renderer.render(scene, camera);}const Illustration: React.FC = (): JSX.Element => {  const divRef = useRef<HTMLDivElement>(null);  let [btnState, setBtnState] = useState(["small", "放大"]);  const toggle = () => {    if (btnState[0] === "small") {      setBtnState(["big", "缩小"]);    } else {      setBtnState(["small", "放大"]);    }  };  useEffect(() => {    const { current } = divRef;    if (current) {      current.innerHTML = "";      current.append(renderer.domElement);    }    animate();  }, []);  return (    <div className="cont">      <p>        立方体,也称正方体,是由6个正方形面组成的正多面体,故又称正六面体。它有12条边和8个顶点。其中正方体是特殊的长方体。立方体是一种特殊的正四棱柱、长方体、三角偏方面体、菱形多面体、平行六面体,就如同正方形是特殊的矩形、菱形、平行四边形一様。立方体具有正八面体对称性,即考克斯特BC3对称性,施莱夫利符号        ,考克斯特-迪肯符号,与正八面体对偶。      </p>      <div className="inllustration">        <div ref={divRef} className={`canvasWrapper ${btnState[0]}`}></div>        <button className="btn" onClick={toggle}>          {btnState[1]}        </button>      </div>      <p>        立方体有11种不同的展开图,即是说,我们可以有11种不同的方法切开空心立方体的7条棱而将其展平为平面图形,见图1。 [2] 立方体的11种不同展开图。        如果我们要将立方体涂色而使相邻的面不带有相同的颜色,则我们至少需要3种颜色(类似于四色问题)。        立方体是唯一能够独立密铺三维欧几里得空间的柏拉图正多面体,因此立方体堆砌也是四维唯一的正堆砌(三维空间中的堆砌拓扑上等价于四维多胞体)。它又是柏拉图立体中唯一一个有偶数边面——正方形面的,因此,它是柏拉图立体中独一无二的环带多面体(它所有相对的面关于立方体中心中心对称)。        将立方体沿对角线切开,能得到6个全等的正4棱柱(但它不是半正的,底面棱长与侧棱长之比为2:√3)将其正方形面贴到原来的立方体上,能得到菱形十二面体(Rhombic        Dodecahedron)(两两共面三角形合成一个菱形)。      </p>      <p>        立方体的对偶多面体是正八面体。 当正八面体在立方体之内: 正八面体体积: 立方体体积=[(1/3)×高×底面积]×2: 边=(1/3)(n/2)[(n)/2]2: n=1: 6 星形八面体的对角线可组成一个立方体。        截半立方体:从一条棱斩去另一条棱的中点得出 截角立方体        超正方体:立方体在高维度的推广。更加一般的,立方体是一个大家族,即立方形家族(又称超方形、正测形)的3维成员,它们都具有相似的性质(如二面角都是90°、有类似的超体积公式,即Vn-cube=a等)。        长方体、偏方面体的特例。      </p>      <p>        立方体是唯一能够独立密铺三维欧几里得空间的柏拉图正多面体,因此立方体堆砌也是四维唯一的正堆砌(三维空间中的堆砌拓扑上等价于四维多胞体)。它又是柏拉图立体中唯一一个有偶数边面——正方形面的,因此,它是柏拉图立体中独一无二的环带多面体(它所有相对的面关于立方体中心中心对称)。        将立方体沿对角线切开,能得到6个全等的正4棱柱(但它不是半正的,底面棱长与侧棱长之比为2:√3)将其正方形面贴到原来的立方体上,能得到菱形十二面体(Rhombic        Dodecahedron)(两两共面三角形合成一个菱形)。      </p>    </div>  );};export default Illustration;

设置css 样式

  • class="lazy" data-src/view/Illustration.css

p {  text-indent: 2em;  line-height: 24px;  font-size: 14px;}.cont {  width: 80%;  max-width: 900px;  margin: auto;}.inllustration{  position: relative;  float: left;}.canvasWrapper {  margin-right: 15px;  transition-property: width, height;  transition-duration: 1s, 1s;}.small {  width: 150px;  height: 150px;}.big {  width: 100%;  height: 100%;}.canvasWrapper canvas {  width: 100%;  height: 100%;}.btn {  position: absolute;  top: 0;  left: 0;  cursor: pointer;}

在App.tsx 中,基于Illustration页新建一个路由

  • class="lazy" data-src/App.tsx

import React from "react";import { useRoutes } from "react-router-dom";import Basics from "./view/Basics";import RenderStructure from "./view/RenderStructure";import ResponsiveDesign from "./view/ResponsiveDesign";import Illustration from "./view/Illustration";const App: React.FC = (): JSX.Element => {  const routing = useRoutes([    ……    {      path: "Illustration",      element: <Illustration />,    },  ]);  return <>{routing}</>;};export default App;

在首页Basics.tsx中再开一个链接

import React from "react";import { Link } from "react-router-dom";const Basics: React.FC = (): JSX.Element => {  return (    <nav style={{ width: "60%", margin: "auto" }}>      <h3>three.js 基础示例</h3>      <ul>        ……        <li>          <Link to="/Illustration">Illustration 三维插图</Link>        </li>      </ul>    </nav>  );};export default Basics;

接下来,在首页点击Illustration 链接,就可以看到效果。

2-自适应设备分辨率

当今大多数的PC端和移动端显示器都是HD-DPI显示器。

HD-DPI 是High Definition-Dots Per Inch 的简称,意思是高分辨率显示器。

不同设备的显示器的分辨率是不一样的。

做过测试的会知道,我们需要用不同的设备测试项目,比如下面微信小程序开发者工具里提供的机型。

three.js响应式设计的方法

以上图中的iPhone6/7/8 为例:

  • 375667 代表的手机的屏幕的物理尺寸,如果我们在其中建立一个100% 充满屏幕的,那其尺寸就是375667。

  • Dpr 代表像素密度,2 表示手机屏幕在宽度上有3752 个像素,在高度上有6672 个像素,因此iPhone6/7/8 的屏幕的像素尺寸就是750*1334。

当我们在这种像素尺寸大于物理尺寸的高分辨率显示器里绘图的时候,就需要考虑一个问题。

若我们直接在iPhone6/7/8 里建立一个充满屏幕的canvas,那其像素尺寸就是375*667。

这个尺寸并没发挥高分辨率显示器的优势,我们需要先将其像素尺寸设置为7501334,然后再将其css 尺寸设置为375667。

这样,就可以让canvas画布以高分辨率的姿态显示在显示器里。

代码示例:

function resizeRendererToDisplaySize(renderer: WebGLRenderer) {  const { width, height, clientWidth, clientHeight } = renderer.domElement;  const [w, h] = [clientWidth * devicePixelRatio, clientHeight * devicePixelRatio];  const needResize = width !== w || height !== h;  if (needResize) {    renderer.setSize(w, h, false);  }  return needResize;}

上面的devicePixelRatio 就是设备像素密度,是window下的属性,即window.devicePixelRatio。

其实,有的时候若不刻意观察,canvas 有没有自适应设备分辨率是很难看出的。

因此,若是对画面的渲染质量要求不高,可以什么都不做,这样也能避免canvas 画布像素尺寸变大后降低渲染效率的问题。

关于响应式设计咱们就说到这,接下来咱们说一下three.js 里的内置几何体。

以上就是关于“three.js响应式设计的方法”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程网行业资讯频道。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

three.js响应式设计的方法

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

three.js响应式设计的方法

这篇“three.js响应式设计的方法”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“three.js响应式设计的方法”文章吧
2023-06-30

layui table响应式布局的设计与实现(构建响应式layui table布局的方法)

layui表格响应式布局指南本文介绍了构建响应式layuitable布局的详细方法,包括初始化表格、设置媒体查询、调整表头宽度、隐藏/显示列和添加可滚动区域。通过遵循这些步骤,可以创建可在各种设备屏幕尺寸上无缝显示数据的响应式表格。
layui table响应式布局的设计与实现(构建响应式layui table布局的方法)
2024-04-02

Responsive Web Design响应式网页设计方法是什么

本篇内容主要讲解“Responsive Web Design响应式网页设计方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Responsive Web Design响应式网页设计方法是什
2023-06-04

如何设计响应式WEB

本篇内容主要讲解“如何设计响应式WEB”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何设计响应式WEB”吧!1、为什么需要响应式web设计 由于目前移动设备的大量使用,以及PC显示器的尺寸逐渐
2023-06-08

响应式设计的示例分析

小编给大家分享一下响应式设计的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1.什么是响应式设计?响应式设计就是在网站开发过程中根据用户操作以及设备的环境
2023-06-08

响应式设计中流行的布局方式有哪些?

响应式设计是一种在不同设备上实现一致的用户体验的设计方法。随着移动设备的普及,越来越多的人使用不同尺寸的屏幕访问网页,因此响应式设计已经成为现代网页设计的重要组成部分。在实践中,设计师使用各种布局方式来实现响应式设计。本文将介绍一些流行的响
响应式设计中流行的布局方式有哪些?
2024-02-22

探究响应式网页设计中的不同布局方式

在当今数字化时代,响应式网页设计已经成为了网页设计的基本要求。响应式设计能够使网页在不同尺寸的屏幕上展现出最佳的视觉效果和用户体验,为用户提供了更好的浏览体验。而在响应式网页设计中,不同的布局方式则起到了至关重要的作用。本文将探究响应式网页
探究响应式网页设计中的不同布局方式
2024-02-22

元素选择器的应用于响应式设计

元素选择器在响应式设计中的应用,需要具体代码示例随着移动设备的普及,响应式设计已经成为现代网页设计的基本要求之一。而元素选择器在响应式设计中扮演着至关重要的角色。通过元素选择器,我们可以根据不同的设备尺寸、屏幕密度、浏览器窗口大小等因素,
元素选择器的应用于响应式设计
2024-01-15

解析响应式设计中绝对定位的挑战及解决方法

绝对定位在响应式设计中的挑战与解决方案在现代Web开发中,响应式设计已经成为了一种趋势,因为它能够使网站在不同的设备上展现出最佳的布局与用户体验。然而,在使用绝对定位时,特别是在响应式设计中,会遇到一些挑战。本文将探讨绝对定位在响应式设计
解析响应式设计中绝对定位的挑战及解决方法
2024-01-23

如何在响应式设计中选择最适合的布局方式

在当今互联网时代,移动设备的普及率越来越高,用户对于访问网页的需求也开始从传统的桌面电脑转向移动设备,这就使得网页设计师需要考虑响应式设计来适应不同屏幕尺寸的设备。而在响应式设计中,选择最适合的布局方式显得尤为重要。本文将介绍一些常见的布局
如何在响应式设计中选择最适合的布局方式
2024-02-22

CSS 响应式设计:打造适应性强的布局

适应性布局:打造响应式设计的核心
CSS 响应式设计:打造适应性强的布局
2024-03-13

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录