three打造混凝土高楼林立的城市效果代码
代码语言:html
所属分类:三维
代码描述:three打造混凝土高楼林立的城市效果代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<html lang="en"><head> <meta charset="UTF-8"> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Hind:wght@400;700&display=swap"> <style> * { border: 0; box-sizing: border-box; margin: 0; padding: 0; } :root { font-size: calc(16px + (24 - 16) * (100vw - 320px) / (2560 - 320)); --bg: #737a8c; --buttonBg: #2762f3; --buttonHoverBg: #0c48db; --formBg: #fff; --inputBorder: #abafba; --inputBg: #fff; --inputDisableBg: #e3e4e8; --pColor: #17181c; } aside { background: var(--formBg); box-shadow: 0 0 0.25em hsla(223,10%,10%,0.5); border-radius: 0.375em 0.375em 0 0; position: fixed; bottom: 0; left: 1.25em; max-width: 17.5em; width: calc(100% - 2.5em); transform: translateY(100%); transition: transform 0.3s ease-in-out; } body, button, input { color: var(--pColor); font: 1em/1.5 "Hind", -apple-system, sans-serif; } body, .upload-btn { overflow: hidden; } button:hover, button:focus, .upload-btn input[type=file]:hover + button, .upload-btn input[type=file]:focus + button { background: var(--buttonHoverBg); } button, .upload-btn input[type=file], .upload-btn input[type=file]::-webkit-file-upload-button { cursor: pointer; } button, input { display: block; width: 100%; -webkit-appearance: none; -moz-appearance: none; appearance: none; } button { background: var(--buttonBg); border-radius: 0.375em; color: #fff; margin-bottom: 1.5em; padding: 0.75em 1em; transition: background 0.1s linear; } button:focus { outline: 0; } form { padding: 1.5em 1.5em 0 1.5em; position: relative; } input { background: var(--inputBg); border-radius: 0.25em; box-shadow: 0 0 0 1px var(--inputBorder) inset; padding: 0.75em; } input:disabled { background: var(--inputDisableBg); cursor: not-allowed; text-overflow: ellipsis; } label { display: inline-block; font-weight: bold; } .aside-toggle, .aside-toggle:hover, .aside-toggle:focus { background-color: var(--formBg); } .aside-toggle { border-radius: 0.375em 0.375em 0 0; margin: 0; padding: 0.25em 1em; position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%); transition: none; width: 4.5em; height: 1.5em; } .aside-toggle:before { border-left: 0.5em solid transparent; border-right: 0.5em solid transparent; border-bottom: 0.5em solid; color: var(--pColor); content: ""; display: block; position: absolute; top: 33%; left: calc(50% - 0.5em); width: 0; height: 0; transition: color 0.1s linear; } .aside-toggle:hover:before, .aside-toggle:focus:before { color: var(--buttonBg); } .aside-open { transform: translateY(0%); } .aside-open .aside-toggle:before { border-bottom: 0; border-top: 0.5em solid; } .sr { clip: rect(1px,1px,1px,1px); overflow: hidden; position: absolute; } .upload-btn, .upload-btn input[type=text], .upload-btn input[type=file] + button { margin-bottom: 0.75em; } .upload-btn { display: flex; justify-content: space-between; position: relative; } .upload-btn input[type=text] { width: calc(62.5% - 0.375em); } .upload-btn input[type=file], .upload-btn input[type=file] + button { width: calc(37.5% - 0.375em); } .upload-btn input[type=file] { position: absolute; opacity: 0; top: 0; left: 0; height: 3em; } .upload-btn input[type=file] + button svg { display: block; margin: auto; width: 1.5em; height: 1.5em; } .upload-btn input[type=file] + button path { fill: #fff; } /* Dark theme */ @media (prefers-color-scheme: dark) { :root { --formBg: #17181c; --inputBg: #2e3138; --inputDisableBg: #2e3138; --inputBorder: #5c6270; --pColor: #e3e4e8; } } </style> </head> <body><canvas width="498" height="659" style="display: block; width: 498px; height: 659px;"></canvas> <aside class="aside-open"> <form action=""> <button id="aside-btn" class="aside-toggle aside-toggle-open" type="button"> <span class="sr">Toggle Panel</span> </button> <label for="img_upload">Image</label> <div class="upload-btn"> <input id="img_upload" name="img_upload" type="file" accept="image/*"> <button for="img_upload" type="button" tabindex="-1" title="Upload"> <svg viewBox="0 0 512 512" width="24" height="24" xmlns="http://www.w3.org/2000/svg"> <path d="m182.461 155.48 49.539-49.539v262.059a24 24 0 0 0 48 0v-262.059l49.539 49.539a24 24 0 1 0 33.941-33.941l-90.509-90.51a24 24 0 0 0 -33.942 0l-90.509 90.51a24 24 0 1 0 33.941 33.941z"></path> <path d="m464 232a24 24 0 0 0 -24 24v184h-368v-184a24 24 0 0 0 -48 0v192a40 40 0 0 0 40 40h384a40 40 0 0 0 40-40v-192a24 24 0 0 0 -24-24z"></path> </svg> </button> <input id="img_name" name="img_name" type="text" placeholder="No file selected" disabled=""> </div> <button id="reset-btn" type="button">Reset</button> </form> </aside> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/three.126.js"></script> <script> window.addEventListener("DOMContentLoaded",app); THREE.OrbitControls = function ( object, domElement ) { this.object = object; this.domElement = ( domElement !== undefined ) ? domElement : document; // Set to false to disable this control this.enabled = true; // "target" sets the location of focus, where the object orbits around this.target = new THREE.Vector3(); // How far you can dolly in and out ( PerspectiveCamera only ) this.minDistance = 0; this.maxDistance = Infinity; // How far you can zoom in and out ( OrthographicCamera only ) this.minZoom = 0; this.maxZoom = Infinity; // How far you can orbit vertically, upper and lower limits. // Range is 0 to Math.PI radians. this.minPolarAngle = 0; // radians this.maxPolarAngle = Math.PI; // radians // How far you can orbit horizontally, upper and lower limits. // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ]. this.minAzimuthAngle = - Infinity; // radians this.maxAzimuthAngle = Infinity; // radians // Set to true to enable damping (inertia) // If damping is enabled, you must call controls.update() in your animation loop this.enableDamping = false; this.dampingFactor = 0.05; // This option actually enables dollying in and out; left as "zoom" for backwards compatibility. // Set to false to disable zooming this.enableZoom = true; this.zoomSpeed = 1.0; // Set to false to disable rotating this.enableRotate = true; this.rotateSpeed = 1.0; // Set to false to disable panning this.enablePan = true; this.panSpeed = 1.0; this.screenSpacePanning = false; // if true, pan in screen-space this.keyPanSpeed = 7.0; // pixels moved per arrow key push // Set to true to automatically rotate around the target // If auto-rotate is enabled, you must call controls.update() in your animation loop this.autoRotate = false; this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 // Set to false to disable use of the keys this.enableKeys = true; // The four arrow keys this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; // Mouse buttons this.mouseButtons = { LEFT: THREE.MOUSE.ROTATE, MIDDLE: THREE.MOUSE.DOLLY, RIGHT: THREE.MOUSE.PAN }; // Touch fingers this.touches = { ONE: THREE.TOUCH.ROTATE, TWO: THREE.TOUCH.DOLLY_PAN }; // for reset this.target0 = this.target.clone(); this.position0 = this.object.position.clone(); this.zoom0 = this.object.zoom; // // public methods // this.getPolarAngle = function () { return spherical.phi; }; this.getAzimuthalAngle = function () { return spherical.theta; }; this.saveState = function () { scope.target0.copy( scope.target ); scope.position0.copy( scope.object.position ); scope.zoom0 = scope.object.zoom; }; this.reset = function () { scope.target.copy( scope.target0 ); scope.object.position.copy( scope.position0 ); scope.object.zoom = scope.zoom0; scope.object.updateProjectionMatrix(); scope.dispatchEvent( changeEvent ); scope.update(); state = STATE.NONE; }; // this method is exposed, but perhaps it would be better if we can make it private... this.update = function () { var offset = new THREE.Vector3(); // so camera.up is the orbit axis var quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) ); var quatInverse = quat.clone().inverse(); var lastPosition = new THREE.Vector3(); var lastQuaternion = new THREE.Quaternion(); return function update() { var position = scope.object.position; offset.copy( position ).sub( scope.target ); // rotate offset to "y-axis-is-up" space offset.applyQuaternion( quat ); // angle from z-axis around y-axis spherical.setFromVector3( offset ); if ( scope.autoRotate && state === STATE.NONE ) { rotateLeft( getAutoRotationAngle() ); } if ( scope.enableDamping ) { spherical.theta += sphericalDelta.theta * scope.dampingFactor; spherical.phi += sphericalDelta.phi * scope.dampingFactor; } else { spherical.theta += sphericalDelta.theta; spherical.phi += sphericalDelta.phi; } // restrict theta to be between desired limits spherical.theta = Math.max( scope.minAzimuthAngle, Math.min( scope.maxAzimuthAngle, spherical.theta ) ); // restrict phi to be between desired limits spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) ); spherical.makeSafe(); spherical.radius *= scale; // restrict radius to be between desired limits spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) ); // move target to panned location if ( scope.enableDamping === true ) { scope.target.addScaledVector( panOffset, scope.dampingFactor ); } else { scope.target.add( panOffset ); } offset.setFromSpherical( spherical ); // rotate offset back to "camera-up-vector-is-up" space offset.applyQuaternion( quatInverse ); position.copy( scope.target ).add( offset ); scope.object.lookAt( scope.target ); if ( scope.enableDamping === true ) { sphericalDelta.theta *= ( 1 - scope.dampingFactor ); sphericalDelta.phi *= ( 1 - scope.dampingFactor ); panOffset.multiplyScalar( 1 - scope.dampingFactor ); } else { sphericalDelta.set( 0, 0, 0 ); panOffset.set( 0, 0, 0 ); } scale = 1; // update condition is: // min(camera displacement, camera rotation in radians)^2 > EPS // using small-angle approximation cos(x/2) = 1 - x^2 / 8 if ( zoomChanged || lastPosition.distanceToSquared( scope.object.position ) > EPS || 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) { scope.dispatchEvent( changeEvent ); lastPosition.copy( scope.object.position ); lastQuaternion.copy( scope.object.quaternion ); zoomChanged = false; return true; } return false; }; }(); this.dispose = function () { scope.domElement.removeEventListener( 'contextmenu', onContextMenu, false ); scope.domElement.removeEventListener( 'mousedown', onMouseDown, false ); scope.domElement.removeEventListener( 'wheel', onMouseWheel, false ); scope.domElement.removeEventListener( 'touchstart', onTouchStart, false ); scope.domElement.removeEventListener( 'touchend', onTouchEnd, false ); scope.domElement.removeEventListener( 'touchmove', onTouchMove, false ); document.removeEventListener( 'mousemove', onMouseMove, false ); document.removeEventListener( 'mouseup', onMouseUp, false ); window.removeEventListener( 'keydown', onKeyDown, false ); //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here? }; // // internals // var scope = this; var changeEvent = { type: 'change' }; var startEvent = { type: 'start' }; var endEvent = { type: 'end' }; var STATE = { NONE: - 1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_PAN: 4, TOUCH_DOLLY_PAN: 5, TOUCH_DOLLY_ROTATE: 6 }; var state = STATE.NONE; var EPS = 0.000001; // current position in spherical coordinates var spherical = new THREE.Spherical(); var sphericalDelta = new THREE.Spherical(); var scale = 1; var panOffset = new THREE.Vector3(); var zoomChanged = false; var rotateStart = new THREE.Vector2(); var rotateEnd = new THREE.Vector2(); var rotateDelta = new THREE.Vector2(); var panStart = new THREE.Vector2(); var panEnd = new THREE.Vector2(); var panDelta = new THREE.Vector2(); var dollyStart = new THREE.Vector2(); var dollyEnd = new THREE.Vector2(); var dollyDelta = new THREE.Vector2(); function getAutoRotationAngle() { return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; } function getZoomScale() { return Math.pow( 0.95, scope.zoomSpeed ); } function rotateLeft( angle ) { sphericalDelta.theta -= angle; } function rotateUp( angle ) { sphericalDelta.phi -= angle; } var panLeft = function () { var v = new THREE.Vector3(); return function panLeft( distance, objectMatrix ) { v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix v.multiplyScalar( - distance ); panOffset.add( v ); }; }(); var panUp = function () { var v = new THREE.Vector3(); return function panUp( distance, objectMatrix ) { if ( scope.screenSpacePanning === true ) { v.setFromMatrixColumn( objectMatrix, 1 ); } else { v.setFromMatrixColumn( objectMatrix, 0 ); v.crossVectors( scope.object.up, v ); } v.multiplyScalar( distance ); panOffset.add( v ); }; }(); // deltaX and deltaY are in pixels; right and down are positive var pan = function () { var offset = new THREE.Vector3(); return function pan( deltaX, deltaY ) { var element = scope.domElement === document ? scope.domElement.body : scope.domElement; if ( scope.object.isPerspectiveCamera ) { // perspective var position = scope.object.position; offset.copy( position ).sub( scope.target ); var targetDistance = offset.length(); // half of the fov is center to top of screen targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 ); // we use only clientHeight here so aspect ratio does not distort speed panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix ); panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix ); } else if ( scope.object.isOrthographicCamera ) { // orthographic panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix ); panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix ); } else { // camera neither orthographic nor perspective console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' ); scope.enablePan = false; } }; }(); function dollyIn( dollyScale ) { if ( scope.object.isPerspectiveCamera ) { scale /= dollyScale; } else if ( scope.object.isOrthographicCamera ) { scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) ); scope.object.updateProjectionMatrix(); zoomChanged = true; } else { console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); scope.enableZoom = false; } } function dollyOut( dollyScale ) { if ( scope.object.isPerspectiveCamera ) { scale *= dollyScale; } else if ( scope.object.isOrthographicCamera ) { scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) ); scope.object.updateProjectionMatrix(); zoomChanged = true; } else { console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); scope.enableZoom = false; } } // // event callbacks - update the object state // function handleMouseDownRotate( event ) { rotateStart.set( event.clientX, event.clientY ); } function handleMouseDownDolly( event ) { dollyStart.set( event.clientX, event.clientY ); } function handleMouseDownPan( event ) { panStart.set( event.clientX, event.clientY ); } function handleMouseMoveRotate( event ) { rotateEnd.set( event.clientX, event.clientY ); rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); var element = scope.domElement === document ? scope.domElement.body : scope.domElement; rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); rotateStart.copy( rotateEnd ); scope.update(); } function handleMouseMoveDolly( event ) { dollyEnd.set( event.clientX, event.clientY ); dollyDelta.subVectors( dollyEnd, dollyStart ); if ( dollyDelta.y > 0 ) { dollyIn( getZoomScale() ); } else if ( dollyDelta.y < 0 ) { dollyOut( getZoomScale() ); } dollyStart.copy( dollyEnd ); scope.update(); } function handleMouseMovePan( event ) { panEnd.set( event.clientX, event.clientY ); panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); pan( panDelta.x, panDelta.y ); panStart.copy( panEnd ); scope.update(); } function handleMouseUp( /*event*/ ) { // no-op } function handleMouseWheel( event ) { if ( event.deltaY < 0 ) { dollyOut( getZoomScale() ); } else if ( event.deltaY > 0 ) { dollyIn( getZoomScale() ); } scope.update(); } function handleKeyDown( event ) { var needsUpdate = false; switch ( event.keyCode ) { case scope.keys.UP: pan( 0, scope.keyPanSpeed ); needsUpdate = true; break; case scope.keys.BOTTOM: pan( 0, - scope.keyPanSpeed ); needsUpdate = true; break; case scope.keys.LEFT: pan( scope.keyPanSpeed, 0 ); needsUpdate = true; break; case scope.keys.RIGHT: pan( - scope.keyPanSpeed, 0 ); needsUpdate = true; break; } if ( needsUpdate ) { // prevent the browser from scrolling on cursor keys event.preventDefault(); scope.update(); } } function handleTouchStartRotate( event ) { if ( event.touches.length == 1 ) { rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); } else { var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); rotateStart.set( x, y ); } } function handleTouchStartPan( event ) { if ( event.touches.length == 1 ) { panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); } else { var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); panStart.set( x, y ); } } function handleTouchStartDolly( event ) { var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; var distance = Math.sqrt( dx * dx + dy * dy ); dollyStart.set( 0, distance ); } function handleTouchStartDollyPan( event ) { if ( scope.enableZoom ) handleTouchStartDolly( event ); if ( scope.enablePan ) handleTouchStartPan( event ); } function handleTouchStartDollyRotate( event ) { if ( scope.enableZoom ) handleTouchStartDolly( event ); if ( scope.enableRotate ) handleTouchStartRotate( event ); } function handleTouchMoveRotate( event ) { if ( event.touches.length == 1 ) { rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); } else { var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); rotateEnd.set( x, y ); } rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); var element = scope.domElement === document ? scope.domElement.body : scope.domElement; rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); rotateStart.copy( rotateEnd ); } function handleTouchMovePan( event ) { if ( event.touches.length == 1 ) { panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); } else { var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); panEnd.set( x, y ); } panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); pan( panDelta.x, panDelta.y ); panStart.copy( panEnd ); } function handleTouchMoveDolly( event ) { var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; var distance = Math.sqrt( dx * dx + dy * dy ); dollyEnd.set( 0, distance ); dollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) ); dollyIn( dollyDelta.y ); dollyStart.copy( dollyEnd ); } function handleTouchMoveDollyPan( event ) { if ( scope.enableZoom ) handleTouchMoveDolly( event ); if ( scope.enablePan ) handleTouchMovePan( event ); } function handleTouchMoveDollyRotate( event ) { if ( scope.enableZoom ) handleTouchMoveDolly( event ); if ( scope.enableRotate ) handleTouchMoveRotate( event ); } function handleTouchEnd( /*event*/ ) { // no-op } // // event handlers - FSM: listen for events and reset state // function onMouseDown( event ) { if ( scope.enabled === false ) return; // Prevent the browser from scrolling. event.preventDefault(); // Manually set the focus since calling preventDefault above // prevents the browser from setting it automatically. scope.domElement.focus ? scope.domElement.focus() : window.focus(); s.........完整代码请登录后点击上方下载按钮下载查看
网友评论0