Javascript 用three.js动态画一条线
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31399856/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Drawing a line with three.js dynamically
提问by user3960875
This is what I'd like to achieve (a modifiable polygon where the red circles are vertices) and I'd like to build the polygon dynamically.
这就是我想要实现的(红色圆圈是顶点的可修改多边形),我想动态构建多边形。
When initiating the geometry as
当初始化几何体时
var geometry = new THREE.Geometry();
geometry.vertices.push(point);
geometry.vertices.push(point);
var line = new THREE.Line(geometry, new THREE.LineBasicMaterial({}));
it works well until the second click, it builds a straight line between 1 and 2 but does not add a third line when it's pushed to the array. WebGL seems to require buffered points.
在第二次单击之前它运行良好,它在 1 和 2 之间构建一条直线,但在将其推送到阵列时不会添加第三条线。WebGL 似乎需要缓冲点。
When I predefine vertices like this I can draw two lines (third click)
当我像这样预定义顶点时,我可以画两条线(第三次点击)
var geometry = new THREE.Geometry();
for (var i = 0; i < 4; i++) {
geometry.vertices.push(point);
}
var line = new THREE.Line(geometry, new THREE.LineBasicMaterial({}));
but this is not a good solution as I don't know how many vertices does the user want to add and it's pointless to assign it a big number as I have to loop it multiple times.
但这不是一个好的解决方案,因为我不知道用户想要添加多少个顶点,并且分配一个大数字毫无意义,因为我必须多次循环它。
Is there any way around it?
有什么办法可以解决吗?
回答by WestLangley
You can animate a line -- or increase the number of points rendered -- very easily using BufferGeometry
and the setDrawRange()
method. You do need to set a maximum number of points, however.
您可以使用BufferGeometry
该setDrawRange()
方法非常轻松地为一条线设置动画——或增加渲染点的数量。但是,您确实需要设置最大点数。
var MAX_POINTS = 500;
// geometry
var geometry = new THREE.BufferGeometry();
// attributes
var positions = new Float32Array( MAX_POINTS * 3 ); // 3 vertices per point
geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
// draw range
drawCount = 2; // draw the first 2 points, only
geometry.setDrawRange( 0, drawCount );
// material
var material = new THREE.LineBasicMaterial( { color: 0xff0000 } );
// line
line = new THREE.Line( geometry, material );
scene.add( line );
You set the position data using a pattern like this one:
您可以使用这样的模式设置位置数据:
var positions = line.geometry.attributes.position.array;
var x = y = z = index = 0;
for ( var i = 0, l = MAX_POINTS; i < l; i ++ ) {
positions[ index ++ ] = x;
positions[ index ++ ] = y;
positions[ index ++ ] = z;
x += ( Math.random() - 0.5 ) * 30;
y += ( Math.random() - 0.5 ) * 30;
z += ( Math.random() - 0.5 ) * 30;
}
If you want to change the number of points renderedafter the first render, do this:
如果要更改第一次渲染后渲染的点数,请执行以下操作:
line.geometry.setDrawRange( 0, newValue );
If you want to change the position data valuesafter the first render, you set the needsUpdate
flag like so:
如果你想在第一次渲染后改变位置数据值,你可以needsUpdate
像这样设置标志:
line.geometry.attributes.position.needsUpdate = true; // required after the first render
Here is a fiddleshowing an animated line which you can adapt to your use case.
EDIT: See this answerfor a technique that you may like better -- especially if the line consists of only a few points.
编辑:有关您可能更喜欢的技术,请参阅此答案- 特别是如果该线仅包含几个点。
three.js r.84
三.js r.84
回答by Wilt
Draw a line in real time
实时画线
Here an updated fiddlewhere I optimized the code from user3325025his example; In this case there is absolutely no need to update all the points of the line on render. Update is only needed onMouseMove
(updating end of line) and onMouseDown
(drawing new point):
这是一个更新的小提琴,我优化了来自user3325025示例的代码;在这种情况下,绝对不需要在渲染时更新线的所有点。只需要onMouseMove
更新(更新行尾)和onMouseDown
(绘制新点):
// update line
function updateLine() {
positions[count * 3 - 3] = mouse.x;
positions[count * 3 - 2] = mouse.y;
positions[count * 3 - 1] = mouse.z;
line.geometry.attributes.position.needsUpdate = true;
}
// mouse move handler
function onMouseMove(event) {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
mouse.z = 0;
mouse.unproject(camera);
if( count !== 0 ){
updateLine();
}
}
// add point
function addPoint(event){
positions[count * 3 + 0] = mouse.x;
positions[count * 3 + 1] = mouse.y;
positions[count * 3 + 2] = mouse.z;
count++;
line.geometry.setDrawRange(0, count);
updateLine();
}
回答by user3325025
I updated the fiddle with mouse events and a vector array if you want to scribble freehand.
如果你想徒手涂鸦,我用鼠标事件和向量数组更新了小提琴。
https://jsfiddle.net/w67tzfhx/40/
https://jsfiddle.net/w67tzfhx/40/
function onMouseDown(evt) {
if(evt.which == 3) return;
var x = ( event.clientX / window.innerWidth ) * 2 - 1;
var y = - ( event.clientY / window.innerHeight ) * 2 + 1;
// do not register if right mouse button is pressed.
var vNow = new THREE.Vector3(x, y, 0);
vNow.unproject(camera);
console.log(vNow.x + " " + vNow.y+ " " + vNow.z);
splineArray.push(vNow);
document.addEventListener("mousemove",onMouseMove,false);
document.addEventListener("mouseup",onMouseUp,false);
}