主頁 > 企業開發 > Three.js 進階之旅:全景漫游-初階移動相機版

Three.js 進階之旅:全景漫游-初階移動相機版

2023-03-28 09:03:15 企業開發

宣告:本文涉及圖文和模型素材僅用于個人學習、研究和欣賞,請勿二次修改、非法傳播、轉載、出版、商用、及進行其他獲利行為,

摘要

3D 全景技術可以實作日常生活中的很多功能需求,比如地圖的街景全景模式、數字展廳、在線看房、社交媒體的全景圖預覽、短視頻直播平臺的全景直播等,Three.js 實作全景功能也是十分方便的,當然了目前已經有很多相關內容的文章,我之前就寫過一篇《Three.js 實作3D全景偵探小游戲》,因此本文內容及此專欄下一篇文章討論的重點不是如何實作 3D 全景圖功能,而是如何一步步優雅實作在多個3D全景中穿梭漫游,達到如在真實世界中前進后退的視覺效果

全景漫游系列文章將分為上下兩篇,本篇內容我們先介紹如何通過移動相機的方法來達到場景切換的目的,通過本文的學習,你將學到的知識點包括:在 Three.js 中創建全景圖的幾種方式、在 3D 全景圖中添加互動熱點、利用 Tween.js 實作相機切換影片、多個全景圖之間的切換等,

效果

本文最終將實作如下的效果,左右控制滑鼠旋轉螢屏可以預覽室內三維全景圖,同時全景圖內有多個互動熱點,它們標識著三維場景內的一些物體,比如沙發 ?? 、電視機 ?? 等,互動熱點會隨著場景的旋轉而旋轉,點擊熱點 ?? 可以彈出互動反饋提示框,

點擊螢屏上有其他場景名稱的按鈕比如 客廳臥室書房 時,可以從當前場景切換到目標場景全景圖,互動熱點也會同時切換,

打開以下鏈接,在線預覽效果,大屏訪問效果更佳,

  • ????? 在線預覽地址:https://dragonir.github.io/panorama-basic/

本專欄系列代碼托管在 Github 倉庫【threejs-odessey】,后續所有目錄也都將在此倉庫中更新

?? 代碼倉庫地址:[email protected]:dragonir/threejs-odessey.git

原理

我們先來簡單總結下在 Three.js 中實作三維全景功能的有哪些方式:

球體

在球體內添加 HDR 全景照片可以實作三維全景功能,全景照片是一張用球形相機拍攝的圖片,如下圖所示:

const geometry = new THREE.SphereGeometry(500, 60, 40);
geometry.scale(- 1, 1, 1);
const texture = new THREE.TextureLoader().load( 'textures/hdr.jpg');
const material = new THREE.MeshBasicMaterial({ map: texture });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

?? 球體全景圖 Three.js 官方示例

立方體

在立方體內添加全景圖貼圖的方式也可以實作三維全景圖功能,此時需要對 HDR 全景照片進行裁切,分割成 6 張來分別對應立方體的 6 個面,

const textures = cubeTextureLoader.load([
  '/textures/px.jpg',
  '/textures/nx.jpg',
  '/textures/py.jpg',
  '/textures/ny.jpg',
  '/textures/pz.jpg',
  '/textures/nz.jpg'
]);

const materials = [];
for ( let i = 0; i < 6; i ++ ) {
  materials.push( new THREE.MeshBasicMaterial( { map: textures[ i ] } ) );
}
const skyBox = new THREE.Mesh( new THREE.BoxGeometry( 1, 1, 1 ), materials );
skyBox.geometry.scale( 1, 1, - 1 );
scene.add( skyBox );

?? 立方體全景圖 Three.js 官方示例

環境貼圖

使用環境貼圖也可以實作全景圖功能,像下面這樣加載全景圖片,然后將它賦值給 scene.backgroundscene.environment 即可:

