plunkerでthree.js その9

# 概要
plunkerでthree.jsやってみた。
練習問題、やってみた。

# 練習問題
クリックして、ballを投げよ。

# 参考にしたページ

https://qiita.com/0taUtan/items/b1d7565585b72562ec20


# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/b8206ba8-aad4-a444-ff98-2223cdcaeb21.png)

# サンプルコード

```

let scene, 
    camera, 
    light,
    renderer;
var clock;
var mixer;
function setObjectInitialPosition(position, relativeX, relativeY ) {
	const forward = new THREE.Vector3();
	camera.getWorldDirection(forward);
	forward.normalize();
	const { up } = camera; 
	const left = up.clone().cross(forward); 
	left.multiplyScalar(relativeX * camera.getFilmWidth()); 
	const top = up.clone().multiplyScalar(relativeY * camera.getFilmHeight()); 
	forward.multiplyScalar(camera.near);
	position.copy(camera.position).add(left).add(top).add(forward);
};
function moveObject(object) {
	const startPosition = object.position;
	const { x, y, z } = startPosition;
	const endPosition = new THREE.Vector3();
	camera.getWorldDirection(endPosition);
	endPosition.multiplyScalar(camera.far).add(startPosition);
	const positionKF = new THREE.VectorKeyframeTrack(".position", [0, 10], [x, y, z, endPosition.x, endPosition.y, endPosition.z]);
	const moveObjectClip = new THREE.AnimationClip(`move-object-${object.id}`, -1, [positionKF,]);
	mixer = new THREE.AnimationMixer(object);
	mixer.addEventListener("finished", () => {
		scene.remove(object);
		object.geometry.dispose();
	});
	const action = mixer.clipAction(moveObjectClip);
	action.setLoop(THREE.LoopOnce, 0);
	action.play();
};
renderer = new THREE.WebGLRenderer({ 
	antialias: true 
});
renderer.setSize(400, 400);
document.body.appendChild(renderer.domElement);
scene = new THREE.Scene();
clock = new THREE.Clock();
scene.background = new THREE.Color(0xbfd1e5);
camera = new THREE.PerspectiveCamera(45, 400 / 400, 1, 1000);
camera.position.set(0, 30, 50);
scene.add(camera);
scene.add(new THREE.GridHelper(60, 10));
light = new THREE.AmbientLight(0xFFFFFF);
scene.add(light);
const geometry = new THREE.TorusGeometry(10, 3, 16, 100); 
const material = new THREE.MeshBasicMaterial({ 
	color: 0xff2222 
}); 
const torus = new THREE.Mesh(geometry, material); 
torus.rotation.x += Math.PI / 2;
scene.add(torus);
renderer.render(scene, camera);
var raycaster = new THREE.Raycaster();
var controls = new THREE.OrbitControls(camera, renderer.domElement);
renderer.domElement.addEventListener('click', function(e) {
  var raymouse = new THREE.Vector2();
	raymouse.x = -(e.offsetX / 400) * 2 + 1;
	raymouse.y = -(e.offsetY / 400) * 2 + 1;
	raycaster.setFromCamera(raymouse, camera);
	var intersects = raycaster.intersectObjects(scene.children);
	if (intersects.length > 0)
	{
		const geometry = new THREE.SphereBufferGeometry(3);
    const material = new THREE.MeshBasicMaterial({ 
			color: 0xffffff
	 	});
		const ball = new THREE.Mesh(geometry, material);
		setObjectInitialPosition(ball.position, raymouse.x, raymouse.y);
		scene.add(ball);
		moveObject(ball);
	}
})
function tick() {
	requestAnimationFrame(tick);
	var delta = clock.getDelta();
	if (mixer)
	{
		mixer.update(delta);
	}
	renderer.render(scene, camera);
	controls.update();
}
tick();





```

# 成果物

https://embed.plnkr.co/plunk/0vihxZPdPleI07tl


以上。