[英]Draw dimension lines along with 3D cube using Three.js
我們可以用Cube繪制“線條”以在運行時顯示“尺寸”嗎?
以下是我創建多維數據集並從用戶獲取維度並在運行時更改多維數據集的方法: http : //jsfiddle.net/9Lvk61j3/
但現在我想顯示Dimension,因此用戶知道它們將會改變的長度,寬度和高度。
這是我想要做的最終結果:
這是我的代碼: HTML:
<script src="http://www.html5canvastutorials.com/libraries/three.min.js"></script>
<div id="container"></div>
<div class="inputRow clear" id="dimensionsNotRound" data-role="tooltip">
<label class="grid-8">Dimensions (pixels):</label>
<br/>
<br/>
<div> <span>Length</span>
<input class="numeric-textbox" id="inp-length" type="text" value="100">
<br/>
<br/>
</div>
<div> <span>Width</span>
<input class="numeric-textbox" id="inp-width" type="text" value="50">
<br/>
<br/>
</div>
<div> <span>Height</span>
<input class="numeric-textbox" id="inp-height" type="text" value="40">
<br/>
<br/>
</div>
<button id="btn">Click me to change the Dimensions</button>
JS
var shape = null;
//Script for 3D Box
// revolutions per second
var angularSpeed = 0.2;
var lastTime = 0;
var cube = 0;
// this function is executed on each animation frame
function animate() {
// update
var time = (new Date()).getTime();
var timeDiff = time - lastTime;
var angleChange = angularSpeed * timeDiff * 2 * Math.PI / 1000;
//cube.rotation.y += angleChange; //Starts Rotating Object
lastTime = time;
// render
renderer.render(scene, camera);
// request new frame
requestAnimationFrame(function () {
animate();
});
}
// renderer
var container = document.getElementById("container");
var renderer = new THREE.WebGLRenderer();
renderer.setSize(container.offsetWidth, container.offsetHeight - 4);
container.appendChild(renderer.domElement);
// camera
var camera = new THREE.PerspectiveCamera(60, container.offsetWidth / container.offsetHeight, 1, 1000);
camera.position.z = 800;
// scene
var scene = new THREE.Scene();
scene.remove();
// cube
cube = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1), new THREE.MeshLambertMaterial({
color: '#cccccc'
}));
cube.overdraw = true;
cube.rotation.x = Math.PI * 0.1;
cube.rotation.y = Math.PI * 0.3;
scene.add(cube);
// add subtle ambient lighting
var ambientLight = new THREE.AmbientLight(0x319ec5);
scene.add(ambientLight);
// directional lighting
var directionalLight = new THREE.DirectionalLight(0x666666);
directionalLight.position.set(1, 1, 1).normalize();
scene.add(directionalLight);
shape = cube;
// start animation
animate();
var $ = function(id) { return document.getElementById(id); };
$('btn').onclick = function() {
console.log("Button Clicked");
var width = parseInt(document.getElementById('inp-width').value * 3.779528),
height = parseInt(document.getElementById('inp-height').value * 3.779528),
length = parseInt(document.getElementById('inp-length').value * 3.779528);
console.log("length " + length + " height " + height + " width " + width);
shape.scale.x = length;
shape.scale.y = height;
shape.scale.z = width;
};
這是同樣的小提琴! http://jsfiddle.net/9Lvk61j3/
如果您需要任何其他信息,請與我們聯系。
請建議。
繪圖尺寸有點問題:
我的解決方案中解決了大多數這些問題: https : //jsfiddle.net/mmalex/j35p1fw8/
var geometry = new THREE.BoxGeometry(8.15, 0.5, 12.25);
var material = new THREE.MeshPhongMaterial({
color: 0x09f9f9,
transparent: true,
opacity: 0.75
});
var cube = new THREE.Mesh(geometry, material);
cube.geometry.computeBoundingBox ();
root.add(cube);
var bbox = cube.geometry.boundingBox;
var dim = new LinearDimension(document.body, renderer, camera);
// define start and end point of dimension
var from = new THREE.Vector3(bbox.min.x, bbox.min.y, bbox.min.z);
var to = new THREE.Vector3(bbox.max.x, bbox.min.y, bbox.max.z);
// in which direction to "extrude" dimension away from object
var direction = new THREE.Vector3(0, 0, 1);
// request LinearDimension to create threejs node
var newDimension = dim.create(from, to, direction);
// make it cube child
cube.add(newDimension);
var animate = function() {
requestAnimationFrame(animate);
// we need to reposition dimension label on each camera change
dim.update(camera);
renderer.render(scene, camera);
};
我們現在看看輔助課程。
✔尺寸線僅在攝像機角度不太銳利(超過45°)時可見,
class FacingCamera
會讓你知道世界飛機,這是最好的相機。 隱藏尺寸的有用,這些尺寸面向攝像機,角度太尖銳(銳角)。
可以在這里找到與class FacingCamera
分開的小提琴: https : class FacingCamera
class FacingCamera {
constructor() {
// camera looking direction will be saved here
this.dirVector = new THREE.Vector3();
// all world directions
this.dirs = [
new THREE.Vector3(+1, 0, 0),
new THREE.Vector3(-1, 0, 0),
new THREE.Vector3(0, +1, 0),
new THREE.Vector3(0, -1, 0),
new THREE.Vector3(0, 0, +1),
new THREE.Vector3(0, 0, -1)
];
// index of best facing direction will be saved here
this.facingDirs = [];
this.bestFacingDir = undefined;
// TODO: add other facing directions too
// event listeners are collected here
this.cb = {
facingDirChange: []
};
}
check(camera) {
camera.getWorldDirection(this.dirVector);
this.dirVector.negate();
var maxk = 0;
var maxdot = -1e19;
var oldFacingDirs = this.facingDirs;
var facingDirsChanged = false;
this.facingDirs = [];
for (var k = 0; k < this.dirs.length; k++) {
var dot = this.dirs[k].dot(this.dirVector);
var angle = Math.acos(dot);
if (angle > -Math.PI / 2 && angle < Math.PI / 2) {
this.facingDirs.push(k);
if (oldFacingDirs.indexOf(k) === -1) {
facingDirsChanged = true;
}
if (Math.abs(dot) > maxdot) {
maxdot = dot;
maxk = k;
}
}
}
// and if facing direction changed, notify subscribers
if (maxk !== this.bestFacingDir || facingDirsChanged) {
var prevDir = this.bestFacingDir;
this.bestFacingDir = maxk;
for (var i = 0; i < this.cb.facingDirChange.length; i++) {
this.cb.facingDirChange[i]({
before: {
facing: oldFacingDirs,
best: prevDir
},
current: {
facing: this.facingDirs,
best: this.bestFacingDir
}
}, this);
}
}
}
}
✔尺寸文本是HTML元素,使用CSS設置樣式並使用three.js光線投射邏輯定位。
class LinearDimension
使用箭頭和文本標簽創建線性尺寸的實例,並對其進行控制。
LinearDimension完整實現:
class LinearDimension {
constructor(domRoot, renderer, camera) {
this.domRoot = domRoot;
this.renderer = renderer;
this.camera = camera;
this.cb = {
onChange: []
};
this.config = {
headLength: 0.5,
headWidth: 0.35,
units: "mm",
unitsConverter: function(v) {
return v;
}
};
}
create(p0, p1, extrude) {
this.from = p0;
this.to = p1;
this.extrude = extrude;
this.node = new THREE.Object3D();
this.hidden = undefined;
let el = document.createElement("div");
el.id = this.node.id;
el.classList.add("dim");
el.style.left = "100px";
el.style.top = "100px";
el.innerHTML = "";
this.domRoot.appendChild(el);
this.domElement = el;
this.update(this.camera);
return this.node;
}
update(camera) {
this.camera = camera;
// re-create arrow
this.node.children.length = 0;
let p0 = this.from;
let p1 = this.to;
let extrude = this.extrude;
var pmin, pmax;
if (extrude.x >= 0 && extrude.y >= 0 && extrude.z >= 0) {
pmax = new THREE.Vector3(
extrude.x + Math.max(p0.x, p1.x),
extrude.y + Math.max(p0.y, p1.y),
extrude.z + Math.max(p0.z, p1.z));
pmin = new THREE.Vector3(
extrude.x < 1e-16 ? extrude.x + Math.min(p0.x, p1.x) : pmax.x,
extrude.y < 1e-16 ? extrude.y + Math.min(p0.y, p1.y) : pmax.y,
extrude.z < 1e-16 ? extrude.z + Math.min(p0.z, p1.z) : pmax.z);
} else if (extrude.x <= 0 && extrude.y <= 0 && extrude.z <= 0) {
pmax = new THREE.Vector3(
extrude.x + Math.min(p0.x, p1.x),
extrude.y + Math.min(p0.y, p1.y),
extrude.z + Math.min(p0.z, p1.z));
pmin = new THREE.Vector3(
extrude.x > -1e-16 ? extrude.x + Math.max(p0.x, p1.x) : pmax.x,
extrude.y > -1e-16 ? extrude.y + Math.max(p0.y, p1.y) : pmax.y,
extrude.z > -1e-16 ? extrude.z + Math.max(p0.z, p1.z) : pmax.z);
}
var origin = pmax.clone().add(pmin).multiplyScalar(0.5);
var dir = pmax.clone().sub(pmin);
dir.normalize();
var length = pmax.distanceTo(pmin) / 2;
var hex = 0x0;
var arrowHelper0 = new THREE.ArrowHelper(dir, origin, length, hex, this.config.headLength, this.config.headWidth);
this.node.add(arrowHelper0);
dir.negate();
var arrowHelper1 = new THREE.ArrowHelper(dir, origin, length, hex, this.config.headLength, this.config.headWidth);
this.node.add(arrowHelper1);
// reposition label
if (this.domElement !== undefined) {
let textPos = origin.project(this.camera);
let clientX = this.renderer.domElement.offsetWidth * (textPos.x + 1) / 2 - this.config.headLength + this.renderer.domElement.offsetLeft;
let clientY = -this.renderer.domElement.offsetHeight * (textPos.y - 1) / 2 - this.config.headLength + this.renderer.domElement.offsetTop;
let dimWidth = this.domElement.offsetWidth;
let dimHeight = this.domElement.offsetHeight;
this.domElement.style.left = `${clientX - dimWidth/2}px`;
this.domElement.style.top = `${clientY - dimHeight/2}px`;
this.domElement.innerHTML = `${this.config.unitsConverter(pmin.distanceTo(pmax)).toFixed(2)}${this.config.units}`;
}
}
detach() {
if (this.node && this.node.parent) {
this.node.parent.remove(this.node);
}
if (this.domElement !== undefined) {
this.domRoot.removeChild(this.domElement);
this.domElement = undefined;
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.