const environmentMap = cubeTextureLoader.load([
    '/textures/px.jpg',
    '/textures/nx.jpg',
    '/textures/py.jpg',
    '/textures/ny.jpg',
    '/textures/pz.jpg',
    '/textures/nz.jpg'
]);
environmentMap.encoding = THREE.sRGBEncoding;
scene.background = environmentMap;
scene.environment = environmentMap;

?? 具體原理和實作方式就不詳細介紹了,可查看我往期的文章《Three.js 進階之旅:多媒體應用-3D Iphone》,環境貼圖段落中有詳細實作介紹,

其他

除了使用 Three.js 自己實作全景圖功能之外,也有一些其他功能完備的全景圖庫可以很方便的實作三維全景場景,比如下面幾個就比較不錯,其中后兩個是 GUI 客戶端,可以在客戶端內非常方便的在全景圖上添加互動熱點、實作多個場景的漫游路徑等,大家感興趣的話都可以試試,

  • panolens.js
  • pannellum
  • Photo-Sphere-Viewer
  • krpano
  • Pano2VR

工具

全景圖生成工具

  • 使用球形全景相機拍攝,
  • 使用 Blender 等建模軟體相機 360 度旋轉渲染,

全景圖編輯工具

下面兩個網站提供豐富的三維全景背景照片及將 hdr 圖片裁切成上述需要的 6 張貼圖的能力,大家可以按自己需要下載和編輯,

?? HDR全景背景照片下載網站:polyhaven

?? HDR立方體材質轉換工具:HDRI-to-CubeMap

實作

現在,我們使用第一種球體 ? 全景圖的方式,來實作示例中介紹的內容,

〇 場景初始化

創建全景圖前先做一些常規三維場景準備作業,由于三維全景圖功能并不會涉及到新的技術點,因此像下面這樣簡單實作就可以,

<canvas ></canvas>

在檔案頂部引入以下資源,其中 OrbitControls 用于旋轉全景圖時的鏡頭滑鼠控制;TWEEN 用于創建流程的場景切換影片,Animations 是使用 TWEEN 來控制攝像機和控制器切換的方法的封裝,可以快速實作鏡頭的絲滑切換;rooms 是自定義的一個陣列,用來保存多個全景圖的資訊,

import * as THREE from 'three';
import { OrbitControls } from '@/utils/OrbitControls.js';
import { TWEEN } from 'three/examples/jsm/libs/tween.module.min.js';
import Animations from '@/utils/animations';
import { rooms } from '@/views/home/data';

然后初始化渲染器、場景、相機、控制器、頁面縮放適配、頁面重繪影片等,

const sizes = {
  width: window.innerWidth,
  height: window.innerHeight,
};

// 初始化渲染器
const canvas = document.querySelector('canvas.webgl');
const renderer = new THREE.WebGLRenderer({ canvas });
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));

// 初始化場景
const scene = new THREE.Scene();

// 初始化相機
const camera = new THREE.PerspectiveCamera(65, sizes.width / sizes.height, 0.1, 1000);
camera.position.z = data.cameraZAxis;
scene.add(camera);

// 鏡頭控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 0, 0);

// 頁面縮放監聽
window.addEventListener('resize', () => {
  sizes.width = window.innerWidth;
  sizes.height = window.innerHeight;
  // 更新渲染
  renderer.setSize(sizes.width, sizes.height);
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
  // 更新相機
  camera.aspect = sizes.width / sizes.height;
  camera.updateProjectionMatrix();
});

// 影片
const tick = () => {
  controls && controls.update();
  TWEEN && TWEEN.update();
  renderer.render(scene, camera);
  window.requestAnimationFrame(tick);
};
tick();

① 創建一個球體

現在,像下面這樣,我們往場景中添加一個三維球體 ?,作為第一個全景圖的載體,其中 THREE.SphereGeometry(radius, segmentsWidth, segmentsHeight, phiStart, phiLength, thetaStart, thetaLength) 接收 7 個引數,我們使用前 3 個引數半徑、經度上的面數切片數、緯度上的切片數即可,數值可按自己的需求自行調整,

