43 Three.js自定義二維圖形THREE.ShapeGeometry
簡介
通過THREE.ShapeGeometry,你可以呼叫幾個函式來建立自己的圖形。我們可以使用線條(line)、曲線(curve)和樣條曲線(spline)建立圖形的輪廓。還可以使用THREE.Shape物件的holes屬性給這個圖形打幾個孔。
建立THREE.ShapeGeometry物件
使用THREE.Shape物件繪製完成後,需要建立THREE.ShapeGeometry幾何體,我們有兩種方式建立
- 直接例項化
var shapeGeometry = new THREE.ShapeGeometry(shapes,options);
- 直接使用shape的內建方法
makeGeometry()
var shapeGeometry = shape.makeGeometry(options);
- 參數列
屬性 | 是否必需 | 描述 |
---|---|---|
shapes | 是 | 用來建立THREE.Geometry的一個或多個THREE.Shape物件。可以傳入單個THREE.Shape物件或是一個THREE.Shape物件陣列 |
options | 否 | 還可以傳入一些選項,這些選項可以應用於使用shapes引數傳入的所有圖形。關於這些選項的解釋如下: curveSegments—此屬性確定從圖形建立的曲線的平滑程度。預設值為12。 material—這是用於為指定圖形建立的面的materialIndex屬性。當把THREE.MeshFaceMaterial和此幾何體一起使用時,materialIndex屬性決定傳入的材質中的哪些材質用於傳入的圖形的面 UVGenerator—當對材質使用紋理時,UV對映決定紋理的哪個部分用於特定的面。使用UVGenerator屬性,可以傳入自己的物件,這將為傳入的圖形穿件的面建立UV設定。 |
THREE.Shape的繪圖函式
THREE.ShapeGeometry中最重要的部分是THREE.Shape,它可以用來建立圖形。所以下面介紹用來建立THREE.Shape的繪畫函式
名稱 | 描述 |
---|---|
moveTo(x,y) | 該函式將繪圖點移動到指定的x、y座標處 |
lineTo(x,y) | 該函式從當前位置(例如由moveTo函式設定的位置)繪製一條線到指定的x和y座標處 |
quadraticCurveTo(aCPx,aCPy,x,y) | 可以使用兩種不同方式來指定曲線:使用quadraticCurveTo函式,或使用bezierCurveTo函式。兩個函式的區別在於指定曲線曲率的方法。下面展示了這兩個選項之間的區別: 對於二次曲線,我們要額外指定一個點(使用aCPx和aCPy引數),曲線僅基於該點繪製,當然還需要指定端點(x和y引數)。對於三次曲線(由bezierCurveTo函式繪製),你需要多指定兩個點才能定義曲線。起始點是路徑的當前位置。 |
bezierCurveTo(aCPx1,aCPy1,aCPx2,aCPy2,x,y) | 根據提供的引數繪製一條曲線。相關說明可以參考錢一行的內容。該曲線的繪製局域兩個定義曲線的座標(aCPx1和aCPy1,aCPx2和aCPy2)以及終點座標(x和y)。起始點是路徑的當前位置。 |
splineThru(pts) | 該函式沿著提供的座標集合pts 繪製一條光滑曲線。這個引數應該是一個THREE.Vector2物件陣列。起始點是路徑的相對位置 |
arc(aX,aY,aRadius,aStartAngle,andAngle,aClockwise) | 該函式用來畫圓(或一段圓弧)。圓弧起始於路徑的當前位置。aX和aY用來指定於當前位置的偏移量。aRadius 設定圓的大小,而aStartAngle 和aEndAngle 則用來定義圓弧要畫多長。布林屬性aClockwise 決定這段圓弧是順時針還是逆時針畫。 |
absArc(aX,aY,aRadius,aStartAngle,andAngle,aClockwise) | 參考arc 函式的描述。其位置是絕對位置,而不是相對於當前的位置 |
ellipse(aX,aY,aRadius,aStartAngle,andAngle,aClockwise) | 參考arc 函式的描述。作為補充,通過ellipse 函式,可以分別指定x軸半徑和y軸半徑 |
absEllipse(aX,aY,aRadius,aStartAngle,andAngle,aClockwise) | 參考ellipse 函式的描述。其位置是絕對位置,而不是相對於當前的位置。 |
fromPoints(vectors) | 如果給該函式傳入一個THREE.Vector2 (或THREE.Vector3 )物件陣列,Three.js 會建立一條通過提供的頂點使用直線繪製的路徑 |
holes | holes 屬性包含一個THREE.Shape物件陣列。這個陣列中的每一個物件會渲染為一個孔。關於這個屬性的一個很好的例子就是我們在本節開頭看到的例子。在那段程式碼段中,我們新增了三個THREE.Shape物件到這個陣列,一個用來渲染左邊的孔,一個用來渲染右邊的孔,還有一個渲染主要THREE.Shape物件—嘴 |
THREE.Shape建立幾何體的函式
名稱 | 描述 |
---|---|
makeGeometry(options) | 該函式從THREE.Shape 物件返回一個THREE.ShapeGeometry 物件。 |
createPointsGeometry(divisions) | 該函式將圖形轉換成一個點集。divisions 屬性定義返回點的數量。這個值越高,返回的點越多,最終的曲線也就越平滑。divisions 會分別應用到路徑的每一部分 |
createSpacedPointsGeometry(divisions) | 該函式也是講圖形轉換成一個點集,只不過這裡的divisions 是一次性應用到整個路徑 |
案例程式碼
案例檢視地址:http://www.wjceo.com/blog/threejs/2018-02-12/45.html
通過上面的方法一步一步的實現的下面的效果
注意:頂點必須按照逆時針方向繪製,才能夠實現裡面新增hole
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css">
html, body {
margin: 0;
height: 100%;
}
canvas {
display: block;
}
</style>
</head>
<body onload="draw();">
</body>
<script src="https://johnson2heng.github.io/three.js-demo/lib/three.js"></script>
<script src="https://johnson2heng.github.io/three.js-demo/lib/js/QuickHull.js"></script>
<script src="https://johnson2heng.github.io/three.js-demo/lib/js/geometries/ConvexGeometry.js"></script>
<script src="https://johnson2heng.github.io/three.js-demo/lib/js/controls/OrbitControls.js"></script>
<script src="https://johnson2heng.github.io/three.js-demo/lib/js/libs/stats.min.js"></script>
<script src="https://johnson2heng.github.io/three.js-demo/lib/js/libs/dat.gui.min.js"></script>
<script>
var renderer;
function initRender() {
renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
var camera;
function initCamera() {
camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 1, 10000);
camera.position.set(0, 0, 100);
}
var scene;
function initScene() {
scene = new THREE.Scene();
}
var light;
function initLight() {
scene.add(new THREE.AmbientLight(0x404040));
light = new THREE.DirectionalLight(0xffffff);
light.position.set(1,1,1);
scene.add(light);
}
function initModel() {
var shape = new THREE.ShapeGeometry(drawShape());
var material = new THREE.MeshPhongMaterial({color:0xff00ff});
material.side = THREE.DoubleSide;//設定成兩面都可見
var mesh = new THREE.Mesh(shape,material);
scene.add(mesh);
/*此方法是建立兩種紋理的方法
* var shape = new THREE.ShapeGeometry(drawShape());
var mesh = createMesh(shape);
scene.add(mesh);
* */
}
//生成2d圖形
function drawShape() {
// 例項化shape物件
var shape = new THREE.Shape();
// 設定開始點的位置
shape.moveTo(20, 10);
// 從起始點繪製直線到當前位置
shape.lineTo(20, 40);
//設定一條曲線到30 40
shape.bezierCurveTo(15, 25, -5, 25, -30, 40);
// 設定一條通過當前所有頂點的光滑曲線
shape.splineThru(
[new THREE.Vector2(-22, 30),
new THREE.Vector2(-18, 20),
new THREE.Vector2(-20, 10),
]);
// 設定曲線回到頂點
shape.quadraticCurveTo(0, -15, 20, 10);
// 新增第一個眼
var hole1 = new THREE.Path();
hole1.absellipse(6, 20, 2, 3, 0, Math.PI * 2, true);
shape.holes.push(hole1);
// 新增第二個眼
var hole2 = new THREE.Path();
hole2.absellipse(-10, 20, 2, 3, 0, Math.PI * 2, true);
shape.holes.push(hole2);
// 新增嘴巴,一半的圓
var hole3 = new THREE.Path();
hole3.absarc(0, 5, 2, 0, Math.PI, true);
shape.holes.push(hole3);
// 返回shape
return shape;
}
//生成模型
function createMesh(geom) {
// 建立兩個紋理
var meshMaterial = new THREE.MeshNormalMaterial();
meshMaterial.side = THREE.DoubleSide; //兩面都可見
var wireFrameMat = new THREE.MeshBasicMaterial();
wireFrameMat.wireframe = true; //開啟線框
// 建立生成模型
var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial, wireFrameMat]);
return mesh;
}
//初始化效能外掛
var stats;
function initStats() {
stats = new Stats();
document.body.appendChild(stats.dom);
}
//使用者互動外掛 滑鼠左鍵按住旋轉,右鍵按住平移,滾輪縮放
var controls;
function initControls() {
controls = new THREE.OrbitControls( camera, renderer.domElement );
// 如果使用animate方法時,將此函式刪除
//controls.addEventListener( 'change', render );
// 使動畫迴圈使用時阻尼或自轉 意思是否有慣性
controls.enableDamping = true;
//動態阻尼係數 就是滑鼠拖拽旋轉靈敏度
//controls.dampingFactor = 0.25;
//是否可以縮放
controls.enableZoom = true;
//是否自動旋轉
controls.autoRotate = false;
//設定相機距離原點的最遠距離
controls.minDistance = 20;
//設定相機距離原點的最遠距離
controls.maxDistance = 160;
//是否開啟右鍵拖拽
controls.enablePan = true;
}
function render() {
renderer.render( scene, camera );
}
//視窗變動觸發的函式
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
render();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
//更新控制器
controls.update();
render();
//更新效能外掛
stats.update();
requestAnimationFrame(animate);
}
function draw() {
initRender();
initScene();
initCamera();
initLight();
initModel();
initControls();
initStats();
animate();
window.onresize = onWindowResize;
}
</script>
</html>
相關文章
- Flutter 自定義 Widget 之餅形圖實戰Flutter
- Python自定義詞雲圖形狀和文字顏色Python
- Flink 自定義維表
- 【Android自定義View】繪圖之Path篇(二)AndroidView繪圖
- 利用Xfermode 自定義形狀ViewView
- .NET生成小程式碼,併合自定義背景圖生成推廣小程式二維碼
- 支付寶二維碼生成,自定義金額,自定義備註資訊,不限制生成數量
- Android自定義圓形進度條Android
- 【Android】自定義樹形控制元件Android控制元件
- 自定義鍵盤(二)
- [-Flutter 自定義元件-] 圓形進度條Flutter元件
- QT 自定義QGraphicsItem 縮放後旋轉 圖形出現漂移問題QT
- POI 重疊、並列柱狀圖(條形圖),顯示資料,自定義顏色
- Flutter自定義View(二)—— MultiChildRenderObejctWidgetFlutterView
- Android自定義View:View(二)AndroidView
- UICollectionView自定義佈局(二)UIView
- 自定義圓形進度條控制元件控制元件
- Android自定義View之圖片外形特效——輕鬆實現圓角和圓形圖片AndroidView特效
- 自定義View事件篇進階篇(二)-自定義NestedScrolling實戰View事件
- iOS 生成二維碼/條形碼iOS
- Vue學習(二)自定義指令Vue
- Vue富文字帶圖片修改圖片大小自定義選擇項自定義字型Vue自定義字型
- 拜託,使用Three.js讓二維圖片具有3D效果超酷的好嗎 ?JS3D
- 6.自定義圖片剪下
- uniapp自定義卡片輪播圖APP
- AUTOCAD——新增自定義填充圖案
- Spring Boot - 自定義 Banner 圖案Spring Boot
- iOS 掃描二維碼/條形碼iOS
- Win10如何自定義硬碟圖示_win10自定義硬碟圖示的教程Win10硬碟
- Java 異常(二) 自定義異常Java
- 第216天:Angular—自定義指令(二)Angular
- 安卓學習筆記31:使用自定義檢視繪製文字、圖形與影像安卓筆記
- 自定義上傳圖片拼圖遊戲遊戲
- 永宏BI 自定義繪圖(環狀圖)繪圖
- Flutter 112: 圖解自定義 ACEPieWidget 餅狀圖Flutter圖解
- three.js 製作屬於自己的動態二維碼JS
- Flutter 通過Clipper實現各種自定義形狀Flutter
- 微信、支付寶,收款二維碼實時生成,自定義金額 備註生成
- 自定義百度地圖元件地圖元件