分为两个部分,html部分和js引入部分,自己感兴趣也可以去three.js官网看,都有源码
three.js gitHub库地址:https://github.com/mrdoob/three.js
three.js 官网 Three.js中文网
html部分:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>css3d</title>
<meta
name="viewport"
content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"
/>
<style>
body {
background-color: #000000;
margin: 0;
cursor: move;
overflow: hidden;
}
a {
color: #ffffff;
}
· #info {
position: absolute;
width: 100%;
color: #ffffff;
padding: 5px;
font-family: Monospace;
font-size: 13px;
font-weight: bold;
text-align: center;
z-index: 1;
}
</style>
</head>
<body>
<script src="./three.js"></script>
<script src="./CSS3DRenderer.js"></script>
<script>
//定义相机,场景,渲染器,是3D场景形成的三大要素
var camera, scene, renderer;
//定义几何体,材质,以及几何体加材质之后形成的网格
var geometry, material, mesh;
//生成三维向量(0,0,0),相机的目标点
var target = new THREE.Vector3();
//lon 经度 竖着的 有东经 西经 ;lat 维度 横着的 有南纬 北纬
//该经纬表示相机的聚焦点,初始状态在前面
var lon = 90,
lat = 0;
//同样是相机的聚焦点,上面是角度,此处转化为弧度制
var phi = 0,
theta = 0;
//移动端用户输入的x,y
var touchX, touchY;
init();
animate();
function init() {
//相机的默认位置在坐标系的原点
camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
1,
1000
);
//创建场景
scene = new THREE.Scene();
//右手坐标系,z朝向观察者,即相机。下面是将六个面拼接成立方体,分别对应
//这里的图片可以krpano 或则 pano2vr工具生成6张图
var sides = [
{
url: "http://inews.gtimg.com/newsapp_match/0/10974602313/0.jpg", //右侧
position: [-512, 0, 0],
rotation: [0, Math.PI / 2, 0],
},
{
url: "http://inews.gtimg.com/newsapp_match/0/10974602313/0.jpg", //左侧
position: [512, 0, 0],
rotation: [0, -Math.PI / 2, 0],
},
{
url: "http://inews.gtimg.com/newsapp_match/0/10974602313/0.jpg", //上侧
position: [0, 512, 0],
rotation: [Math.PI / 2, 0, Math.PI],
},
{
url: "http://inews.gtimg.com/newsapp_match/0/10974602313/0.jpg", //下侧
position: [0, -512, 0],
rotation: [-Math.PI / 2, 0, Math.PI],
},
{
url: "http://inews.gtimg.com/newsapp_match/0/10974602313/0.jpg", //前
position: [0, 0, 512],
rotation: [0, Math.PI, 0],
},
{
url: "http://inews.gtimg.com/newsapp_match/0/10974602313/0.jpg", //后
position: [0, 0, -512],
rotation: [0, 0, 0],
},
];
//将六个图片添加到场景中
for (var i = 0; i < sides.length; i++) {
var side = sides[i];
var element = document.createElement("img");
element.width = 1026; // 2 pixels extra to close the gap.
element.src = side.url;
//CSS3DObject 是拓展出去的方法,原型是object3D,见CSS3DRenderer.js
var object = new THREE.CSS3DObject(element);
object.position.fromArray(side.position);
object.rotation.fromArray(side.rotation);
scene.add(object);
}
//渲染器也是拓展出来的方法,见CSS3DRenderer.js
renderer = new THREE.CSS3DRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
//添加鼠标,手势,窗口事件
document.addEventListener("mousedown", onDocumentMouseDown, false);
document.addEventListener("wheel", onDocumentMouseWheel, false);
document.addEventListener("touchstart", onDocumentTouchStart, false);
document.addEventListener("touchmove", onDocumentTouchMove, false);
window.addEventListener("resize", onWindowResize, false);
}
function onWindowResize() {
//窗口缩放的时候,保证场景也跟随着一起缩放
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function onDocumentMouseDown(event) {
event.preventDefault();
//保证监听拖拽事件
document.addEventListener("mousemove", onDocumentMouseMove, false);
document.addEventListener("mouseup", onDocumentMouseUp, false);
}
function onDocumentMouseMove(event) {
//鼠标的移动距离 currentEvent.movementX = currentEvent.screenX - previousEvent.screenX
var movementX =
event.movementX || event.mozMovementX || event.webkitMovementX || 0;
var movementY =
event.movementY || event.mozMovementY || event.webkitMovementY || 0;
lon -= movementX * 0.1;
lat += movementY * 0.1;
}
function onDocumentMouseUp(event) {
//保证监听拖拽事件
document.removeEventListener("mousemove", onDocumentMouseMove);
document.removeEventListener("mouseup", onDocumentMouseUp);
}
function onDocumentMouseWheel(event) {
//相机的视觉随着鼠标滚动的距离拉进或者远离
var fov = camera.fov + event.deltaY * 0.05;
camera.fov = THREE.Math.clamp(fov, 10, 75);
camera.updateProjectionMatrix();
}
function onDocumentTouchStart(event) {
event.preventDefault();
//移动端没有movement,所以直接用touchX touchY去计算移动的距离
var touch = event.touches[0];
touchX = touch.screenX;
touchY = touch.screenY;
}
function onDocumentTouchMove(event) {
event.preventDefault();
var touch = event.touches[0];
lon -= (touch.screenX - touchX) * 0.1;
lat += (touch.screenY - touchY) * 0.1;
touchX = touch.screenX;
touchY = touch.screenY;
}
//开启动画
function animate() {
requestAnimationFrame(animate);
//自动由左向右横向预览全景
//lon += 0.1;
lat = Math.max(-85, Math.min(85, lat));
phi = THREE.Math.degToRad(90 - lat); //角度转为弧度制
theta = THREE.Math.degToRad(lon);
//在球坐标系中算出相机的聚焦点的坐标
target.x = Math.sin(phi) * Math.cos(theta);
target.y = Math.cos(phi);
target.z = Math.sin(phi) * Math.sin(theta);
camera.lookAt(target);
renderer.render(scene, camera);
}
</script>
</body>
</html>
js引入文件部分:
three.js可以自己到官网找一下,内容太多,就不贴出来了
CSS3DRenderer.js内容如下:
(function () {
const _position = new THREE.Vector3();
const _quaternion = new THREE.Quaternion();
const _scale = new THREE.Vector3();
class CSS3DObject extends THREE.Object3D {
constructor(element = document.createElement("div")) {
super();
this.element = element;
this.element.style.position = "absolute";
this.element.style.pointerEvents = "auto";
this.element.style.userSelect = "none";
this.element.setAttribute("draggable", false);
this.addEventListener("removed", function () {
this.traverse(function (object) {
if (
object.element instanceof Element &&
object.element.parentNode !== null
) {
object.element.parentNode.removeChild(object.element);
}
});
});
}
copy(source, recursive) {
super.copy(source, recursive);
this.element = source.element.cloneNode(true);
return this;
}
}
CSS3DObject.prototype.isCSS3DObject = true;
class CSS3DSprite extends CSS3DObject {
constructor(element) {
super(element);
this.rotation2D = 0;
}
copy(source, recursive) {
super.copy(source, recursive);
this.rotation2D = source.rotation2D;
return this;
}
}
CSS3DSprite.prototype.isCSS3DSprite = true; //
const _matrix = new THREE.Matrix4();
const _matrix2 = new THREE.Matrix4();
class CSS3DRenderer {
constructor(parameters = {}) {
const _this = this;
let _width, _height;
let _widthHalf, _heightHalf;
const cache = {
camera: {
fov: 0,
style: "",
},
objects: new WeakMap(),
};
const domElement =
parameters.element !== undefined
? parameters.element
: document.createElement("div");
domElement.style.overflow = "hidden";
this.domElement = domElement;
const cameraElement = document.createElement("div");
cameraElement.style.transformStyle = "preserve-3d";
cameraElement.style.pointerEvents = "none";
domElement.appendChild(cameraElement);
this.getSize = function () {
return {
width: _width,
height: _height,
};
};
this.render = function (scene, camera) {
const fov = camera.projectionMatrix.elements[5] * _heightHalf;
if (cache.camera.fov !== fov) {
domElement.style.perspective = camera.isPerspectiveCamera
? fov + "px"
: "";
cache.camera.fov = fov;
}
if (scene.autoUpdate === true) scene.updateMatrixWorld();
if (camera.parent === null) camera.updateMatrixWorld();
let tx, ty;
if (camera.isOrthographicCamera) {
tx = -(camera.right + camera.left) / 2;
ty = (camera.top + camera.bottom) / 2;
}
const cameraCSSMatrix = camera.isOrthographicCamera
? "scale(" +
fov +
")" +
"translate(" +
epsilon(tx) +
"px," +
epsilon(ty) +
"px)" +
getCameraCSSMatrix(camera.matrixWorldInverse)
: "translateZ(" +
fov +
"px)" +
getCameraCSSMatrix(camera.matrixWorldInverse);
const style =
cameraCSSMatrix +
"translate(" +
_widthHalf +
"px," +
_heightHalf +
"px)";
if (cache.camera.style !== style) {
cameraElement.style.transform = style;
cache.camera.style = style;
}
renderObject(scene, scene, camera, cameraCSSMatrix);
};
this.setSize = function (width, height) {
_width = width;
_height = height;
_widthHalf = _width / 2;
_heightHalf = _height / 2;
domElement.style.width = width + "px";
domElement.style.height = height + "px";
cameraElement.style.width = width + "px";
cameraElement.style.height = height + "px";
};
function epsilon(value) {
return Math.abs(value) < 1e-10 ? 0 : value;
}
function getCameraCSSMatrix(matrix) {
const elements = matrix.elements;
return (
"matrix3d(" +
epsilon(elements[0]) +
"," +
epsilon(-elements[1]) +
"," +
epsilon(elements[2]) +
"," +
epsilon(elements[3]) +
"," +
epsilon(elements[4]) +
"," +
epsilon(-elements[5]) +
"," +
epsilon(elements[6]) +
"," +
epsilon(elements[7]) +
"," +
epsilon(elements[8]) +
"," +
epsilon(-elements[9]) +
"," +
epsilon(elements[10]) +
"," +
epsilon(elements[11]) +
"," +
epsilon(elements[12]) +
"," +
epsilon(-elements[13]) +
"," +
epsilon(elements[14]) +
"," +
epsilon(elements[15]) +
")"
);
}
function getObjectCSSMatrix(matrix) {
const elements = matrix.elements;
const matrix3d =
"matrix3d(" +
epsilon(elements[0]) +
"," +
epsilon(elements[1]) +
"," +
epsilon(elements[2]) +
"," +
epsilon(elements[3]) +
"," +
epsilon(-elements[4]) +
"," +
epsilon(-elements[5]) +
"," +
epsilon(-elements[6]) +
"," +
epsilon(-elements[7]) +
"," +
epsilon(elements[8]) +
"," +
epsilon(elements[9]) +
"," +
epsilon(elements[10]) +
"," +
epsilon(elements[11]) +
"," +
epsilon(elements[12]) +
"," +
epsilon(elements[13]) +
"," +
epsilon(elements[14]) +
"," +
epsilon(elements[15]) +
")";
return "translate(-50%,-50%)" + matrix3d;
}
function renderObject(object, scene, camera, cameraCSSMatrix) {
if (object.isCSS3DObject) {
const visible = object.visible && object.layers.test(camera.layers);
object.element.style.display = visible ? "" : "none";
if (visible) {
object.onBeforeRender(_this, scene, camera);
let style;
if (object.isCSS3DSprite) {
_matrix.copy(camera.matrixWorldInverse);
_matrix.transpose();
if (object.rotation2D !== 0)
_matrix.multiply(_matrix2.makeRotationZ(object.rotation2D));
object.matrixWorld.decompose(_position, _quaternion, _scale);
_matrix.setPosition(_position);
_matrix.scale(_scale);
_matrix.elements[3] = 0;
_matrix.elements[7] = 0;
_matrix.elements[11] = 0;
_matrix.elements[15] = 1;
style = getObjectCSSMatrix(_matrix);
} else {
style = getObjectCSSMatrix(object.matrixWorld);
}
const element = object.element;
const cachedObject = cache.objects.get(object);
if (cachedObject === undefined || cachedObject.style !== style) {
element.style.transform = style;
const objectData = {
style: style,
};
cache.objects.set(object, objectData);
}
if (element.parentNode !== cameraElement) {
cameraElement.appendChild(element);
}
object.onAfterRender(_this, scene, camera);
}
}
for (let i = 0, l = object.children.length; i < l; i++) {
renderObject(object.children[i], scene, camera, cameraCSSMatrix);
}
}
}
}
THREE.CSS3DObject = CSS3DObject;
THREE.CSS3DRenderer = CSS3DRenderer;
THREE.CSS3DSprite = CSS3DSprite;
})();
效果:
3d空间图片