javascript - 试图让 Three.js Boxplot 响应式
问题描述
我构建了一个简单的 three.js 箱线图,为每个网格(条形图)加载单独的 jpg。箱线图在桌面上看起来不错,但在移动设备上它看起来被拉伸/扭曲。有没有最好的方法来使这个响应?
为了简单起见,我将为每个网格使用一个示例公共 url。
这是我的代码:
<canvas id="threeBoxPlot"></canvas>
#threeBoxPlot {
position: absolute;
top: 10500px;
left: 100px;
width: 100%;
height: 100%;
display: block;
}
initiateThree();
function initiateThree() {
let scene, camera, renderer;
let cubeGroup;
init();
animate();
function init() {
const data = [
[49, 33, 30],
[27, 17, 13],
[9, 8, 5, 2]
]
var i = 1;
width = 500
height = 500
fov = 9
aspect = 1/5
near = .1
far = 1000
color = 0x828282
density = 0.1
loader = new THREE.TextureLoader()
scene = new THREE.Scene(); // ADDED
camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
//camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.position.set(50, 30, 50);
camera.lookAt( scene.position );
cubeGeometries = data.map(row => {
return row.map(c => {
//return new THREE.BoxGeometry( 0.2, c/max, 0.2 );
return new THREE.BoxBufferGeometry(0.2, c / 8, 0.2);
})
})
var materialArray = [];
const cubeMaterialEight = new THREE.MeshBasicMaterial({
map: new
THREE.TextureLoader().load('http://content.internetvideoarchive.com/content/photos/
1428/06000501_.jpg')
});
cubeMaterialEight.color.convertSRGBToLinear();
const cubeMaterialThree = new THREE.MeshBasicMaterial({
map: new
THREE.TextureLoader().load('http://content.internetvideoarchive.com/content/photos/
1428/06000501_.jpg')
});
cubeMaterialThree.color.convertSRGBToLinear();
const cubeMaterialTwo = new THREE.MeshBasicMaterial({
map: new
THREE.TextureLoader().load('http://content.internetvideoarchive.com/content/photos/
1428/06000501_.jpg')
});
cubeMaterialTwo.color.convertSRGBToLinear();
const cubeMaterialSeven = new THREE.MeshBasicMaterial({
map: new
THREE.TextureLoader().load('http://content.internetvideoarchive.com/content/photos/
1428/06000501_.jpg')
});
cubeMaterialSeven.color.convertSRGBToLinear();
const cubeMaterial = new THREE.MeshBasicMaterial({
map: new
THREE.TextureLoader().load('http://content.internetvideoarchive.com/content/photos/
1428/06000501_.jpg')
});
cubeMaterial.color.convertSRGBToLinear();
const cubeMaterialTen = new THREE.MeshBasicMaterial({
map: new
THREE.TextureLoader().load('http://content.internetvideoarchive.com/content/photos/
1428/06000501_.jpg')
});
cubeMaterialTen.color.convertSRGBToLinear();
const cubeMaterialNine = new THREE.MeshBasicMaterial({
map: new
THREE.TextureLoader().load('http://content.internetvideoarchive.com/content/photos/
1428/06000501_.jpg')
});
cubeMaterialNine.color.convertSRGBToLinear();
const cubeMaterialFive = new THREE.MeshBasicMaterial({
map: new
THREE.TextureLoader().load('http://content.internetvideoarchive.com/content/photos/
1428/06000501_.jpg')
});
cubeMaterialFive.color.convertSRGBToLinear();
const cubeMaterialFour = new THREE.MeshBasicMaterial({
map: new
THREE.TextureLoader().load('http://content.internetvideoarchive.com/content/photos/
1428/06000501_.jpg')
});
cubeMaterialFour.color.convertSRGBToLinear();
const cubeMaterialSix = new THREE.MeshBasicMaterial({
map: new
THREE.TextureLoader().load('http://content.internetvideoarchive.com/content/photos/
1428/06000501_.jpg')
});
cubeMaterialSix.color.convertSRGBToLinear();
materialArray.push(cubeMaterialEight, cubeMaterialThree, cubeMaterialTwo,
cubeMaterialSeven, cubeMaterial, cubeMaterialTen, cubeMaterialNine, cubeMaterialFive,
cubeMaterialFour, cubeMaterialSix);
materialIndex = -1;
const cubeMeshes = cubeGeometries.map(row => {
return row.map((cubeGeometry, index) => {
materialIndex += 1;
return new THREE.Mesh(cubeGeometry, materialArray[materialIndex]);
}
)
});
cubeGroup = new THREE.Group();
data.forEach((row, i, iarr) => {
row.forEach((d, j, jarr) => {
cubeMeshes[i][j].position.set(
i / iarr.length - 0.5,
//d/max*0.5-0.6,
d / 8 * 0.5 - 0.6,
j / jarr.length - 0.5);
//cubeMeshes[i][j].scale.set(1,4,1);
cubeGroup.add(cubeMeshes[i][j]);
})
})
const mainLight = new THREE.DirectionalLight(0xffffff, 5.0);
mainLight.position.set(10, 10, 10);
mainLight.castShadow = true;
mainLight.shadowCameraVisible = true;
mainLight.shadow.radius = 8;
const ambientLight = new THREE.HemisphereLight(0xddeeff, 0x202020, 3);
var material = new THREE.LineBasicMaterial({
color: 0x0000ff
});
scene.add(cubeGroup);
scene.add(mainLight);
scene.add(ambientLight);
scene.fog = new THREE.Fog(color, near, far);
scene.background = new THREE.Color( 0x000000 );
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.physicallyCorrectLights = true;
renderer.domElement.id = 'threeBoxPlot';
document.body.appendChild(renderer.domElement); //ADDED
}
function animate() {
requestAnimationFrame( animate );
cubeGroup.rotation.y += 0.01;
renderer.setClearColor( 0xffffff );
renderer.render( scene, camera );
}
}
解决方案
当浏览器窗口调整大小时,您应该重新计算相机的纵横比,并调整渲染器的大小。这是所有 Three.js 示例使用的标准:
window.addEventListener( 'resize', onWindowResize, false );
function onWindowResize() {
// Update camera
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
// Update renderer
renderer.setSize( window.innerWidth, window.innerHeight );
}
推荐阅读
- java - OSGi:如何正确安装分辨率答案图
>? - java - Apache Kafka-Log4j-Appender 不工作火花集群模式
- python - 如何对整数列表的一部分进行排序?
- tensorflow - 如何在 tensforflow 2.0 中替换 OutputProjectionWrapper
- php - 使用过滤器覆盖 WordPress 父主题中的部分
- python - 如何设计一个可以将用户请求引导到相关应用程序视图的结构?
- numpy - 有没有一种有效的方法可以用 numpy 或 scipy 形成这个块矩阵?
- c - 使用数组指针对结构进行排序不起作用
- c# - “菜单组件/MaterialUI/Toaster 无法检查,因为不存在”错误但确实存在
- flutter - 元素类型'List
'不能分配给列表类型'Widget'