我試圖渲染一個THREE.js場景+一些使用html2canvas.js重疊的HTML元素。它工作最多次,但不是所有的時間。Three.js canvas.toDataURL有時爲空
在失敗的情況下,HTML元素呈現(背景,疊加等),但沒有別的。 THREE.js場景就好像它完全是空的,儘管它明顯有數據。我可以說,它通常對較大型號不合格,但只是在渲染之前。它確實可以在所有情況下都可以工作,但較大的型號需要大約30秒。就好像我必須給緩衝區一段時間才能穩定下來。
html2canvas按照您的預期處理THREE.js畫布 - 它只是使用drawImage
將THREE.js畫布繪製到最終由庫返回的新畫布上。
否則,我儘量保證其他什麼都忙於在畫布上,就像這個小提琴:http://jsfiddle.net/TheJim01/k6dto5sk/63/(以下js代碼)
正如你所看到的,我做了不少嘗試塊渲染循環,並且當我想捕捉場景時再執行一次渲染。但即使所有這些預防措施似乎都沒有幫助。
有沒有更好的方法從THREE.js畫布中獲取圖像?我可能會手動執行該部分,然後換出THREE.js畫布以獲取足夠長的HTML圖片以完成它的操作,然後將THREE.js畫布交換回來。我不想那樣做,所以我不渾濁DOM,如果用戶做了很多快照(圖像資源,圖像資源無處不在...)。
無論如何,這是代碼。歡迎任何想法或建議。謝謝!
var hostDiv, scene, renderer, camera, root, controls, light, shape, theta, aniLoopId, animating;
function snap() {
animating = false;
cancelAnimationFrame(aniLoopId);
renderer.render(scene, camera);
// html2canvas version:
/*
var element = document.getElementById('scenePlusOverlays');
// the input buttons represent my overlays
html2canvas(element, function(canvas) {
// I'd convert the returned canvas to a PNG
animating = true;
animate();
});
*/
// This is basically what html2canvas does with the THREE.js canvas.
var c = document.getElementById('rendererCanvas');
var toC = document.createElement('canvas');
toC.width = c.width;
toC.height = c.height;
var toCtx = toC.getContext('2d');
toCtx.drawImage(c, 0, 0);
console.log(toC.toDataURL('image/png'));
animating = true;
animate();
}
function addGeometry() {
//var geo = new THREE.BoxGeometry(1, 1, 1);
var geo = new THREE.SphereGeometry(5, 32, 32);
var beo = new THREE.BufferGeometry().fromGeometry(geo);
geo.dispose();
geo = null;
var mat = new THREE.MeshPhongMaterial({color:'red'});
var msh;
var count = 10;
count /= 2;
var i = 20;
var topLayer = new THREE.Object3D();
var zLayer, xLayer, yLayer;
for(var Z = -count; Z < count; Z++){
zLayer = new THREE.Object3D();
for(var X = -count; X < count; X++){
xLayer = new THREE.Object3D();
for(var Y = -count; Y < count; Y++){
yLayer = new THREE.Object3D();
msh = new THREE.Mesh(beo, mat);
yLayer.add(msh);
msh.position.set((X*i)+(i/2), (Y*i)+(i/2), (Z*i)+(i/2));
xLayer.add(yLayer);
}
zLayer.add(xLayer);
}
topLayer.add(zLayer);
}
scene.add(topLayer);
}
var WIDTH = '500';//window.innerWidth,
HEIGHT = '500';//window.innerHeight,
FOV = 35,
NEAR = 0.1,
FAR = 10000;
function init() {
hostDiv = document.getElementById('hostDiv');
document.body.insertBefore(hostDiv, document.body.firstElementChild);
renderer = new THREE.WebGLRenderer({ antialias: true, preserverDrawingBuffer: true });
renderer.setSize(WIDTH, HEIGHT);
renderer.domElement.setAttribute('id', 'rendererCanvas');
hostDiv.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(FOV, WIDTH/HEIGHT, NEAR, FAR);
camera.position.z = 500;
controls = new THREE.TrackballControls(camera, renderer.domElement);
light = new THREE.PointLight(0xffffff, 1, Infinity);
light.position.copy(camera.position);
scene = new THREE.Scene();
scene.add(camera);
scene.add(light);
animating = true;
animate();
}
function animate() {
if(animating){
light.position.copy(camera.position);
aniLoopId = requestAnimationFrame(animate);
}
renderer.render(scene, camera);
controls.update();
}
編輯: 調用readPixels或toDataURL中描述的方式是可能的 - 我曾考慮類似的方法來獲取緩衝器,但被的異步代碼所需的時間量推遲。事情是這樣的:
var global_callback = null;
function snapshot_method() {
global_callback = function(returned_image) {
// do something with the image
}
}
// ...
function render() {
renderer.render();
if(global_callback !== null) {
global_callback(renderer.domElement.toDataURL());
global_callback = null;
}
}
我認爲你有一個錯字......'preserverDrawingBuffer'應該是'preserveDrawingBuffer'。這是否解決了這個問題? – caseygrun 2014-10-20 00:04:30
你是對的。我現在一定在我的模板代碼中有這麼多年了......我跑了一些快速壓力測試,看起來錯字是造成這個問題的原因。我很驚訝,甚至在一段時間內工作!如果您將評論添加爲答案,我會接受它。 – TheJim01 2014-10-20 21:11:31