|
<!DOCTYPE html> |
|
<meta charset='utf-8'> |
|
<title>sprite</title> |
|
<style> |
|
|
|
body { |
|
margin: 0; |
|
overflow: hidden; |
|
background-color: steelblue; |
|
} |
|
|
|
.sprite, .container { |
|
display: inline-block; |
|
} |
|
|
|
</style> |
|
<script src="https://unpkg.com/[email protected]"></script> |
|
<script src="https://d3js.org/d3.v4.min.js"></script> |
|
<body> |
|
<div id="WebGL-output" class="container"></div> |
|
|
|
<script> |
|
|
|
var spriteWidth = spriteHeight = 16 * 16; |
|
|
|
// Dimensions of WebGL canvas |
|
var width = 960 - spriteWidth, height = 500; |
|
|
|
// Globals used for animation |
|
var requestId, group; |
|
|
|
// First slider to select gradient's start radius |
|
var r0 = d3.select('body').append("input") |
|
.attr("type", "range") |
|
.attr('min', 0) |
|
.attr('max', spriteWidth / 2) |
|
.attr('value', 0) |
|
.style('position', "absolute") |
|
.style('top', spriteHeight + 10 + "px") |
|
.style('left', spriteWidth / 4 + "px") |
|
.style('width', spriteWidth / 2 + 'px') |
|
.on('change', changed); |
|
|
|
// Second slider to select gradient's end radius |
|
var r1 = d3.select('body') |
|
.append(function() { return r0.node().cloneNode(); }) |
|
.attr('value', spriteWidth / 2) |
|
.style('top', spriteHeight + 30 + "px") |
|
.on('change', changed); |
|
|
|
// Add a canvas for the sprite |
|
var sprite = d3.select('body').insert(createCanvasDot, "div") |
|
.attr('class', 'sprite') |
|
.style('vertical-align', 'top') |
|
|
|
// Add a div container for the WebGL canvas |
|
var container = d3.select("WebGL-output") |
|
.attr('class', "container") |
|
.attr('width', width) |
|
.attr('height', height) |
|
|
|
var scene = new THREE.Scene(); |
|
|
|
var camera = new THREE.OrthographicCamera(0, width, 0, height, 0, 1000); |
|
|
|
var renderer = new THREE.WebGLRenderer(); |
|
|
|
// Configure the renderer |
|
renderer.setSize(width, 500) |
|
renderer.setClearColor (0xbbbbbb, 1); |
|
|
|
// Position and point the camera toward the center of the scene |
|
camera.position.x = 0; |
|
camera.position.y = 0; |
|
camera.position.z = 125; |
|
|
|
// Add the renderer to the container |
|
document.getElementById("WebGL-output").appendChild(renderer.domElement); |
|
|
|
// Add a group of sprites to the scene |
|
scene.add(createGroupOfSprites()); |
|
|
|
// Start the animation |
|
render(); |
|
|
|
// Return a group of sprites |
|
function createGroupOfSprites() { |
|
var material = new THREE.SpriteMaterial(); |
|
var n = 10, dx = height / n; |
|
|
|
material.map = generateSprite(); // returns THREE.texture() |
|
|
|
group = new THREE.Group(); |
|
for (var x = 0; x < n; x++) { |
|
for (var y = 0; y < n; y++) { |
|
var sprite = new THREE.Sprite(material); |
|
sprite.scale.set(50, 50, 50); // scale determines size (default: 1 pixel) |
|
sprite.position.set((x + 1 / 2) * dx, (y + 1 / 2) * dx, 0); |
|
group.add(sprite); |
|
} |
|
} |
|
return group |
|
} |
|
|
|
// Animate the scene |
|
function render() { |
|
requestId = requestAnimationFrame(render); |
|
group.position.x += .5; |
|
// group.rotation.x += .05; |
|
renderer.render(scene, camera); |
|
} |
|
|
|
// Returns a THREE.texture created from a canvas element |
|
function generateSprite() { |
|
var canvas = createCanvasDot(); |
|
var texture = new THREE.Texture(canvas); |
|
texture.needsUpdate = true; |
|
return texture; |
|
} |
|
|
|
// Returns a canvas element with a single dot |
|
function createCanvasDot() { |
|
var canvas = document.createElement('canvas'); |
|
canvas.width = spriteWidth; |
|
canvas.height = spriteHeight; |
|
|
|
var context = canvas.getContext('2d'); |
|
|
|
// Arguments: x0, y0, r0 (of the start circle), x1, y1, r1 (of the end circle) |
|
var x0 = y0 = x1 = y1 = spriteWidth / 2; |
|
var crimson = 'rgba(255,0,63,1)'; |
|
if (r0.node().value === r1.node().value) { |
|
context.fillStyle = crimson; |
|
context.beginPath(); |
|
context.arc(x0, y0, r0.node().value, 0, 2*Math.PI); |
|
context.fill(); |
|
} else { |
|
var gradient = context.createRadialGradient(x0, y0, r0.node().value, x1, y1, r1.node().value); |
|
gradient.addColorStop(0, crimson); |
|
gradient.addColorStop(1, 'rgba(255,255,255,0)'); |
|
context.fillStyle = gradient; |
|
context.fillRect(0, 0, canvas.width, canvas.height); |
|
} |
|
return canvas |
|
} |
|
|
|
// Create a new set of sprites when user selects a new value |
|
function changed() { |
|
// Stop the animation |
|
cancelAnimationFrame(requestId); |
|
|
|
// Redraw the sprite with the new parameters |
|
var start = +r0.node().value; |
|
var end = +r1.node().value; |
|
if (start > end) start = r0.node().value = end; |
|
d3.select('.sprite').each(function() { |
|
this.getContext("2d").clearRect(0, 0, spriteWidth, spriteHeight); |
|
this.getContext("2d").drawImage(createCanvasDot(), 0, 0); |
|
}); |
|
|
|
// Remove all objects from the scene |
|
while (scene.children.length > 0) { |
|
scene.remove(scene.children[0]); |
|
} |
|
|
|
// Add a new group of sprites to the scene |
|
scene.add(createGroupOfSprites()); |
|
|
|
// Restart the animation |
|
render(); |
|
} |
|
|
|
</script> |