欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

按钮(click button)

程序员文章站 2022-04-27 14:57:36
...

按钮

更多有趣示例 尽在小红砖社区

示例

按钮(click button)

HTML

p Drag to rotate the button!<br>Press it in when you need it!
small.info Created with ThreeJS, ThreeCSG<br>(wo any 3d model)
small.credits
	a(href="http://www.amazon.com/Gemmy-32651-The-Official-Button/dp/B000L70MQO", target="_blank") Real life BS button (have one on my desk)
	a(href="https://twitter.com/pety7439", target="_blank") @pety7439

CSS

body {
	margin: 0;
	padding: 0;
	overflow: hidden;
	font-family: 'Open Sans', sans-serif;
	color: #fff;
	background: #000;
}

canvas {
	margin: 0;
	padding: 0;
}

p {
	position: absolute;
	top: 30px;
	left: 50%;
	font-size: 14px;
	font-weight: 600;
	line-height: 20px;
	text-align: center;
	transform: translateX(-50%);
}

small {
	position: absolute;
	bottom: 30px;
	font-size: 12px;
	line-height: 16px;
	
	&.info {
		left: 30px;
		text-align: left;
	}
	
	&.credits {
		right: 30px;
		text-align: right;
	}
	
	a {
		display: block;
		margin: 0 0 4px;
		color: #fff;
		text-decoration: none;
		
		&:hover {
			text-decoration: underline;
		}
		
	}
	
}

JS

