请参阅我之前的问题here,以参考我要实现的目标
TL; DR:
我正在尝试使HTML元素与<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg version="1.1" id="mySVG" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" xml:space="preserve" viewBox="0 0 1425.1 5483.3">
<style type="text/css">
.st0{fill:none;stroke:#292929;stroke-width:2;stroke-linecap:square;stroke-miterlimit:10;stroke-dasharray:10,7;}
.st1{fill:none;}
.st2{fill:none;stroke:url(#SVGID_1_);stroke-width:2;stroke-miterlimit:10;}
.st3{fill:none;stroke:url(#SVGID_2_);stroke-width:2;stroke-miterlimit:10;stroke-dasharray:9.3333,6.5333;}
.st4{fill:none;stroke:url(#SVGID_3_);stroke-width:2;stroke-miterlimit:10;}
.st5{fill-rule:evenodd;clip-rule:evenodd;fill:url(#SVGID_4_);}
.st6{fill-rule:evenodd;clip-rule:evenodd;fill:url(#SVGID_5_);}
.st7{fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:10;}
.st8{fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:10;stroke-dasharray:10.4762,7.3333;}
</style>
<path class="st0" id="path1" d="M635.5,152.3V1072l177.7-0.4c0,0,34.5-3.8,64.6,21.4c0,0,18.4,12.7,29.8,41.7c0,0,7.5,15.6,5.8,49.5v290.4c0,0-0.8,34.5,5.8,46c0,0,10.2,29,28.3,41.8c0,0,19.5,21.6,62.1,25.1h20.7l479.6,0.1v861h-478.2c0,0-60-8.7-95.8,35.1c0,0-22.6,23.1-22.6,64.5v322.4l0.1,200.9c0,0,1.6,33.1,14.2,51.8c0,0,11.1,25.5,46.1,46.9c0,0,20.5,12.7,51.2,15.1l105.2,0.2c0,0,36.2,2.3,65.2-15.6c0,0,41.9-23.6,53.1-60.3c0,0,11.5-22.9,8.9-70.6l-0.4-153.2c0,0-0.9-32.2-23.1-59.2c0,0-21-28.7-56.4-38.1c0,0-20.2-6.3-46.3-4.3H754.8H635.5v606h295c0,0,47.7-3.1,92.9,35.5c0,0,27,22.3,38.2,56.4c0,0,10,15.3,7.9,64.8v194.5v186.4v77.6c0,0,0.5,44.2-12.4,71.9c0,0-17.2,45.5-42.9,67.8c0,0-27.8,31.4-87.6,51.3l-119.1,55.9c0,0-39.3,13.7-64.5,59c0,0-18.2,26.9-21.9,68.2c0,0-0.7,19-0.7,32.1l-0.6,284.1l-0.2,74.5c0,0-0.8,26.4,13.3,46.2c0,0,18.9,29,52.9,34.6c0,0,18.4,1.2,37.1,1.2h252.4h188.4c0,0,29.9-0.4,49.6-17.2c0,0,30-24.2,30.2-57.4l0-140.1c0,0-1.9-30-17.8-44.9c0,0-19.9-27.7-59.1-29.4l-254.8-0.1H802.1c0,0-43-1.1-66.9,33.9c0,0-17.5,21.6-15.7,56.9"/>
<path class="st0" id="path2" d="M915.5,150c0,0-0.7,52.5-9.6,73.4c0,0-22.2,83.3-75.3,131.8c0,0-44.4,51.3-125.9,75.4c0,0-33.9,10.3-77,11.8l-385,0.1c0,0-50.4-3.9-94,22.5c0,0-32.5,15.5-62.2,63.4c0,0-22.6,37.4-20.9,82.5v286.9V1578v325.4v135.2c0,0-3.5,35.2,23.2,59.1c0,0,16.1,17.9,45.3,20.6c0,0,31.5,0.3,35.7,0.3h306.4h301.2h33.9c0,0,25.2,3,54.3-16.4c0,0,29.4-18.7,37.4-53.9c0,0,4.1-14,2.8-52.8v-184.7v-187.3c0,0,1.7-39.2-14.1-62.9c0,0-18.1-33.4-54-47.2c0,0-19.7-10.2-65.1-7.8H381.5H-29.8v2363h224.1h507.9H1101c0,0,109.3,12.4,167-45.7c0,0,42.1-35.8,56.8-88c0,0,10.6-19.8,7.7-95.7v-137.6c0,0-0.4-50.3,27.5-80.9c0,0,24.8-32.8,67.1-43.9c0,0,21.8-6.4,56.1-4.2h218.8"/>
<polyline class="st1" points="-7.5,5248.7 1432.6,5248.7 1432.6,234.7 -7.5,234.7 "/>
<polyline class="st1" points="-3299.4,5248.7 -1859.3,5248.7 -1859.3,234.7 -3299.4,234.7 "/>
<g class="lineactive" id="lineactive">
<g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="41.558" y1="32.0825" x2="19.692" y2="37.9415">
<stop offset="0" style="stop-color:#292929"/>
<stop offset="0.4124" style="stop-color:#0777D0"/>
<stop offset="0.539" style="stop-color:#68E0BE"/>
<stop offset="1" style="stop-color:#292929"/>
</linearGradient>
<line class="st2" x1="40" y1="30" x2="40" y2="35"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="51.3413" y1="68.5944" x2="29.4753" y2="74.4534">
<stop offset="0" style="stop-color:#292929"/>
<stop offset="0.4124" style="stop-color:#0777D0"/>
<stop offset="0.539" style="stop-color:#68E0BE"/>
<stop offset="1" style="stop-color:#292929"/>
</linearGradient>
<line class="st3" x1="40" y1="41.5" x2="40" y2="101.7"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="60.308" y1="102.0585" x2="38.442" y2="107.9175">
<stop offset="0" style="stop-color:#292929"/>
<stop offset="0.4124" style="stop-color:#0777D0"/>
<stop offset="0.539" style="stop-color:#68E0BE"/>
<stop offset="1" style="stop-color:#292929"/>
</linearGradient>
<line class="st4" x1="40" y1="105" x2="40" y2="110"/>
</g>
</g>
<g transform="translate(34 65)" class="lineactive" id="lineactive2">
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-454.75" y1="470.8333" x2="-453.75" y2="470.8333" gradientTransform="matrix(12 0 0 -12 5457 5656)">
<stop offset="0" style="stop-color:#EEF8FF"/>
<stop offset="1" style="stop-color:#68E0BE"/>
</linearGradient>
<circle class="st5" cx="6" cy="6" r="6"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="-454.7299" y1="471.3137" x2="-453.9361" y2="470.5191" gradientTransform="matrix(12 0 0 -12 5457 5656)">
<stop offset="0" style="stop-color:#0777D0"/>
<stop offset="1" style="stop-color:#68E0BE"/>
</linearGradient>
<circle class="st6" cx="6" cy="6" r="6"/>
</g>
<g class="lineactive" id="lineactive3">
<g>
<line class="st7" x1="79.9" y1="-0.1" x2="79.9" y2="4.9"/>
<line class="st8" x1="79.9" y1="12.3" x2="79.9" y2="133.3"/>
<line class="st7" x1="79.9" y1="136.9" x2="79.9" y2="141.9"/>
</g>
</g>
<g class="lineactive" id="lineactive4">
<g>
<line class="st7" x1="1.2" y1="0" x2="1.2" y2="5"/>
<line class="st8" x1="1.2" y1="12.3" x2="1.2" y2="133.3"/>
<line class="st7" x1="1.2" y1="137" x2="1.2" y2="142"/>
</g>
</g>
</svg>
一起旋转,以使这些HTML元素似乎卡在地球上并随其移动。 (考虑某些国家/地区上方3D地球上的地图标记)
我使用THREE.js OrbitControls
几乎成功地做到了这一点,并且能够通过纬度/经度计算将HTML元素固定在3D地球仪上的某个位置,并在{{ 1}}。
问题
我唯一遇到的问题是HTML元素的缩放比例与它们离相机的距离有多远。通常,我认为这是理想的效果,有助于感觉更近/更远,但是缩放导致我无法正确且一致地调整HTML元素的大小,并且还导致元素内的文本和SVG模糊/变得像素化
我想要的
我正在寻找一种关闭这种缩放的方法,以便HTML元素仍然可以其他方式进行变换,但是无论它们在何处都保持相同的大小(即scale(1、1、1)或它们的原始缩放)在CSS3DRenderer
创建的3D渲染器中。
我认为我必须为此编辑CSS3DRenderer.js代码,但是我绝对不知道从哪里开始,而且在其他任何地方都找不到任何信息。
谢谢。
我的一些代码:
创建OrbitControls
CSS3DRenderer
调整大小功能(在窗口调整大小事件上调用)
CSS3DRenderer
从HTML中的//CSS3D Renderer
rendererHTML = new THREE.CSS3DRenderer();
rendererHTML.setSize(WIDTH, HEIGHT);
rendererHTML.domElement.classList.add('CSS3D-container');
containerHTML = document.querySelector('.globe__container');
containerHTML.appendChild(rendererHTML.domElement);
元素创建CSS3DSprite对象,并设置其在地球上的初始位置
HEIGHT = sizeControlElem.getBoundingClientRect().width;
WIDTH = sizeControlElem.getBoundingClientRect().width;
renderer.setSize(WIDTH, HEIGHT);
rendererHTML.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
您可以在问题here
中看到更多我的代码答案 0 :(得分:0)
唯一停止缩放的方法是使用Vector3.project()
方法将3D位置投影到2D。看一下下面的代码示例,我评论了JavaScript代码中的关键点,但是快速的解释是:
vector.project(camera)
将3D点转换为2D坐标。奖金:您仍然可以使用2D矢量的.z
属性来确定它是否在相机的视锥范围内。
var camera, controls, scene, renderer;
// This array will hold all positions in 3D space
var posArray3D = [];
// This array will hold all hotspot DIVs
var divArray = [];
// Create temp vector to reuse on loops
var tempVec = new THREE.Vector3();
init();
animate();
function init() {
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xcccccc );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 3000 );
camera.position.set( 400, 200, 0 );
// controls
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.enableDamping = true;
controls.dampingFactor = 0.25;
controls.screenSpacePanning = false;
controls.minDistance = 100;
controls.maxDistance = 500;
controls.maxPolarAngle = Math.PI / 2;
// world
var geometry = new THREE.CylinderBufferGeometry( 0, 10, 30, 4, 1 );
var material = new THREE.MeshPhongMaterial( { color: 0xffffff, flatShading: true } );
// This is where all hotspot DIVs will go
var hotspotBox = document.getElementById("hotspotBox");
for ( var i = 0; i < 100; i ++ ) {
var mesh = new THREE.Mesh( geometry, material );
mesh.position.x = Math.random() * 1600 - 800;
mesh.position.y = 0;
mesh.position.z = Math.random() * 1600 - 800;
mesh.updateMatrix();
mesh.matrixAutoUpdate = false;
scene.add( mesh );
// Populate array of 3D positions
posArray3D.push(mesh.position);
// Create 'hotspot' DIV, and place within 'hotspotBox' holder
divArray.push(document.createElement("div"));
divArray[i].classList.add("hotspot");
hotspotBox.appendChild(divArray[i]);
}
// lights
var light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 1, 1, 1 );
scene.add( light );
var light = new THREE.DirectionalLight( 0x002288 );
light.position.set( - 1, - 1, - 1 );
scene.add( light );
var light = new THREE.AmbientLight( 0x222222 );
scene.add( light );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
// Loops through all divs and updates their positions based on the camera
function updateDivs() {
var vectorScreen = new THREE.Vector3();
// Loop through all positions
for (var i = 0; i < posArray3D.length; i ++) {
vectorScreen.copy(worldToScreen(posArray3D[i], camera));
// Update CSS attributes of each DIV
divArray[i].style.transform = "translate(" + vectorScreen.x + "px, " + vectorScreen.y + "px)";
// Checks for depth, hides if it's behind the camera
if(vectorScreen.z <= 1) {
divArray[i].style.display = "block";
} else {
divArray[i].style.display = "none";
}
}
}
// Projects 3D coordinates into 2D space
function worldToScreen(_position, _cam) {
tempVec.copy(_position);
tempVec.project(_cam);
// Converts range from [-1, 1] to [0, windowWidth]
tempVec.x = ( tempVec.x + 1 ) * window.innerWidth / 2;
tempVec.y = ( - tempVec.y + 1 ) * window.innerHeight / 2;
return tempVec;
}
function animate() {
requestAnimationFrame( animate );
controls.update();
updateDivs();
render();
}
function render() {
renderer.render( scene, camera );
}
body {
color: #000;
font-family:Monospace;
font-size:13px;
text-align:center;
font-weight: bold;
background-color: #fff;
margin: 0px;
overflow: hidden;
}
/*hotspotBox holds all .hotspots It's placed on top of WebGL canvas*/
#hotspotBox{
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
border: 1px dashed #f90;
pointer-events: none;
}
/*100 hotspots to be placed within #hotspotBox */
.hotspot {
background: #f90;
width: 10px;
height: 10px;
border-radius: 5px;
position: absolute;
cursor: pointer;
pointer-events: auto;
}
<div id="hotspotBox"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/99/three.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>
答案 1 :(得分:0)
事实证明,对我的问题最简单的解决方案是仅使用CSS2DRenderer
而不是CSS3DRenderer
。
它实际上具有相同的作用,但仅使用translate
转换HTML元素,而不转换rotate
或scale
,这意味着您可以使用来自由修改HTML元素的大小CSS宽度和大小等...这就是我想要做的。
它的实现方式完全相同,我唯一需要更改的代码就是将CSS3DSprite
替换为CSS2DObject
。
详细了解CSS2DRenderer
here。