博物馆html5,HTML5 在线3D博物馆/画展/艺术博览会

这篇博客深入探讨了使用JavaScript实现3D场景的渲染,包括相机视角平滑移动、墙的绘制以及图片的加载与鼠标交互。通过Babel和CoffeeScript编译,创建了一个3D环境,用户可以滚动和缩放查看不同图片墙的细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JavaScript

语言:

JaveScriptBabelCoffeeScript

确定

~ function() {

'use strict';

var over = false,

overlast = false;

var camera = {

x: 0,

y: 11100,

z: 10000,

zEye: -101,

visible: true,

zoom: function(z) {

var z0 = this.zEye - z;

if (z0 > 0) z0 = -0.1;

z0 = this.zEye / z0;

this.visible = (z > this.zEye * 0.9);

return z0;

},

ease: function(pointer) {

var xm = (canvas.centerX - pointer.x) * (250 / canvas.centerX);

var ym = (canvas.centerY - pointer.y) * (110 / canvas.centerY);

this.x += (xm - this.x) / 20;

this.y += (pointer.z - this.y) / 20;

this.z += (ym - this.z) / 20;

}

};

var Wall = function(x, y, z) {

this.x = x;

this.y = y;

this.z = z;

};

Wall.prototype.anim = function() {

ctx.beginPath();

ctx.fillStyle = '#fff';

for (var i = 0; i < 4; i++) {

var z0 = camera.zoom(camera.y + this.z[i] * 100);

ctx.lineTo(

canvas.centerX + (camera.x + this.x[i] * 100) * z0,

canvas.centerY + (camera.z + this.y[i] * 100) * z0

);

}

ctx.fill();

};

var Pict = function(img, title, text, x, y, z, w, h) {

this.x = x * 100;

this.y = y * 100;

this.z = z * 100;

this.w = w * 100;

this.h = h * 100;

this.loaded = false;

this.img = document.createElement('canvas');

this.img.width = 1000;

this.img.height = 1000;

this.srcimg = new Image();

this.srcimg.onload = function() {

var ict = this.img.getContext('2d');

ict.fillStyle = 'rgba(0,0,0,0.3)';

ict.fillRect(0, 0, 1000, 1000);

ict.drawImage(this.srcimg, 100, 100, 800, 800);

this.loaded = true;

}.bind(this);

this.srcimg.src = '/uploads/160301/' + img;

this.text = document.createElement('canvas');

this.text.width = 1000;

this.text.height = 300;

var ict = this.text.getContext('2d');

ict.font = 'bold 140px arial';

ict.fillStyle = '#ddd';

ict.textAlign = 'center';

ict.fillText(title, 500, 120);

ict.font = '48px arial';

ict.fillText(text, 500, 200);

};

Pict.prototype.isPointerInside = function(x, y, z0) {

return (

pointer.x > canvas.centerX + x &&

pointer.y > canvas.centerY + y &&

pointer.x < canvas.centerX + x + this.w * z0 &&

pointer.y < canvas.centerY + y + this.w * z0

);

}

Pict.prototype.anim = function() {

if (!this.loaded) return;

var z0 = camera.zoom(camera.y + this.z);

if (camera.visible) {

var x = (camera.x + this.x) * z0,

y = (camera.z + this.y) * z0;

if (this.isPointerInside(x, y, z0)) over = this;

ctx.drawImage(this.img,

canvas.centerX + x,

canvas.centerY + y,

this.w * z0,

this.h * z0

);

if (z0 > 0.3) {

var z1 = camera.zoom(camera.y + this.z - 5);

x = (camera.x + this.x + (this.w - 100) * 0.5) * z1;

y = (camera.z + this.y + this.h - 30) * z1;

ctx.drawImage(this.text,

canvas.centerX + x,

canvas.centerY + y,

100 * z1,

30 * z1

);

}

}

};

var anim = function() {

over = false;

for (

var i = 0, that; that = objects[i++]; that.anim()

);

if (over !== overlast) {

overlast = over;

canvas.elem.style.cursor = over ? 'pointer' : 'default';

}

}

// main loop

var run = function() {

requestAnimationFrame(run);

ctx.clearRect(0, 0, canvas.width, canvas.height);

ctx.fillStyle = '#222';

ctx.fillRect(0, 0, canvas.width, canvas.height * 0.1);

ctx.fillRect(0, canvas.height * 0.9, canvas.width, canvas.height * 0.1);

camera.ease(pointer);

anim();

}

// canvas

var canvas = {

elem: document.createElement('canvas'),

resize: function() {

this.left = 0;

this.top = 0;

this.width = this.elem.width = this.elem.offsetWidth;

this.height = this.elem.height = this.elem.offsetHeight;

this.centerX = this.width / 2;

this.centerY = this.height / 2;

},

init: function() {

var ctx = this.elem.getContext('2d');

document.body.appendChild(this.elem);

window.addEventListener('resize', this.resize.bind(this), false);

this.resize();

return ctx;

}

};

var ctx = canvas.init();

// pointer

var pointer = (function(canvas) {

var scaling = false,

oldDist = 0;

var pointer = {

x: canvas.width / 2,

y: canvas.height / 2,

z: 10,

canvas: canvas,

touchMode: false

};

var distance = function(dx, dy) {

return Math.sqrt(dx * dx + dy * dy);

};

[

[window, 'mousemove,touchmove', function(e) {

this.touchMode = e.targetTouches;

e.preventDefault();

if (scaling && this.touchMode) {

var x0 = this.touchMode[0].clientX,

x1 = this.touchMode[1].clientX,

y0 = this.touchMode[0].clientY,

y1 = this.touchMode[1].clientY;

this.x = (x0 + x1) / 2;

this.y = (y0 + y1) / 2;

var d = distance(x0 - x1, y0 - y1);

var s = d > oldDist ? -1 : 1;

oldDist = d;

this.z += s;

if (this.z < -160) this.z = -160;

return;

}

var pointer = this.touchMode ? this.touchMode[0] : e;

this.x = pointer.clientX - this.canvas.left;

this.y = pointer.clientY - this.canvas.top;

}],

[canvas.elem, 'mousedown,touchstart', function(e) {

this.touchMode = e.targetTouches;

e.preventDefault();

if (this.touchMode && e.touches.length === 2) {

scaling = true;

} else {

var pointer = this.touchMode ? this.touchMode[0] : e;

this.x = pointer.clientX - this.canvas.left;

this.y = pointer.clientY - this.canvas.top;

anim();

if (over) {

this.z = -80 - over.z;

} else this.z = 0;

}

}],

[window, 'mouseup,touchend', function(e) {

e.preventDefault();

scaling = false;

}]

].forEach(function(e) {

for (var i = 0, events = e[1].split(','); i < events.length; i++) {

e[0].addEventListener(events[i], e[2].bind(pointer), false);

}

}.bind(pointer));

window.addEventListener('wheel', function(e) {

e.preventDefault();

var s = e.deltaY > 0 ? -10 : 10;

this.z += s;

if (this.z < -160) this.z = -160;

}.bind(pointer), false);

return pointer;

}(canvas));

// walls

var objects = [];

objects.push(

new Wall(

[-2.5, -2.5, -2.5, -2.5], [-1, -1, 1, 1], [-1, 1, 1, -1]

)

);

objects.push(

new Wall(

[-2.5, 2.5, 2.5, -2.5], [-1, -1, 1, 1], [1, 1, 1, 1]

)

);

objects.push(

new Wall(

[2.5, 2.5, 2.5, 2.5], [-1, -1, 1, 1], [1, -.5, -.5, 1]

)

);

objects.push(

new Wall(

[2.5, 2.7, 2.7, 2.5], [-1, -1, 1, 1], [-.5, -.5, -.5, -.5]

)

);

objects.push(

new Wall(

[-2.5, -2.7, -2.7, -2.5], [-1, -1, 1, 1], [-1, -1, -1, -1]

)

);

objects.push(

new Pict(

'bl112.jpg',

'he knew', "No explanation needed", -1, -.8, .8, 2, 1.4

)

);

objects.push(

new Pict(

'sf48.jpg',

'New life', "Here you come!", -2, -0.7, .4, 2, 1.4

)

);

objects.push(

new Pict(

'ct137.jpg',

'Inside', "I'm now trapped, without hope of escape",

0.5, -.6, .2, 2, 1.4

)

);

objects.push(

new Pict(

'ct60.jpg',

'Discoveries', "are made by not following instructions", -1.5, -.8, 0, 1.5, 2

)

);

objects.push(

new Pict(

'bl201.jpg',

'Nonexistance', "There's no such thing",

.5, -1, -.4, 1.5, 2

)

);

objects.push(

new Pict(

'ct41.jpg',

'Much work', "remains to be done", -2, -1, -.8, 1.5, 2

)

);

run();

}();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值