(function () {
	'use strict';

	var container,
		renderer,
		camera,
		scene,
		group,
		buttonGroup,

		raycaster = new THREE.Raycaster(),
		raycasterCheck = false,
		intersects,
		mouseVectors = new THREE.Vector2(),

		alertBuffer = null,
		alertLoaded = false,
		audioContext,
		audioSource,

		blinkTid,
		blinkDelay = 400,
		blinkLimit = 10,

		targetRotationX = 0,
		targetRotationY = 1,
		targetRotationXOnMouseDown = 0,
		targetRotationYOnMouseDown = 0,

		mouseX = 0,
		mouseXOnMouseDown = 0,
		mouseY = 0,
		mouseYOnMouseDown = 0,

		windowHalfX = window.innerWidth / 2,
		windowHalfY = window.innerHeight / 2,

		topSphere,
		buttonMaterial,
		buttonMaterialInner;


	function init3d() {
		container = document.createElement('div');
		document.body.appendChild(container);

		renderer = new THREE.WebGLRenderer({
			antialias: true
		});

		renderer.setClearColor(0x1E90FF);
		renderer.setPixelRatio(window.devicePixelRatio);
		renderer.setSize(window.innerWidth, window.innerHeight);

		camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 5000);
		camera.position.set(0, 0, 200);

		scene = new THREE.Scene();
		scene.add(camera);

		initLights();

		group = new THREE.Group();

		scene.add(group);

		container.appendChild(renderer.domElement);
	}

	function initLights() {
		var light1,
			light2,
			light3,
			light4,
			light5,
			light6;

		light1 = new THREE.PointLight(0x1E90FF, 0.8, 500);
		light1.position.set(300.0, -300.0, 300.0);

		light2 = new THREE.PointLight(0xffffff, 0.8, 500);
		light2.position.set(-300.0, -300.0, 300.0);

		light3 = new THREE.PointLight(0xffffff, 0.8, 500);
		light3.position.set(0.0, 300.0, 300.0);

		light4 = new THREE.DirectionalLight(0xffffff, 0.5);
		light4.position.set(0.0, -200.0, 200.0);

		light5 = new THREE.DirectionalLight(0xffffff, 0.5);
		light5.position.set(0.0, 200.0, -200.0);

		light6 = new THREE.DirectionalLight(0xffffff, 0.5);
		light6.position.set(-200.0, 200.0, 200.0);

		scene.add(light1);
		scene.add(light2);
		scene.add(light3);
		scene.add(light4);
		scene.add(light5);
		scene.add(light6);

	}

	function initEventBindings() {
		document.addEventListener('mousedown', onDocumentMouseDown, false);
		document.addEventListener('touchstart', onDocumentTouchStart, false);
		document.addEventListener('touchmove', onDocumentTouchMove, false);
		window.addEventListener('resize', onWindowResize, false);
	}

	function createBaseCylinder() {
		var bottomGeometry = new THREE.CylinderGeometry(37, 37, 32, 256, 16, true),
			bottomGeometry2 = new THREE.CylinderGeometry(36, 37, 12, 64),
			topGeometry = new THREE.CylinderGeometry(30, 37, 4, 64),
			batteryGeometry = new THREE.BoxGeometry(50, 10, 25),
			material = new THREE.MeshPhongMaterial({
				color: new THREE.Color('#273a4b'),
				shading: THREE.SmoothShading
			}),
			screwMaterial = new THREE.MeshPhongMaterial({
				color: new THREE.Color('#bcc6cc'),
				emissive: new THREE.Color('#333333'),
				shininess: 40,
				metal: true
			}),
			cylinderGroup,
			batteryBox,
			batteryCover,
			batteryCoverBSP,
			bottomCylinder,
			bottomCylinder2,
			bottomBSP,
			topCylinder,
			substractCylinder,
			screw1,
			screw2,
			screw3,
			screw4,
			screwGeometry = new THREE.CylinderGeometry(1.5, 1.5, 3, 64),
			batteryBSP,
			substractBSP,
			substractGeometry = new THREE.CylinderGeometry(2, 2, 5, 64),
			resultBSP,
			resultCylinder,
			bottomCylinderBSP,
			box,
			box2,
			box3,
			boxMesh,
			boxMesh2,
			boxMesh3,
			boxBSP,
			boxBSP2,
			boxBSP3,
			cutCylinder,
			cutCylinderMesh,
			cutCylinderBSP;

		cylinderGroup = new THREE.Group();
		bottomCylinder = new THREE.Mesh(bottomGeometry, material);
		bottomCylinder2 = new THREE.Mesh(bottomGeometry2, material);
		bottomCylinder2.position.y = -10;

		batteryBox = new THREE.Mesh(batteryGeometry);
		batteryBox.position.y = -14;
		batteryBox.position.z = 11;

		screw1 = new THREE.Mesh(screwGeometry, screwMaterial);
		screw2 = new THREE.Mesh(screwGeometry, screwMaterial);
		screw3 = new THREE.Mesh(screwGeometry, screwMaterial);
		screw4 = new THREE.Mesh(screwGeometry, screwMaterial);

		topCylinder = new THREE.Mesh(topGeometry, material);
		substractCylinder = new THREE.Mesh(substractGeometry);

		substractCylinder.position.x = 20;
		substractCylinder.position.z = -20;
		substractCylinder.position.y = -14;

		screw1.position.x = 20;
		screw1.position.z = -20;
		screw1.position.y = -12;

		topCylinder.position.y = 18;

		bottomBSP = new ThreeBSP(bottomCylinder2);
		substractBSP = new ThreeBSP(substractCylinder);
		batteryBSP = new ThreeBSP(batteryBox);

		resultBSP = bottomBSP.subtract(substractBSP);
		resultBSP = resultBSP.subtract(batteryBSP);

		batteryBox = new THREE.Mesh(batteryGeometry);
		batteryBox.scale.x = 0.15;
		batteryBox.position.x = -10;
		batteryBox.position.y = -14;
		batteryBox.position.z = 16;

		batteryBSP = new ThreeBSP(batteryBox);

		resultBSP = resultBSP.subtract(batteryBSP);

		batteryBox = new THREE.Mesh(new THREE.BoxGeometry(50, 12, 35));
		batteryBox.position.y = -10;
		batteryBox.position.z = 11;

		batteryBSP = new ThreeBSP(batteryBox);
		batteryCoverBSP = batteryBSP.subtract(resultBSP);
		batteryCoverBSP = batteryCoverBSP.intersect(bottomBSP);

		substractCylinder.position.x = -10;
		substractCylinder.position.z = 26;
		substractBSP = new ThreeBSP(substractCylinder);
		batteryCoverBSP = batteryCoverBSP.subtract(substractBSP);

		batteryCover = batteryCoverBSP.toMesh(material);
		batteryCover.geometry.computeFaceNormals();
		batteryCover.scale.x = 0.98;
		batteryCover.scale.y = 0.98;
		batteryCover.scale.z = 0.98;

		screw4.position.x = -10;
		screw4.position.z = 26;
		screw4.position.y = -12;

		substractCylinder.position.x = -28;
		substractCylinder.position.z = -10;

		screw2.position.x = -28;
		screw2.position.z = -10;
		screw2.position.y = -12;

		substractBSP = new ThreeBSP(substractCylinder);

		resultBSP = resultBSP.subtract(substractBSP);

		substractCylinder.position.x = 5;
		substractCylinder.position.z = 28;

		screw3.position.x = 5;
		screw3.position.z = 28;
		screw3.position.y = -12;

		substractBSP = new ThreeBSP(substractCylinder);

		resultBSP = resultBSP.subtract(substractBSP);

		resultCylinder = resultBSP.toMesh(material);
		resultCylinder.geometry.computeFaceNormals();

		cylinderGroup.add(topCylinder);
		cylinderGroup.add(resultCylinder);
		//cylinderGroup.add(batteryCover);
		
		box = new THREE.BoxGeometry(72, 5, 72);
		boxMesh = new THREE.Mesh(box);
		boxMesh.position.y = 10;
		boxBSP = new ThreeBSP(boxMesh);
		
		box2 = new THREE.BoxGeometry(15, 5, 72);
		boxMesh2 = new THREE.Mesh(box2);
		boxMesh2.position.y = 10;
		boxBSP2 = new ThreeBSP(boxMesh2);
		
		box3 = new THREE.BoxGeometry(72, 5, 15);
		boxMesh3 = new THREE.Mesh(box3);
		boxMesh3.position.y = 10;
		boxBSP3 = new ThreeBSP(boxMesh3);
		
		cutCylinder = new THREE.CylinderGeometry(35, 35, 5, 128);
		cutCylinderMesh = new THREE.Mesh(cutCylinder);
		cutCylinderMesh.position.y = 10;
		cutCylinderBSP = new ThreeBSP(cutCylinderMesh);
		
		bottomCylinderBSP = new ThreeBSP(bottomCylinder);
		
		resultBSP = boxBSP.subtract(boxBSP2);
		resultBSP = resultBSP.subtract(boxBSP3);
		resultBSP = resultBSP.subtract(cutCylinderBSP);
		resultBSP = bottomCylinderBSP.subtract(resultBSP);
		
		bottomCylinder = resultBSP.toMesh(material);
		bottomCylinder.geometry.computeFaceNormals();
		
		cylinderGroup.add(bottomCylinder);
		
		cylinderGroup.add(screw1);
		cylinderGroup.add(screw2);
		cylinderGroup.add(screw3);
		cylinderGroup.add(screw4);

		group.add(cylinderGroup);
	}

	function createButton() {
		var baseGeometry = new THREE.CylinderGeometry(29, 29, 4, 64),
			textMaterial = new THREE.MeshLambertMaterial({
				color: 0xffffff,
				emissive: 0xffffff,
				overdraw: 0.5
			}),
			textGeometry = new THREE.TextGeometry('BULLSHIT', {
				size: 8.5,
				height: 0.8,
				font: 'helvetiker',
				weight: 'normal',
				style: 'normal'
			}),
			topGeometry = new THREE.SphereGeometry(45, 64, 64, 0, Math.PI * 2, 0, 0.7),
			textMesh,
			baseCylinder,
			centerOffsetX,
			centerOffsetY,
			direction,
			axis,
			angle,
			modifier = new THREE.BendModifier();

		buttonMaterial = new THREE.MeshPhongMaterial({
			color: new THREE.Color('#982625'),
			emissive: new THREE.Color('#9d0302'),
			specular: new THREE.Color('#333333'),
			shininess: 30
		});

		buttonMaterialInner = new THREE.MeshPhongMaterial({
			color: new THREE.Color('#982625'),
			emissive: new THREE.Color('#9d0302'),
			specular: new THREE.Color('#333333')
		});
		
		buttonGroup = new THREE.Group();
		buttonGroup.name = 'button';

		baseCylinder = new THREE.Mesh(baseGeometry, buttonMaterial);
		baseCylinder.position.y = 22;

		topSphere = new THREE.Mesh(topGeometry, buttonMaterial);
		topSphere.position.y = -10.5;
		topSphere.doubleSided = true;

		//buttonGroup.add(baseCylinder);
		buttonGroup.add(topSphere);

		direction = new THREE.Vector3(0, 0, -1);
		axis = new THREE.Vector3(0, 1, 0);
		angle = Math.PI / 5.75;
		modifier.set(direction, axis, angle).modify(textGeometry);

		textMesh = new THREE.Mesh(textGeometry, textMaterial);
		textMesh.rotation.x = -90 * Math.PI / 180;
		textMesh.position.y = 34;

		textGeometry.computeBoundingBox();

		centerOffsetX = -0.5 * (textGeometry.boundingBox.max.x - textGeometry.boundingBox.min.x);
		centerOffsetY = 0.5 * (textGeometry.boundingBox.max.y - textGeometry.boundingBox.min.y);

		textMesh.position.x = centerOffsetX;
		textMesh.position.z = centerOffsetY;

		buttonGroup.add(textMesh);

		group.add(buttonGroup);
	}

	function createTexts() {
		var bottomTextGeometry = new THREE.TextGeometry('HB', {
				size: 2,
				height: 1,
				font: 'helvetiker',
				weight: 'normal',
				style: 'normal'
			}),
			bottomTextGeometry2 = new THREE.TextGeometry('0513', {
				size: 2,
				height: 1,
				font: 'helvetiker',
				weight: 'normal',
				style: 'normal'
			}),
			bottomTextGeometry3 = new THREE.TextGeometry('Batch-001', {
				size: 2,
				height: 1,
				font: 'helvetiker',
				weight: 'normal',
				style: 'normal'
			}),
			bottomTextGeometry4 = new THREE.TextGeometry('Budapest, Hungary', {
				size: 2,
				height: 1,
				font: 'helvetiker',
				weight: 'normal',
				style: 'normal'
			}),
			planeGeometry = new THREE.PlaneBufferGeometry(32, 14, 1, 1),
			material = new THREE.MeshLambertMaterial({
				color: 0xffffff,
				overdraw: 0.5
			}),
			textureImg = new Image(),
			texture,
			planeMaterial,
			planeMesh,
			bottomTextMesh,
			bottomTextMesh2,
			bottomTextMesh3,
			bottomTextMesh4;

		textureImg.crossOrigin = "Anonymous";
		texture = new THREE.Texture();
		texture.image = textureImg;

		textureImg.onload = function () {
			texture.needsUpdate = true;
		};

		textureImg.src = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/8223/environmental-signs.png';

		planeMaterial = new THREE.MeshLambertMaterial({
			map: texture,
			transparent: true,
			overdraw: true
		});

		bottomTextMesh = new THREE.Mesh(bottomTextGeometry, material);
		bottomTextMesh.rotation.x = 90 * Math.PI / 180;
		bottomTextMesh.rotation.z = -180 * Math.PI / 180;

		bottomTextMesh.position.x = 10;
		bottomTextMesh.position.y = -15.2;
		bottomTextMesh.position.z = -28;

		bottomTextMesh2 = new THREE.Mesh(bottomTextGeometry2, material);
		bottomTextMesh2.rotation.x = 90 * Math.PI / 180;
		bottomTextMesh2.rotation.z = -180 * Math.PI / 180;

		bottomTextMesh2.position.x = 10;
		bottomTextMesh2.position.y = -15.2;
		bottomTextMesh2.position.z = -25;

		bottomTextMesh3 = new THREE.Mesh(bottomTextGeometry3, material);
		bottomTextMesh3.rotation.x = 90 * Math.PI / 180;
		bottomTextMesh3.rotation.z = -180 * Math.PI / 180;

		bottomTextMesh3.position.x = 10;
		bottomTextMesh3.position.y = -15.2;
		bottomTextMesh3.position.z = -22;

		bottomTextMesh4 = new THREE.Mesh(bottomTextGeometry4, material);
		bottomTextMesh4.rotation.x = 90 * Math.PI / 180;
		bottomTextMesh4.rotation.z = -180 * Math.PI / 180;

		bottomTextMesh4.position.x = 10;
		bottomTextMesh4.position.y = -15.2;
		bottomTextMesh4.position.z = -19;

		planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
		planeMesh.rotation.x = 90 * Math.PI / 180;
		planeMesh.rotation.z = -180 * Math.PI / 180;

		planeMesh.position.x = 0;
		planeMesh.position.y = -16.2;
		planeMesh.position.z = -10;

		group.add(bottomTextMesh);
		group.add(bottomTextMesh2);
		group.add(bottomTextMesh3);
		group.add(bottomTextMesh4);
		group.add(planeMesh);

	}

	function animate() {
		window.requestAnimationFrame(animate);
		render();
	}

	function render() {
		group.rotation.x += (targetRotationY - group.rotation.x) * 0.05;
		group.rotation.y += (targetRotationX - group.rotation.y) * 0.05;

		if (raycasterCheck) {
			raycaster.setFromCamera(mouseVectors, camera);

			intersects = raycaster.intersectObjects(scene.children, true);
			if (intersects.length > 0) {
				checkHit(intersects);
			}
			raycasterCheck = false;
		}

		renderer.render(scene, camera);
	}

	function checkHit(intersects) {
		var i = 0,
			l = intersects.length;

		if (l > 0) {

			if (intersects[0].object.parent && intersects[i].object.parent.name === 'button') {
				moveButton();
				blinkLimit = 10;
				blinkButton();

				if (alertLoaded) {
					stopSound();
					playSound(alertBuffer);
				}

			}

		}

	}

	function moveButton() {
		TweenMax.killAll();
		TweenMax.to(buttonGroup.position, 0.25, {
			ease: Expo.easeInOut,
			y: -3,
			yoyo: true,
			repeat: 1
		});
	}

	function blinkButton() {
		clearTimeout(blinkTid);
		if (blinkLimit > 0) {
			blinkTid = window.setTimeout(function () {

				if (blinkLimit % 2 === 0) {
					buttonMaterial.emissive = new THREE.Color('#9d0302');
					buttonMaterial.shininess = 30;
				} else {
					buttonMaterial.emissive = new THREE.Color('#ff3600');
					buttonMaterial.shininess = 40;
				}

				blinkButton();
			}, blinkDelay);
			blinkLimit--;
		}

	}

	function loadAlertSound(url) {
		var request = new XMLHttpRequest();

		request.open('GET', url, true);
		request.responseType = 'arraybuffer';

		request.onload = function () {
			audioContext.decodeAudioData(request.response, function (buffer) {
				alertBuffer = buffer;
				alertLoaded = true;
			});
		};

		request.send();
	}

	function stopSound() {
		if (audioSource) {
			audioSource.stop();
		}
	}

	function playSound(buffer) {
		audioSource = audioContext.createBufferSource();
		audioSource.buffer = buffer;
		audioSource.connect(audioContext.destination);
		audioSource.start(0);
	}

	function onWindowResize() {
		windowHalfX = window.innerWidth / 2;
		windowHalfY = window.innerHeight / 2;
		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);
		document.addEventListener('mouseout', onDocumentMouseOut, false);
		mouseXOnMouseDown = event.clientX - windowHalfX;
		mouseYOnMouseDown = event.clientY - windowHalfY;
		targetRotationXOnMouseDown = targetRotationX;
		targetRotationYOnMouseDown = targetRotationY;
		mouseVectors.x = (event.clientX / window.innerWidth) * 2 - 1;
		mouseVectors.y = -(event.clientY / window.innerHeight) * 2 + 1;
		raycasterCheck = true;
	}

	function onDocumentMouseMove(event) {
		mouseX = event.clientX - windowHalfX;
		mouseY = event.clientY - windowHalfY;
		targetRotationX = targetRotationXOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.02;
		targetRotationY = targetRotationYOnMouseDown + (mouseY - mouseYOnMouseDown) * 0.02;
	}

	function onDocumentMouseUp() {
		document.removeEventListener('mousemove', onDocumentMouseMove, false);
		document.removeEventListener('mouseup', onDocumentMouseUp, false);
		document.removeEventListener('mouseout', onDocumentMouseOut, false);
		raycasterCheck = false;
	}

	function onDocumentMouseOut() {
		document.removeEventListener('mousemove', onDocumentMouseMove, false);
		document.removeEventListener('mouseup', onDocumentMouseUp, false);
		document.removeEventListener('mouseout', onDocumentMouseOut, false);
	}

	function onDocumentTouchStart(event) {

		if (event.touches.length === 1) {
			event.preventDefault();
			mouseXOnMouseDown = event.touches[0].pageX - windowHalfX;
			mouseYOnMouseDown = event.touches[0].pageY - windowHalfY;
			targetRotationXOnMouseDown = targetRotationX;
			targetRotationYOnMouseDown = targetRotationY;
		}
	}

	function onDocumentTouchMove(event) {

		if (event.touches.length === 1) {
			event.preventDefault();
			mouseX = event.touches[0].pageX - windowHalfX;
			mouseY = event.touches[0].pageY - windowHalfY;
			targetRotationX = targetRotationXOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.05;
			targetRotationY = targetRotationYOnMouseDown + (mouseY - mouseYOnMouseDown) * 0.05;
		}
	}

	window.AudioContext = window.AudioContext || window.webkitAudioContext;
	audioContext = new AudioContext();

	loadAlertSound('https://s3-us-west-2.amazonaws.com/s.cdpn.io/8223/alert.mp3');

	init3d();
	initEventBindings();

	createBaseCylinder();
	createButton();
	createTexts();

	animate();

})();