HTML Editor
<!DOCTYPE html> <html lang="en-US"> <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <style> #canvas { background:red; background-image: url("wall.jpg"); background-size: 510px 310px; background-repeat: no-repeat; cursor: pointer; -webkit-box-shadow: 4px 4px 8px rgba(0,0,0,0.5); -moz-box-shadow: 4px 4px 8px rgba(0,0,0,0.5); box-shadow: 4px 4px 8px rgba(0,0,0,0.5); display:block; margin:0 auto; } #bBtn{ background-color: #4CAF50; border: #2f6a31; color: white; padding: 14px; letter-spacing:3px; width:120px; text-align: center; text-decoration: none; display:block; margin:15px auto; font-size: 16px; } </style> </head> <body> <canvas id='canvas' width='510' height='310'> </canvas> <button id="bBtn">Play</button> <script> var ImagePainter = function(imageUrl){ this.image = new Image; this.image.src = imageUrl; }; ImagePainter.prototype = { image: undefined, paint: function(sprite, context){ if(this.image !== undefined){ if(!this.image.complete){ this.image.onload = function(e){ sprite.width = this.width; sprite.height = this.height; context.drawImage(this, // this is image sprite.left, sprite.top, sprite.width, sprite.height); }; } else{ context.drawImage(this.image, sprite.left, sprite.top, sprite.width, sprite.height); } } } }; SpriteSheetPainter = function(cells) { this.cells = cells; }; SpriteSheetPainter.prototype = { cells: [], cellIndex: 0, advance: function(){ if(this.cellIndex == this.cells.length-1){ this.cellIndex = 0; } else{ this.cellIndex++; } }, paint: function(sprite, context){ var cell = this.cells[this.cellIndex]; context.drawImage(spritesheet, cell.left, cell.top, cell.width, cell.height, sprite.left, sprite.top, cell.width, cell.height); } }; var SpriteAnimator = function(painters, elapsedCallback){ this.painters = painters; if(elapsedCallback){ this.elapsedCallback = elapsedCallback; } }; SpriteAnimator.prototype = { painters: [], duration: 1000, startTime: 0, index: 0, elapsedCallback: undefined, end: function(sprite, originalPainter){ sprite.animating = false; if(this.elapsedCallback){ this.elapsedCallback(sprite); } else{ sprite.painter = originalPainter; } }, start: function(sprite, duration){ var endTime = +new Date() + duration, period = duration / (this.painters.length), interval = undefined, animator = this, // for setInterval() function originalPainter = sprite.painter; this.index = 0; sprite.animating = true; sprite.painter = this.painters[this.index]; interval = setInterval(function(){ if(+new Date() < endTime){ sprite.painter = animator.painters[++animator.index]; } else { animator.end(sprite, originalPainter); clearInterval(interval); } }, period); }, }; var Sprite = function(name, painter, behaviors){ if(name !== undefined) this.name = name; if(painter !== undefined) this.painter = painter; if(behaviors !== undefined) this.behaviors = behaviors; return this; }; Sprite.prototype = { left: 0, top: 0, width: 10, height: 10, velocityX: 0, velocityY: 0, visible: true, animating: false, painter: undefined, // object with paint(sprite, context) behaviors: [], // objects with execute(sprite, context, time) paint: function(context){ if(this.painter !== undefined && this.visible){ this.painter.paint(this, context); } }, update: function(context, time){ for (var i = this.behaviors.length; i > 0; --i){ this.behaviors[i-1].execute(this, context, time); } } }; </script> <script> window.requestNextAnimationFrame = (function(){ var originalWebkitRequestAnimationFrame = undefined, wrapper = undefined, callback = undefined, geckoVersion = 0, userAgent = navigator.userAgent, index = 0, self = this; if(window.webkitRequestAnimationFrame){ // Define the wrapper wrapper = function(time){ if(time === undefined){ time = +new Date(); } self.callback(time); }; // Make the switch originalWebkitRequestAnimationFrame = window.webkitRequestAnimationFrame; window.webkitRequestAnimationFrame = function(callback, element){ self.callback = callback; // Browser calls the wrapper and wrapper calls the callback originalWebkitRequestAnimationFrame(wrapper, element); } } // Workaround for Gecko 2.0, which has a bug in // mozRequestAnimationFrame() that restricts animations // to 30-40 fps. if(window.mozRequestAnimationFrame){ // Check the Gecko version. Gecko is used by browsers // other than Firefox. Gecko 2.0 corresponds to // Firefox 4.0. index = userAgent.indexOf('rv:'); if(userAgent.indexOf('Gecko') != -1){ geckoVersion = userAgent.substr(index + 3, 3); if(geckoVersion === '2.0'){ // Forces the return statement to fall through // to the setTimeout() function. window.mozRequestAnimationFrame = undefined; } } } return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback, element){ var start, finish; window.setTimeout( function(){ start = +new Date(); callback(start); finish = +new Date(); self.timeout = 1000 / 60 - (finish - start); }, self.timeout); }; } )(); </script> <script> var canvas = document.getElementById('canvas'), context = canvas.getContext('2d'), ball = new Sprite('ball', { paint: function(sprite, context){ context.save(); context.strokeStyle = 'blue'; context.fillStyle = 'yellow'; context.beginPath(); context.arc(sprite.left + sprite.width/2, sprite.top + sprite.height/2, 10, 0, Math.PI*2, false); context.stroke(); context.fill(); context.restore(); } }), ballMoving = false, lastTime = undefined, velocityX = 350, velocityY = 190; // Functions..................................................... function windowToCanvas(e){ var x = e.x || e.clientX, y = e.y || e.clientY, bbox = canvas.getBoundingClientRect(); return { x: x - bbox.left * (canvas.width / bbox.width), y: y - bbox.top * (canvas.height / bbox.height) }; }; function getBoundingBox(ball){ return { left: ball.left, top: ball.top, width: ball.width, height: ball.height }; } function handleEdgeCollisions(){ var bbox = getBoundingBox(ball), right = bbox.left + bbox.width, bottom = bbox.top + bbox.height; if(right > canvas.width || bbox.left < 0){ velocityX = -velocityX; if(right > canvas.width){ ball.left -= right-canvas.width; } if(bbox.left < 0){ ball.left -= bbox.left; } } if(bottom > canvas.height || bbox.top < 0){ velocityY = -velocityY; if(bottom > canvas.height){ ball.top -= bottom-canvas.height; } if(bbox.top < 0){ ball.top -= bbox.top; } } }; function detectCollisions(){ if(ballMoving){ handleEdgeCollisions(); } }; function isPointInBall(x, y){ return x > ball.left && x < ball.left + ball.width && y > ball.top && y < ball.top + ball.height; } // Event Handlers................................................ $("#bBtn").click(function(e){ if(ballMoving){ $("#bBtn").text("Play"); } else{ $("#bBtn").text("Pause"); } var location = windowToCanvas(e); ballMoving = !ballMoving; }); // Animation..................................................... function animate(time){ var elapsedTime; if(lastTime === 0){ lastTime = time; } else{ context.clearRect(0,0,canvas.width,canvas.height); if(ballMoving){ elapsedTime = parseFloat(time - lastTime) / 1000; ball.left += velocityX * elapsedTime; ball.top += velocityY * elapsedTime; detectCollisions(); } lastTime = time; ball.paint(context); } window.requestNextAnimationFrame(animate); }; // Initialization................................................ ball.fillStyle = 'rgba(255,255,0,1.0)'; ball.left = 100; ball.top = 100; context.shadowColor = 'rgba(100,140,255,0.5)'; context.shadowBlur = 4; context.shadowOffsetX = 2; context.shadowOffsetY = 2; context.font = '38px Arial'; window.requestNextAnimationFrame(animate); </script> </body> </html>
OUTPUT
×

Save as Private