So for my assignment I have a webpage where I input a number and choose a shape and the chosen number amount of the chosen shape will appear and go through a set animation. After the animation, I need to make the shape disappear. I've tried everything including using the remove() action and still can't figure this one out.
So here's my fiddle: https://jsfiddle.net/o6e2yu5b/2/
Here's the javascript code:
draw = function() {
var typed = $('#howmany').val()
var shape = $('#shape').val()
var x, y;
for (var i = 0; i < typed; i++) {
x = Math.random() * 350
y = Math.random() * 350
if (shape == 'a') {
pattern = paper.circle(25, 25, 25)
}
if (shape == 'b') {
pattern = paper.rect(10, 10, 50, 50)
}
if (shape == 'c') {
pattern = paper.path('M25,0 L50,50, L0,50 Z')
}
color_attr = {
'fill': '#BB7'
}
position_attr = {
'transform': 't' + x + ',' + y
}
pattern.attr(color_attr)
pattern.animate(position_attr, 2000)
onComplete:function() {
this.target.remove();
}
}
}
setup = function() {
paper = Raphael('svg1', 400, 400)
$('button').click(draw)
}
jQuery(document).ready(setup)
Please help! Thanks
It looks like your onComplete function is incorrect and didn't work. So I made a new setTimeout function that will delete generated shape/s after animation is complete. Check out this demo https://jsfiddle.net/o6e2yu5b/3/
setTimeout(function(){
SVG.find("circle").remove();
SVG.find("rect").remove();
SVG.find("path").remove();
}, 2000);
Related
I create a game using javascript. The code is placed at the bottom of the page. Visualize it as if the game is below a footer. The game starts when the user selects the start game button. The mechanics of the game are controlled by the arrow key. Arrow keys are used to move up, right, and left down. The problem is when I press the up or down key, the page scrolls too. How to stop this? I want the page not to scroll when the game is active. I am attaching the code of the game I create. It is a snake game.There's CSS too, but I'm not attaching it as I don't think its relevant
<div id="app" class="app">
<div class="start-screen">
<h2>🦊 </h2>
<div class="options">
<h3>Choose Difficulty</h3>
<p class="end-score"></p>
<button data-difficulty="100" class="active">Easy</button>
<button data-difficulty="75">Medium</button>
<button data-difficulty="50">Hard</button>
</div>
<button class="play-btn">Play</button>
</div>
<canvas id="board"></canvas>
<div class="score">0</div>
</div>
<script>
class SnakeGame {
constructor() {
this.$app = document.querySelector('#app');
this.$canvas = this.$app.querySelector('canvas');
this.ctx = this.$canvas.getContext('2d');
this.$startScreen = this.$app.querySelector('.start-screen');
this.$score = this.$app.querySelector('.score');
this.settings = {
canvas: {
width: 500,
height: 500,
background: 'white',
border: 'black'
},
snake: {
size: 20,
background: '#73854A',
border: '#000'
}
};
this.game = {
// "direction" (set in setUpGame())
// "nextDirection" (set in setUpGame())
// "score" (set in setUpGame())
speed: 100,
keyCodes: {
38: 'up',
40: 'down',
39: 'right',
37: 'left'
}
}
this.soundEffects = {
score: new Audio('./sounds/score.mp3'),
gameOver: new Audio('./sounds/game-over.mp3')
};
this.setUpGame();
this.init();
}
init() {
// Choose difficulty
// Rather than using "this.$startScreen.querySelectorAll('button')" and looping over the node list
// and attaching seperate event listeners on each item, it's more efficient to just listen in on the container and run a check at runtime
this.$startScreen.querySelector('.options').addEventListener('click', event => {
this.chooseDifficulty(event.target.dataset.difficulty);
});
// Play
this.$startScreen.querySelector('.play-btn').addEventListener('click', () => {
this.startGame();
});
}
chooseDifficulty(difficulty) {
if(difficulty) {
this.game.speed = difficulty;
this.$startScreen.querySelectorAll('.options button').forEach(btn => btn.classList.remove('active'));
event.target.classList.add('active');
}
}
setUpGame() {
// The snake starts off with 5 pieces
// Each piece is 30x30 pixels
// Each following piece must be n times as far from the first piece
const x = 300;
const y = 300;
this.snake = [
{ x: x, y: y },
{ x: x - this.settings.snake.size, y: y },
{ x: x - (this.settings.snake.size * 2), y: y },
{ x: x - (this.settings.snake.size * 3), y: y },
{ x: x - (this.settings.snake.size * 4), y: y }
];
this.food = {
active: false,
background: '#EC5E0B',
border: '#73AA24',
coordinates: {
x: 0,
y: 0
}
};
this.game.score = 0;
this.game.direction = 'right';
this.game.nextDirection = 'right';
}
startGame() {
// Stop the game over sound effect if a new game was restarted quickly before it could end
this.soundEffects.gameOver.pause();
this.soundEffects.gameOver.currentTime = 0;
// Reset a few things from the prior game
this.$app.classList.add('game-in-progress');
this.$app.classList.remove('game-over');
this.$score.innerText = 0;
this.generateSnake();
this.startGameInterval = setInterval(() => {
if(!this.detectCollision()) {
this.generateSnake();
} else {
this.endGame();
}
}, this.game.speed);
// Change direction
document.addEventListener('keydown', event => {
this.changeDirection(event.keyCode);
});
}
changeDirection(keyCode) {
const validKeyPress = Object.keys(this.game.keyCodes).includes(keyCode.toString()); // Only allow (up|down|left|right)
if(validKeyPress && this.validateDirectionChange(this.game.keyCodes[keyCode], this.game.direction)) {
this.game.nextDirection = this.game.keyCodes[keyCode];
}
}
// When already moving in one direction snake shouldn't be allowed to move in the opposite direction
validateDirectionChange(keyPress, currentDirection) {
return (keyPress === 'left' && currentDirection !== 'right') ||
(keyPress === 'right' && currentDirection !== 'left') ||
(keyPress === 'up' && currentDirection !== 'down') ||
(keyPress === 'down' && currentDirection !== 'up');
}
resetCanvas() {
// Full screen size
this.$canvas.width = this.settings.canvas.width;
this.$canvas.height = this.settings.canvas.height;
this.$canvas.style.border = `3px solid ${this.settings.canvas.border}`;
// Background
this.ctx.fillStyle = this.settings.canvas.background;
this.ctx.fillRect(0, 0, this.$canvas.width, this.$canvas.height);
}
generateSnake() {
let coordinate;
switch(this.game.direction) {
case 'right':
coordinate = {
x: this.snake[0].x + this.settings.snake.size,
y: this.snake[0].y
};
break;
case 'up':
coordinate = {
x: this.snake[0].x,
y: this.snake[0].y - this.settings.snake.size
};
break;
case 'left':
coordinate = {
x: this.snake[0].x - this.settings.snake.size,
y: this.snake[0].y
};
break;
case 'down':
coordinate = {
x: this.snake[0].x,
y: this.snake[0].y + this.settings.snake.size
};
}
// The snake moves by adding a piece to the beginning "this.snake.unshift(coordinate)" and removing the last piece "this.snake.pop()"
// Except when it eats the food in which case there is no need to remove a piece and the added piece will make it grow
this.snake.unshift(coordinate);
this.resetCanvas();
const ateFood = this.snake[0].x === this.food.coordinates.x && this.snake[0].y === this.food.coordinates.y;
if(ateFood) {
this.food.active = false;
this.game.score += 10;
this.$score.innerText = this.game.score;
this.soundEffects.score.play();
} else {
this.snake.pop();
}
this.generateFood();
this.drawSnake();
}
drawSnake() {
const size = this.settings.snake.size;
this.ctx.fillStyle = this.settings.snake.background;
this.ctx.strokestyle = this.settings.snake.border;
// Draw each piece
this.snake.forEach(coordinate => {
this.ctx.fillRect(coordinate.x, coordinate.y, size, size);
this.ctx.strokeRect(coordinate.x, coordinate.y, size, size);
});
this.game.direction = this.game.nextDirection;
}
generateFood() {
// If there is uneaten food on the canvas there's no need to regenerate it
if(this.food.active) {
this.drawFood(this.food.coordinates.x, this.food.coordinates.y);
return;
}
const gridSize = this.settings.snake.size;
const xMax = this.settings.canvas.width - gridSize;
const yMax = this.settings.canvas.height - gridSize;
const x = Math.round((Math.random() * xMax) / gridSize) * gridSize;
const y = Math.round((Math.random() * yMax) / gridSize) * gridSize;
// Make sure the generated coordinates do not conflict with the snake's present location
// If so recall this method recursively to try again
this.snake.forEach(coordinate => {
const foodSnakeConflict = coordinate.x == x && coordinate.y == y;
if(foodSnakeConflict) {
this.generateFood();
} else {
this.drawFood(x, y);
}
});
}
drawFood(x, y) {
const size = this.settings.snake.size;
this.ctx.fillStyle = this.food.background;
this.ctx.strokestyle = this.food.border;
this.ctx.fillRect(x, y, size, size);
this.ctx.strokeRect(x, y, size, size);
this.food.active = true;
this.food.coordinates.x = x;
this.food.coordinates.y = y;
}
detectCollision() {
// Self collison
// It's impossible for the first 3 pieces of the snake to self collide so the loop starts at 4
for(let i = 4; i < this.snake.length; i++) {
const selfCollison = this.snake[i].x === this.snake[0].x && this.snake[i].y === this.snake[0].y;
if(selfCollison) {
return true;
}
}
// Wall collison
const leftCollison = this.snake[0].x < 0;
const topCollison = this.snake[0].y < 0;
const rightCollison = this.snake[0].x > this.$canvas.width - this.settings.snake.size;
const bottomCollison = this.snake[0].y > this.$canvas.height - this.settings.snake.size;
return leftCollison || topCollison || rightCollison || bottomCollison;
}
endGame() {
this.soundEffects.gameOver.play();
clearInterval(this.startGameInterval);
this.$app.classList.remove('game-in-progress');
this.$app.classList.add('game-over');
this.$startScreen.querySelector('.options h3').innerText = 'Game Over';
this.$startScreen.querySelector('.options .end-score').innerText = `Score: ${this.game.score}`;
this.setUpGame();
}
}
const snakeGame = new SnakeGame();
</script>
Stop the page from moving up and down when the game is active
You just need to prevent the default behaviour of these keys:
// Change direction
document.addEventListener('keydown', event => {
event.preventDefault(); // add this line
this.changeDirection(event.keyCode);
});
Note that this isn't a very good idea to do it that way, as it will prevent the default behaviour of all keypresses anywhere on your page. Most notably, F5 will never refresh the browser, and if you have other elements like buttons, links, etc, the standard keypresses to activate those will stop working (turning these off is a particular problem if you want your site to be accessible to those with disabilities).
You'd be better off checking the keyCode first and only preventing default if it corresponds to one of the arrow keys - which isn't so easy to do with your code as it stands but I'd encourage you to rewrite it that way.
Even doing that presents a problem to those who are not able to use a mouse, as (depending on the position of your game interface on the screen and its size) they may still need to scroll down and will be prevented from doing this by this preventDefault behaviour. But well that's what you asked for, and I've given you the solution - but with this important caveat.
I making simple shooting game and there is a problem (sometimes):
GIF Game problem
3 bullets was removed (but only one bullet collided). Bullets and enemy (blue square) are in one array (var objects = []). Sometimes it destroy (splice) only bullets not enemy.
When i do a .splice(), array is being re-indexed, i know i can use:
split objects (two arrays for enemy and bullets)
or use "delete"
But i want use splice() and i want all objects (bullets, enemy) in one array, it possible? Any ideas? I don't need a code (but if someone have a time please update my jsfiddle...). I tried decrement (i--) variable "i" (in loop) after a .splice() - but that does not solve the problem.
Sample: https://jsfiddle.net/uy9okuzv/1/ (space == shot, keys == controls)
html
<canvas id="game" width="500" height="400" style="border: 1px red solid;">
javascript
var ctx = document.getElementById("game").getContext('2d');
var objects = [];
var keys = [];
var shotTime = 30;
var ship = {
x: 20,
y: 200,
w: 50,
h: 50,
}
setInterval(function(){
// controls
if(keys[37]){
ship.x-=4;
}
if(keys[38]){
ship.y-=4;
}
if(keys[39]){
ship.x+=4;
}
if(keys[40]){
ship.y+=4;
}
if(keys[32] && shotTime<=0){
push(ship.x+ship.w, ship.y, "bullet", "red", "left");
shotTime = 30;
}else{
shotTime--;
}
// update
for(var e=0; e<objects.length; e++){
var obj = objects[e];
if(obj.type=="bullet"){
for (var i = 0; i<objects.length; i++) {
var enemy = objects[i];
if(enemy.type=="enemy"){
if(collisionObj(obj, enemy)){
objects.splice(e,1);
objects.splice(i,1);
}
}
}
}
if(obj.dir=="left"){
obj.x+=5;
}
if(obj.dir=="right"){
obj.x--;
}
}
// render
ctx.clearRect(0,0,game.width, game.height);
for(var e=0; e<objects.length; e++){
var obj = objects[e];
ctx.fillStyle=obj.color;
ctx.fillRect(obj.x, obj.y, obj.w, obj.h);
}
ctx.fillStyle="green";
ctx.fillRect(ship.x, ship.y, ship.w, ship.h);
},1000/60);
// add enemy
setInterval(function(){
push(game.width, mt_rand(10,game.height-50), "enemy", "blue", "right");
},1000);
// functions
function collisionObj(obj1, obj2, marginX, marginY){
if(marginX==null){
marginX = 0;
}
if(marginY==null){
marginY = 0;
}
if(obj1.x < obj2.x + obj2.w-marginX
&& obj1.x + obj1.w-marginX > obj2.x &&
obj1.y < obj2.y + obj2.h-marginY &&
obj1.h-marginY + obj1.y > obj2.y){
return true;
}
return false;
}
function mt_rand(minimum, maximum) {
minimum = parseInt(minimum, 10);
maximum = parseInt(maximum, 10);
return Math.floor(Math.random() * (maximum - minimum + 1)) + minimum;
}
function push(x,y, what,color, dir){
objects.push({
x: x,
y: y,
h: 50,
w: 50,
type: what,
color: color,
dir: dir,
});
}
// listeners
window.addEventListener('keydown', function(e){
keys[e.keyCode] = true;
}, false);
window.addEventListener('keyup', function(e){
delete keys[e.keyCode];
}, false);
I think the problem is along these lines:
if(collisionObj(obj, enemy)){
objects.splice(e,1);
objects.splice(i,1);
}
When you have a collision, you remove both the bullet (index e) and the enemy (index i). Whenever the enemy index is larger than the bullet's, after removing the bullet, the enemy index won't be correct anymore.
You have to remove the one that comes last first:
if(collisionObj(obj, enemy)){
if( e > i ){
objects.splice(e,1);
objects.splice(i,1);
}
else{
objects.splice(i,1);
objects.splice(e,1);
}
}
This is not a duplicate of the other question.
I found this talking about rotation about the center using XML, tried to implement the same using vanilla JavaScript like rotate(45, 60, 60) but did not work with me.
The approach worked with me is the one in the snippet below, but found the rect not rotating exactly around its center, and it is moving little bit, the rect should start rotating upon the first click, and should stop at the second click, which is going fine with me.
Any idea, why the item is moving, and how can I fix it.
var NS="http://www.w3.org/2000/svg";
var SVG=function(el){
return document.createElementNS(NS,el);
}
var svg = SVG("svg");
svg.width='100%';
svg.height='100%';
document.body.appendChild(svg);
class myRect {
constructor(x,y,h,w,fill) {
this.SVGObj= SVG('rect'); // document.createElementNS(NS,"rect");
self = this.SVGObj;
self.x.baseVal.value=x;
self.y.baseVal.value=y;
self.width.baseVal.value=w;
self.height.baseVal.value=h;
self.style.fill=fill;
self.onclick="click(evt)";
self.addEventListener("click",this,false);
}
}
Object.defineProperty(myRect.prototype, "node", {
get: function(){ return this.SVGObj;}
});
Object.defineProperty(myRect.prototype, "CenterPoint", {
get: function(){
var self = this.SVGObj;
self.bbox = self.getBoundingClientRect(); // returned only after the item is drawn
self.Pc = {
x: self.bbox.left + self.bbox.width/2,
y: self.bbox.top + self.bbox.height/2
};
return self.Pc;
}
});
myRect.prototype.handleEvent= function(evt){
self = evt.target; // this returns the `rect` element
this.cntr = this.CenterPoint; // backup the origional center point Pc
this.r =5;
switch (evt.type){
case "click":
if (typeof self.moving == 'undefined' || self.moving == false) self.moving = true;
else self.moving = false;
if(self.moving == true){
self.move = setInterval(()=>this.animate(),100);
}
else{
clearInterval(self.move);
}
break;
default:
break;
}
}
myRect.prototype.step = function(x,y) {
return svg.createSVGTransformFromMatrix(svg.createSVGMatrix().translate(x,y));
}
myRect.prototype.rotate = function(r) {
return svg.createSVGTransformFromMatrix(svg.createSVGMatrix().rotate(r));
}
myRect.prototype.animate = function() {
self = this.SVGObj;
self.transform.baseVal.appendItem(this.step(this.cntr.x,this.cntr.y));
self.transform.baseVal.appendItem(this.rotate(this.r));
self.transform.baseVal.appendItem(this.step(-this.cntr.x,-this.cntr.y));
};
for (var i = 0; i < 10; i++) {
var x = Math.random() * 100,
y = Math.random() * 300;
var r= new myRect(x,y,10,10,'#'+Math.round(0xffffff * Math.random()).toString(16));
svg.appendChild(r.node);
}
UPDATE
I found the issue to be calculating the center point of the rect using the self.getBoundingClientRect() there is always 4px extra in each side, which means 8px extra in the width and 8px extra in the height, as well as both x and y are shifted by 4 px, I found this talking about the same, but neither setting self.setAttribute("display", "block"); or self.style.display = "block"; worked with me.
So, now I've one of 2 options, either:
Find a solution of the extra 4px in each side (i.e. 4px shifting of both x and y, and total 8px extra in both width and height),
or calculating the mid-point using:
self.Pc = {
x: self.x.baseVal.value + self.width.baseVal.value/2,
y: self.y.baseVal.value + self.height.baseVal.value/2
};
The second option (the other way of calculating the mid-point worked fine with me, as it is rect but if other shape is used, it is not the same way, I'll look for universal way to find the mid-point whatever the object is, i.e. looking for the first option, which is solving the self.getBoundingClientRect() issue.
Here we go…
FIDDLE
Some code for documentation here:
let SVG = ((root) => {
let ns = root.getAttribute('xmlns');
return {
e (tag) {
return document.createElementNS(ns, tag);
},
add (e) {
return root.appendChild(e)
},
matrix () {
return root.createSVGMatrix();
},
transform () {
return root.createSVGTransformFromMatrix(this.matrix());
}
}
})(document.querySelector('svg.stage'));
class Rectangle {
constructor (x,y,w,h) {
this.node = SVG.add(SVG.e('rect'));
this.node.x.baseVal.value = x;
this.node.y.baseVal.value = y;
this.node.width.baseVal.value = w;
this.node.height.baseVal.value = h;
this.node.transform.baseVal.initialize(SVG.transform());
}
rotate (gamma, x, y) {
let t = this.node.transform.baseVal.getItem(0),
m1 = SVG.matrix().translate(-x, -y),
m2 = SVG.matrix().rotate(gamma),
m3 = SVG.matrix().translate(x, y),
mtr = t.matrix.multiply(m3).multiply(m2).multiply(m1);
this.node.transform.baseVal.getItem(0).setMatrix(mtr);
}
}
Thanks #Philipp,
Solving catching the SVG center can be done, by either of the following ways:
Using .getBoundingClientRect() and adjusting the dimentions considering 4px are extra in each side, so the resulted numbers to be adjusted as:
BoxC = self.getBoundingClientRect();
Pc = {
x: (BoxC.left - 4) + (BoxC.width - 8)/2,
y: (BoxC.top - 4) + (BoxC.height - 8)/2
};
or by:
Catching the .(x/y).baseVal.value as:
Pc = {
x: self.x.baseVal.value + self.width.baseVal.value/2,
y: self.y.baseVal.value + self.height.baseVal.value/2
};
Below a full running code:
let ns="http://www.w3.org/2000/svg";
var root = document.createElementNS(ns, "svg");
root.style.width='100%';
root.style.height='100%';
root.style.backgroundColor = 'green';
document.body.appendChild(root);
//let SVG = function() {}; // let SVG = new Object(); //let SVG = {};
class SVG {};
SVG.matrix = (()=> { return root.createSVGMatrix(); });
SVG.transform = (()=> { return root.createSVGTransformFromMatrix(SVG.matrix()); });
SVG.translate = ((x,y)=> { return SVG.matrix().translate(x,y) });
SVG.rotate = ((r)=> { return SVG.matrix().rotate(r); });
class Rectangle {
constructor (x,y,w,h,fill) {
this.node = document.createElementNS(ns, 'rect');
self = this.node;
self.x.baseVal.value = x;
self.y.baseVal.value = y;
self.width.baseVal.value = w;
self.height.baseVal.value = h;
self.style.fill=fill;
self.transform.baseVal.initialize(SVG.transform()); // to generate transform list
this.transform = self.transform.baseVal.getItem(0), // to be able to read the matrix
this.node.addEventListener("click",this,false);
}
}
Object.defineProperty(Rectangle.prototype, "draw", {
get: function(){ return this.node;}
});
Object.defineProperty(Rectangle.prototype, "CenterPoint", {
get: function(){
var self = this.node;
self.bbox = self.getBoundingClientRect(); // There is 4px shift in each side
self.bboxC = {
x: (self.bbox.left - 4) + (self.bbox.width - 8)/2,
y: (self.bbox.top - 4) + (self.bbox.height - 8)/2
};
// another option is:
self.Pc = {
x: self.x.baseVal.value + self.width.baseVal.value/2,
y: self.y.baseVal.value + self.height.baseVal.value/2
};
return self.bboxC;
// return self.Pc; // will give same output of bboxC
}
});
Rectangle.prototype.animate = function () {
let move01 = SVG.translate(this.CenterPoint.x,this.CenterPoint.y),
move02 = SVG.rotate(10),
move03 = SVG.translate(-this.CenterPoint.x,-this.CenterPoint.y);
movement = this.transform.matrix.multiply(move01).multiply(move02).multiply(move03);
this.transform.setMatrix(movement);
}
Rectangle.prototype.handleEvent= function(evt){
self = evt.target; // this returns the `rect` element
switch (evt.type){
case "click":
if (typeof self.moving == 'undefined' || self.moving == false) self.moving = true;
else self.moving = false;
if(self.moving == true){
self.move = setInterval(()=>this.animate(),100);
}
else{
clearInterval(self.move);
}
break;
default:
break;
}
}
for (var i = 0; i < 10; i++) {
var x = Math.random() * 100,
y = Math.random() * 300;
var r= new Rectangle(x,y,10,10,'#'+Math.round(0xffffff * Math.random()).toString(16));
root.appendChild(r.draw);
}
This is a query about something that popped up while I was experimenting with the canvas element via javascript. I wanted to have an array of points that formed a gradient which moved with time, which works perfectly apart from a bizarre pattern that comes up (only after the first wave or more), which also changes according to the number of columns and rows in the canvas (changing the size of the points just makes the patterns bigger or smaller, it's always on the same pixels.
Here's a little demo of what I mean with a bit of interface for you to mess around with, an example of the changing patterns is if the number of rows is changed to 0.75x the number of columns from the original (i.e. 40 columns, 30 rows).
http://codepen.io/zephyr/pen/GpwwWB
Javascript:
String.prototype.hexToRGBA = function(a) {
function cutHex(h) {
return (h.charAt(0) == "#") ? h.substring(1, 7) : h
}
var r = parseInt((cutHex(this)).substring(0, 2), 16);
var g = parseInt((cutHex(this)).substring(2, 4), 16);
var b = parseInt((cutHex(this)).substring(4, 6), 16);
return 'rgba(' + r.toString() + ',' + g.toString() + ',' + b.toString() + ',' + a.toString() + ')';
}
CanvasRenderingContext2D.prototype.clearDrawRect = function(shape) {
this.clearRect(shape.position.x, shape.position.y, shape.size, shape.size);
this.fillStyle = shape.color.base;
this.fillRect(shape.position.x, shape.position.y, shape.size, shape.size);
}
CanvasRenderingContext2D.prototype.render = function(render) {
(function animate() {
requestAnimationFrame(animate);
render();
})();
}
CanvasRenderingContext2D.prototype.renderAndThrottleFpsAt = function(fps, render) {
var fpsInterval, startTime, now, then, elapsed;
fpsInterval = 1000 / fps;
then = Date.now();
startTime = then;
(function animate() {
requestAnimationFrame(animate);
now = Date.now();
elapsed = now - then;
if (elapsed > fpsInterval) {
then = now - (elapsed % fpsInterval);
render();
}
})();
}
CanvasRenderingContext2D.prototype.pool = {};
CanvasRenderingContext2D.prototype.parsePoint = function(x, y, s, c) {
return {
color: c,
position: {
x: x,
y: y
},
size: s
}
}
CanvasRenderingContext2D.prototype.fillPointsPool = function(size, cols, rows, color) {
var i = cols;
var j = rows;
while(i--){
while(j--){
var x = i * size;
var y = j * size;
var a = (i * j) / (cols * rows);
var c = {
hex: color,
alpha: a,
dir: 1
};
if (typeof this.pool.points == 'undefined') {
this.pool.points = [this.parsePoint(x, y, size, c)];
} else {
this.pool.points.push(this.parsePoint(x, y, size, c));
}
}
j = rows;
}
}
CanvasRenderingContext2D.prototype.updatePointsPool = function(size, cols, rows, color) {
this.pool.points = [];
this.clearRect(0,0,this.canvas.width,this.canvas.height);
this.fillPointsPool(size, cols, rows, color);
}
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// Populate Points
var size = document.getElementById('size');
var cols = document.getElementById('cols');
var rows = document.getElementById('rows');
var color = document.getElementById('color');
ctx.fillPointsPool(size.value, cols.value, rows.value, color.value);
size.oninput = function(){
ctx.updatePointsPool(this.value, cols.value, rows.value, color.value);
}
cols.oninput = function(){
ctx.updatePointsPool(size.value, this.value, rows.value, color.value);
}
rows.oninput = function(){
ctx.updatePointsPool(size.value, cols.value, this.value, color.value);
}
color.oninput = function(){
ctx.updatePointsPool(size.value, cols.value, rows.value, this.value);
}
ctx.renderAndThrottleFpsAt(60, function(){
var i = 0;
var len = ctx.pool.points.length;
while (i<len) {
var point = ctx.pool.points[i];
// Change alpha for wave
var delta = 0.01;
point.color.alpha = point.color.alpha + (delta * point.color.dir);
if (point.color.alpha > 1) {
point.color.dir = -1;
} else if (point.color.alpha <= 0) {
point.color.dir = 1;
}
// Calculate rgba value with new alpha
point.color.base = point.color.hex.hexToRGBA(point.color.alpha);
ctx.clearDrawRect(point);
i++;
}
});
Do any of you have an idea of what's causing the pattern to appear, and any suggestions on a fix for this?
Note: I will be changing the updatePointsPool function
You are forgetting to clamp your alpha values when you change the direction. The small error in the alpha value accumulates slowly producing the unwanted artifacts you see as the animation progresses.
To fix add the top and bottom limits to alpha in the code just after you add delta direction to alpha.
if (point.color.alpha > 1) {
point.color.alpha = 1; // clamp alpha max
point.color.dir = -1;
} else if (point.color.alpha <= 0) {
point.color.alpha = 0; // clamp alpha min
point.color.dir = 1;
}
So I'm a newbie and should obviously spend time in the tuts, but I'm looking for a quick answer. Basically, I've created a grid of movie clips with AS3. When I 'preview' the flash (as a flash or HTML) it shows up fine. Success. Yet, the stage remains empty.
Q1) Will the stage remain empty as I have used AS3 to dynamically 'draw' the grid of mc's? Or is there a slit of code I am missing to make this baby show up on the stage?
Q2) I've managed to use alpha to make the MC's 'fade' on hover - but I want to make them change color (to red) when hovered over. I've searched everywhere and can't seem to find the right script.
Here is my code:
var stage = new createjs.Stage("canvas");
var image = new createjs.Bitmap("images/square.png");
stage.addChild(image);
createjs.Ticker.addEventListener("tick", handleTick);
function handleTick(event) {
image.x += 10;
stage.update();
}
var x0:Number = 0;
var y0:Number = 0;
var nt:Number = 72;
var nc = 10;
var vd:Number = 12;
var hd:Number = 12;
for (var i = 1; i <= nt; i++) {
var mc = this.attachMovie("square", "square" + i, i);
var aprox = Math.floor((i - 1) / nc);
mc._x = x0 + hd * ((i - aprox * nc) - 1);
mc._y = y0 + aprox * vd;
mc.useHandCursor = true;
// fade in
mc.onRollOver = function()
{
this.onEnterFrame = function()
{
if (this._alpha > 0) {
this._alpha -= 10;
} else {
this._alpha = 0;
delete this.onEnterFrame;
}
};
};
// fade out
mc.onRollOut = function()
{
this.onEnterFrame = function()
{
if (this._alpha < 100) {
this._alpha += 10;
} else {
this._alpha = 100;
delete this.onEnterFrame;
}
};
};
}
Thanks in advance - sorry I am a noob.
This will never work. 1/3 of your code is in AS3, 2/3 in AS2. Considering you haven't been thrown any error, I assume you exported it as AS2.