const geometry = new THREE.SphereGeometry(16, 256, 256);
const material = new THREE.MeshBasicMaterial({
  color: 0xffffff,
});
const room = new THREE.Mesh(geometry, material);
scene.add(room);

② 創建全景圖

現在我們對球體進行全景圖片貼圖,并將 side 屬性設定為 THREE.DoubleSide 或者 THREE.BackSide 然后通過設定 geometry.scale(1, 1, -1) 將球體內外翻轉,就能得到下面所示的效果,

const geometry = new THREE.SphereGeometry(16, 256, 256);
const material = new THREE.MeshBasicMaterial({
  map: textLoader.load(map),
  side: THREE.DoubleSide,
});
geometry.scale(1, 1, -1);
const room = new THREE.Mesh(geometry, material);

此時,我們通過滑鼠放大球體,進入到球體內部,上下左右旋轉球體,就能觀察到全景效果了,

③ 創建其他場景的全景圖

對于數量較少,簡單的場景我們可以創建多個球體全景圖來實作,這種方式雖然笨重,但是控制多個場景很方便,代碼也非常容易理解,下篇文章將通過另一種更優雅的方式來實作多個全景圖場景,以適應更加復雜的需求,

我們先對創建球體 ? 全景圖的方法加以封裝,通過 createRoom 方法批量創建多個全景圖場景,它接收的名稱 name、位置 position 以及 貼圖 map 三個引數是通過上述引入的 rooms 數值配置的,

const createRoom = (name, position, map) => {
  const geometry = new THREE.SphereGeometry(16, 256, 256);
  geometry.scale(1, 1, -1);
  const material = new THREE.MeshBasicMaterial({
    map: textLoader.load(map),
    side: THREE.DoubleSide,
  });
  const room = new THREE.Mesh(geometry, material);
  room.name = name;
  room.position.set(position.x, position.y, position.z);
  room.rotation.y = Math.PI / 2;
  scene.add(room);
  return room;
};

// 批量創建
rooms.map((item) => {
  const room = createRoom(item.key, item.position, item.map);
  return room;
});

我們按房間位置的和貼圖的配置,創建如下所示的三個房間客廳、臥室和書房,

④ 限制旋轉角度

根據自己的需求,我們可以對鏡頭控制器 ?? 做以下限制,比如開啟轉動慣性、禁止整個場景通過滑鼠右鍵發生平移、設定縮放的最大級別防止暴露出球體、限制垂直方向旋轉等,以增強用戶體驗,

// 轉動慣性
controls.enableDamping = true;
// 禁止平移
controls.enablePan = false;
// 縮放限制
controls.maxDistance = 12;
// 垂直旋轉限制
controls.minPolarAngle = Math.PI / 2;
controls.maxPolarAngle = Math.PI / 2;

⑤ 實作多個場景穿梭漫游

本文中實作多個場景穿梭漫游的方法原理:主要是通過移動相機和控制器的中點位置來實作的,我們先用用于生成多個場景的 rooms 數值在頁面上添加一些表示切換房間的按鈕,點擊按鈕時拿到需要跳轉的目標場景資訊,然后通過 Animations.animateCamera 方法將像機和控制器從當前位置平滑移動到目標位置

// 點擊切換場景
const handleSwitchButtonClick = async (key) => {
  const room = rooms.filter((item) => item.key === key)[0];
  if (data.camera) {
    const x = room.position.x;
    const y = room.position.y;
    const z = room.position.z;
    Animations.animateCamera(data.camera, data.controls, { x, y, z: data.cameraZAxis }, { x, y, z }, 1600, () => {});
    data.controls.update();
  }
};

其中 Animations.animateCamera 方法是使用 TWEEN.js 封裝的一個移動相機 ?? 和控制器 ?? 的方法,使用它可以實作絲滑的鏡頭補間影片,不僅可以像本文中這樣來實作多個場景的切換,還可以實作像鏡頭從遠處拉近、點擊互動點后鏡頭聚焦放大到某個區域鏡頭場景巡航等效果,完整代碼可以查看本篇文章的示例代碼:

animateCamera: (camera, controls, newP, newT, time = 2000, callBack) => {
  const tween = new TWEEN.Tween({
    x1: camera.position.x, // 相機x
    y1: camera.position.y, // 相機y
    z1: camera.position.z, // 相機z
    x2: controls.target.x, // 控制點的中心點x
    y2: controls.target.y, // 控制點的中心點y
    z2: controls.target.z, // 控制點的中心點z
  });
  tween.to(
    {
      x1: newP.x,
      y1: newP.y,
      z1: newP.z,
      x2: newT.x,
      y2: newT.y,
      z2: newT.z,
    },
    time,
  );
  // ...
}

⑥ 添加互動點

場景漫游穿梭的功能已經實作了,現在我們來在全景場景中添加一些互動熱點 ?,用于實作場景物體標注和滑鼠點擊互動,比如我們在這個示例中,在客廳中添加了 電視機??沙發??冰箱?? 等互動點,我們可以現在創建場景的陣列中添加這些互動點的資訊 interactivePoints,以方便批量創建,根據自己的需求我們可以添加一些可選的配置引數,本文中的引數含義分別是:

  • key:唯一識別符號,
  • value:顯示名稱,
  • description:描述文案,
  • cover:配圖,
  • position:在三維空間中的位置,
const rooms = [
  {
    name: '客廳',
    key: 'living-room',
    map: new URL('@/assets/images/map/map_living_room.jpg', import.meta.url).href,
    position: new Vector3(0, 0, 0),
    interactivePoints: [
      {
        key: 'tv',
        value: '電視機',
        description: '智能電視',
        cover: new URL('@/assets/images/home/cover_living_room_tv.png', import.meta.url).href,
        position: new Vector3(-6, 2, -8),
      },
      // ...
    ],
  },

然后在頁面上利用 rooms 陣列的 interactivePoints 來批量創建互動點的 DOM 節點:

<div
  
  v-for="(point, index) in interactivePoints"
  :key="index"
  :
  @click="handleReactivePointClick(point)"
  v-show="point.room === data.currentRoom"
>
  <div  :>
    <label >
      <div >
        <i
          
          :style="{
            background: `url(${point.cover}) no-repeat center`,
            'background-size': 'contain',
          }"
        ></i>
      </div>
      <div >
        <p >{{ point.value }}</p>
        <p >{{ point.description }}</p>
      </div>
    </label>
  </div>
</div>

用樣式表把互動點設定成自己喜歡的樣式 ?? ,需要注意的一點是,互動點 ?? 初始的樣式中設定了 transform: scale(0, 0), 即它的寬高都為 0,是隱藏看不見的,這樣設定的目的是為了實作只有互動點出現在相機可視區域時才顯示在場景中,其他轉動到相機背面時應該隱藏掉,當互動點被添加 .visible 類時,互動點變為顯示狀態,本示例中還使用互動點內 .label::before.label::after等偽元素和子元素添加了一些波紋擴散影片及其其他文案資訊等,

.point
  position: fixed
  top: 50%
  left: 50%
  .label
    position: absolute
    &::before, &::after
      display inline-block
      content ''
    &::before
      animation: bounce-wave 1.5s infinite
    &::after
      animation: bounce-wave 1.5s -0.4s infinite
    .label-tips
      height 88px
      width 200px
      position absolute
  &.visible .label
    transform: scale(1, 1)

?? 隱藏顯示的互動也可以通過 display:nonevisibility:hidden、及使用 js 變數控制元素隱藏顯示等方式來實作,

創建完互動點 ?? 元素之后,我們還需要在頁面重繪方法 tick() 中像下面這樣添加一個方法,來將互動點顯示在三維場景中,并根據與相機的關系來控制每個互動點的顯示與隱藏,原理是使用 THREE.Raycaster 來檢測元素是否被遮擋:

const raycaster = new THREE.Raycaster();

const tick = () => {
  for (const point of _points) {
    // 獲取2D螢屏位置
    const screenPosition = point.position.clone();
    const pos = screenPosition.project(camera);
    raycaster.setFromCamera(screenPosition, camera);
    const intersects = raycaster.intersectObjects(scene.children, true);
    if (intersects.length === 0) {
      // 未找到相交點,顯示
      point.element.classList.add('visible');
    } else {
      // 獲取相交點的距離和點的距離
      const intersectionDistance = intersects[0].distance;
      const pointDistance = point.position.distanceTo(camera.position);
      // 相交點距離比點距離近,隱藏;相交點距離比點距離遠,顯示
      intersectionDistance < pointDistance
        ? point.element.classList.remove('visible')
        : point.element.classList.add('visible');
    }
    pos.z > 1
      ? point.element.classList.remove('visible')
      : point.element.classList.add('visible');
    const translateX = screenPosition.x * sizes.width * 0.5;
    const translateY = -screenPosition.y * sizes.height * 0.5;
    point.element.style.transform = `translateX(${translateX}px) translateY(${translateY}px)`;
  }
  // ...
};

?? 關于使用 Raycaster 來檢測元素是否被遮擋的詳細介紹,可以看看我的這篇文章《Three.js 打造繽紛夏日3D夢中情島》,

⑦ 頁面優化和加載進度管理

最后,因為創建多個三維全景圖場景需要加載很多張圖片,而且全景圖的圖片一般比較大,我們可以預先加載完所有圖片后再進行渲染,本文使用的是自己添加的一個預加載方法,也可以使用像 preload.js 等其他庫來預加載圖片,除了加載進度顯示之外,現實開發場景中應該還有很多個性化的需求,比如可以在點擊互動點的時候彈出一個詳細彈窗、點擊電視的時候開始播放一段視頻、點擊沙發的時候鏡頭聚焦放大到沙發、點擊開關的時候變為夜間模式……這些互動的原理和本文中的互動點是差不多的 ??

?? 原始碼地址: https://github.com/dragonir/threejs-odessey

總結

本文中主要包含的知識點包括:

  • Three.js 中實作全景圖的原理和多種實作方式,
  • 與全景圖相關的生成工具、編輯工具的使用,
  • 創建多個全景圖并實作多個場景間的漫游穿梭功能,
  • 在三維全景圖中添加互動熱點,

本文到這里就結束了,本文中通過移動相機鏡頭和控制的方法來實作幾個全景圖之間漫游穿梭效果還是不錯的,但是它的缺點也是很明顯的,就是當全景場景數量特別多時,就需要創建非常多的球體,此時計算出每個場景的位置非常困難,并且會造成頁面性能耗損問題,因此需要進行優化,下篇文章將會介紹另一種更加優雅的方式來實作全景圖之間的漫游功能,過渡影片也會更加流暢絲滑,

想了解其他前端知識或其他未在本文中詳細描述的Web 3D開發技術相關知識,可閱讀我往期的文章,如果有疑問可以在評論中留言,如果覺得文章對你有幫助,不要忘了一鍵三連哦 ??

附錄

  • [1]. ?? Three.js 打造繽紛夏日3D夢中情島
  • [2]. ?? Three.js 實作炫酷的賽博朋克風格3D數字地球大屏
  • [3]. ?? Three.js 實作2022冬奧主題3D趣味頁面,含冰墩墩
  • [4]. ?? Three.js 實作3D開放世界小游戲:阿貍的多元宇宙
  • [5]. ?? 掘金1000粉!使用Three.js實作一個創意紀念頁面
  • ...
  • 【Three.js 進階之旅】系列專欄訪問 ??
  • 更多往期【3D】專欄訪問 ??
  • 更多往期【前端】專欄訪問 ??

參考

  • [1]. threejs.org

本文作者:dragonir 本文地址:https://www.cnblogs.com/dragonir/p/17263717.html

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/548380.html

標籤:其他

上一篇:我為什么推薦Nuxt3

下一篇:聊聊前端性能指標那些事兒

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more