KineticJS canvas modified by CamanJS - javascript

I'm trying to apply CamanJS filter to a canvas created with KineticJS. It works:
Caman("#creator canvas", function()
{
this.lomo().render();
});
After applying a CamanJS filter I'm trying to do sth with canvas (eg. drag and move layer or just click on it), but then the canvas reverts to its original state (before applying CamanJS filter). So the question is: how to "tell" KineticJS to update cache(?) or do sth like stage.draw() to keep new canvas data?
Here is jsfiddle (click on "apply filter", when processing will be done, try to drag the star).
BTW: why is the processing so slow?
Thanks in advance.

As you've discovered, Kinetic will redraw the original image when it internally redraws.
Your Caman modified content is not used or saved.
To keep your Caman effect, you can create an offscreen canvas and instruct your Kinetic.Image to get its image from that offscreen canvas.
Then you can use Caman to filter that canvas.
The result is that Kinetic will do its internal redraws with your Caman modified canvas image.
Demo: http://jsfiddle.net/m1erickson/L3ACd/
Code Example:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Prototype</title>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.7.2.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/camanjs/3.3.0/caman.full.min.js"></script>
<style>
body{padding:20px;}
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:350px;
height:350px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);
// create an offscreen canvas
var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
// load the star.png
var img=new Image();
img.onload=start;
img.crossOrigin="anonymous";
img.src="https://dl.dropboxusercontent.com/u/139992952/stack1/star.png";
// when star.png is loaded...
function start(){
// draw the star image to the offscreen canvas
canvas.width=img.width;
canvas.height=img.height;
ctx.drawImage(img,0,0);
// create a new Kinetic.Image
// The image source is the offscreen canvas
var image1 = new Kinetic.Image({
x:10,
y:10,
image:canvas,
draggable: true
});
layer.add(image1);
layer.draw();
}
// lomo the canvas
// then redraw the kinetic.layer to display the lomo'ed canvas
$("#myButton").click(function(){
Caman(canvas, function () {
this.lomo().render(function(){
layer.draw();
});
});
});
}); // end $(function(){});
</script>
</head>
<body>
<button id="myButton">Lomo the draggable Star</button>
<div id="container"></div>
</body>
</html>

Related

How to delete image(element) from canvas

I am developing hotel floor view using canvas with the help of kinetic js.I want to provide an option to delete current dragged,dropped image on canvas.
this is my code for only drag drop of image and not with delete option :
// get a reference to the house icon in the toolbar
// hide the icon until its image has loaded
var $house=$("#house");
$house.hide();
// get the offset position of the kinetic container
var $stageContainer=$("#container");
var stageOffset=$stageContainer.offset();
var offsetX=stageOffset.left;
var offsetY=stageOffset.top;
// create the Kinetic.Stage and layer
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);
// start loading the image used in the draggable toolbar element
// this image will be used in a new Kinetic.Image
var image1=new Image();
image1.onload=function(){
$house.show();
}
image1.src="https://dl.dropboxusercontent.com/u/139992952/multple/4top.png";
// make the toolbar image draggable
$house.draggable({
helper:'clone',
});
// set the data payload
$house.data("url","house.png"); // key-value pair
$house.data("width","32"); // key-value pair
$house.data("height","33"); // key-value pair
$house.data("image",image1); // key-value pair
// make the Kinetic Container a dropzone
$stageContainer.droppable({
drop:dragDrop,
});
// handle a drop into the Kinetic container
function dragDrop(e,ui){
// get the drop point
var x=parseInt(ui.offset.left-offsetX);
var y=parseInt(ui.offset.top-offsetY);
// get the drop payload (here the payload is the image)
var element=ui.draggable;
var data=element.data("url");
var theImage=element.data("image");
// create a new Kinetic.Image at the drop point
// be sure to adjust for any border width (here border==1)
var image = new Kinetic.Image({
name:data,
x:x,
y:y,
image:theImage,
draggable: true
});
layer.add(image);
layer.draw();
}
body{padding:20px;}
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:350px;
height:350px;
}
#toolbar{
width:350px;
height:35px;
border:solid 1px blue;
}
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.7.2.min.js"></script>
<script src="http://code.jquery.com/ui/1.9.2/jquery-ui.min.js"></script>
<h4>Drag from toolbar onto canvas. Then drag around canvas.</h4>
<div id="toolbar">
<img id="house" width=32 height=32 src="https://dl.dropboxusercontent.com/u/139992952/multple/4top.png"><br>
</div>
<div id="container"></div>
You can use Kinetic to image.remove(), then layer.draw() to refresh the canvas, in similar fashion to this answer.
If you want to temporarily remove an image (and later re-add it) you use:
// temporarily remove the image from the layer
yourImage.remove();
yourLayer.draw();
// and later re-add it
yourLayer.add(yourImage);
yourLayer.draw();
But if you want to permanently delete the image (and recover all its resources) you use:
// permanently delete the image and reclaim all the resources it used
yourImage.destroy();
yourLayer.draw();

Extract individual frame from a sprite sheet using html or javascript

I have a sprite sheet consisting of 12 frames.
I want to extract each individual frame from it and want to show it in different canvas like below.
what i have tried so far is posted below
//HTML code for define the canvas area .
<body onload="image_render();">
<div id="image_area"> <canvas id="image"></canvas></div>
<script src="sprite_demo.js"></script>
</body>
// javascript to slice the image and assign to the canvas
var canvasImage = new Image();
canvasImage.src = "image/sprite_xxdpi.jpg";
var can= document.getElementById("image");
can.width = 500;
can.height = 300;
function image_render()
{
coin.render();
}
var coin = sprite({
context: can.getContext("2d"),
width: 500,
height: 300,
image: coinImage
});
function sprite (options) {
var that = {};
that.context = options.context;
that.width = options.width;
that.height = options.height;
that.image = options.image;
that.render = function () {
// Draw the animation
that.context.drawImage(
that.image,
0, //X-axis starting position from where slicing begins
0, //y-axis starting position from where slicing begins
that.width, //width of slicing image
that.height,//height of slicing image
0, //X-axis starting position where image will be drawn
0, //y-axis starting position where image will be drawn
150, // width of the resulting image
150); //height of the resulting image
};
return that;
}
I am only able to get a single image ,But I want to get all the images to show in a grid.And also i want to get the image to show any where I want.
I also want to scale down big size images to show in a grid and while taping on it I want to show the original image.
Note: I don't want to animate my frames, I just want to show in grid. There are mostly examples of sprite animation available on internet.
You have the correct version of drawImage to clip individual sprites from the spritesheet, but you must alter the values in drawImage for each sprite.
The "faces" example spritesheet you show appear to have equal sized individual sprites (75px by 75px).
Assuming all your sprites are the same size, you would alter the 2nd & 3rd drawImage parameters which tell canvas the top-left x/y coordinate to begin clipping on the spritesheet.
Here's example code and a Demo: http://jsfiddle.net/m1erickson/tVD2K/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var spriteWidth=75;
var spriteHeight=75;
var spriteCols=4;
var spriteRows=3;
var y=20-sprightHeight;
var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/spritesheet1.jpg";
function start(){
var canvasY=0;
for(var col=0;col<spriteCols;col++){
for(var row=0;row<spriteRows;row++){
var sourceX=col*spriteWidth;
var sourceY=row*spriteHeight;
// testing: calc a random position to draw this sprite
// on the canvas
var canvasX=Math.random()*150+20;
canvasY+=spriteHeight+5;
// drawImage with changing source and canvas x/y positions
ctx.drawImage(img,
sourceX,sourceY,spriteWidth,spriteHeight,
canvasX,canvasY,spriteWidth,spriteHeight
);
}}
}
}); // end $(function(){});
</script>
</head>
<body>
<h4>Draw individual sprites from a spritesheet</h4>
<canvas id="canvas" width=300 height=1000></canvas>
</body>
</html>

How can i improve the performance of drawing an animation path?

I drew a rectangle with kinetic.js and animating it in a circular path. In each animation frame i reduce it's radius, and i draw animating path of this object by kineticJS Line. But This Kinetics animation loop develops an undesirable pausing "stagger". This stagger is small in Chrome, noticeable in IE and horrible in FireFox. This seems to be due to the Kinetic.Line being unable to smoothly add + draw thousands of changing points of data. How can make this animation flawless, smooth. It would be great help if you give me the link of a jsfiddle. Bunches of thanks in advance.
CODES:
var R= 80;
$(document).ready(function(){
var stage= new Kinetic.Stage({
container: 'container',
width:500,
height:500
});
var layer = new Kinetic.Layer();
var line = new Kinetic.Line({
points:[0,0,0,0],
stroke:'blue',
strokeWidth:2
});
var rect = new Kinetic.Rect({
x:10,
y:10,
width:10,
height: 10,
fill:'black',
stroke:'red'
});
layer.add(rect);
layer.add(line);
stage.add(layer);
var centerX = stage.width()/2;
var points=[];
var anim = new Kinetic.Animation(
function(f){
var cX= stage.width()/2;
var cY= stage.height()/2;
R=R-1/100;
var X = cX + R*Math.cos(f.time/1000);
var Y = cY+ R*Math.sin(f.time/1000);
points.push(X,Y);
line.setPoints(points);
rect.setX(X);
rect.setY(Y);
}
,layer);
anim.start();
});
JSFIDDLE: http://jsfiddle.net/tanvirgeek/n8z8N/7/
Thanks In advance.
As you’ve discovered, updating and drawing a Kinetic.Line containing thousands of line segments causes a noticable lag.
One Kinetic trick that I rarely seen used is useful to create a lag-free animation of thousands of line segments.
First, draw your line segments on an off-screen html5 canvas. When a new line segment is needed, just add that segment to all the pre-existing segments. This is very efficient because only the last line segment needs to be drawn.
You can use a Kinetic.Image to display the offscreen html5 canvas on the screen.
The trick is to set the Kinetic.Image image-source to the html canvas: myKineticImage.setImage(myOffscreenCanvas). This works because “behind the scenes” the Kinetic.Image is using context.drawImage to display its image. Since context.drawImage can also accept another canvas as its image-source, you can efficiently display the current offscreen canvas drawings.
A Demo: http://jsfiddle.net/m1erickson/rYC96/
And example code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Prototype</title>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.0.1.min.js"></script>
<style>
body{padding:20px;}
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:350px;
height:350px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);
// variables used to set the stage and animate
var rectSize=15;
var cx=stage.getWidth()/2;
var cy=stage.getHeight()/2;
var R=100;
var A=0;
var deltaA=Math.PI/180;
var lastX=cx+R*Math.cos(A);
var lastY=cy+R*Math.sin(A);
// the html canvas incrementally draws the line segments
// which are in turn displayed as a Kinetic.Image (called line)
var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
canvas.width=stage.getWidth();
canvas.height=stage.getHeight();
ctx.strokeStyle="blue";
ctx.lineWidth=2;
// this Kinetic.Image exactly displays the current html canvas drawings
// (this trick cures the lags)
var line=new Kinetic.Image({
x:0,
y:0,
width:canvas.width,
height:canvas.height,
image:canvas
});
layer.add(line);
// the rotating Kinetic.Rectangle
var rect = new Kinetic.Rect({
x:lastX,
y:lastY,
width:rectSize,
height:rectSize,
fill:'black',
stroke:'red'
});
layer.add(rect);
// use requestAnimationFrame (RAF) to drive the animation
// RAF efficiently schedules animation frames with display
function animate(){
// stop animating when rect reaches center
if(R<=rectSize/2){return;}
// schedule another animation frame even before this one is done
requestAnimationFrame(animate);
// calc the new XY position
R=R-.01;
A+=deltaA;
var X=cx+R*Math.cos(A);
var Y=cy+R*Math.sin(A);
// animate the rect and line to their next position
// draw just the latest line segment to the canvas
// (all the previous line segments are still there--no need to redraw them)
ctx.beginPath();
ctx.moveTo(lastX,lastY);
ctx.lineTo(X,Y);
ctx.stroke();
// set lastXY for next frame
lastX=X;
lastY=Y;
// update the rect position
rect.setX(X);
rect.setY(Y);
// draw the changed line-image and rect to the kinetic layer
layer.draw();
}
// start animating!
animate();
}); // end $(function(){});
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>

AjaxToolKit: Balloon Popup Extender on html5 Canvas

I have a canvas drawing implemented on my project. I would like to show speech-bubbles with information related to specific mouse clicks on the canvas. Say a click on a particular region of my canvas allows for a popup that gives text information about that region on the canvas.
<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.0.min.js"></script>
<ajaxToolkit:BalloonPopupExtender ID="BalloonPopupExtender1"
runat="server"
TargetControlID="myCanvas"
BalloonPopupControlID="Panel1"
Position="TopLeft"
BalloonStyle="Cloud"
BalloonSize="Small"
CustomCssUrl="CustomStyle/BalloonPopupOvalStyle.css"
CustomClassName="oval"
UseShadow="true"
ScrollBars="Auto"
DisplayOnMouseOver="true"
DisplayOnFocus="false"
DisplayOnClick="true" />
<canvas id="myCanvas" width="915" height="850" style="border: 2px double #000000;"></canvas>
<script type="text/javascript">
However this doesn't work, I believe this is because myCanvas is not a asp.net/server side element, hence runat ="server" isn't correct methodology.
I am currently following these blogs:-
http://www.c-sharpcorner.com/UploadFile/364074/balloonpopupextendercontrol-in-ajax/
http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/BalloonPopup/BalloonPopupExtender.aspx
Any idea how to implement the popup on the canvas, upon a click?
Given that you want to respond to clicks on specific canvas coordinates, you might have to work on the client side. Here's code to do an info popup on the client side.
This is code that will draw an info balloon inside a separate canvas element. The canvas is moved off-screen until it's needed. You can of course, style this popup balloon in any way you want because it's a canvas element!
<canvas id="balloon" width=105 height=105></canvas>
function drawBalloon(X,Y,theInfo){
popCtx.save();
popCtx.fillStyle="#FD0";
popCtx.strokeStyle="#000";
// draw the balloon
popCtx.beginPath();
popCtx.moveTo(52,02);
popCtx.quadraticCurveTo(02,02,02,42);
popCtx.quadraticCurveTo(02,77,27,77);
popCtx.quadraticCurveTo(27,102,07,102);
popCtx.quadraticCurveTo(37,102,42,77);
popCtx.quadraticCurveTo(102,77,102,42);
popCtx.quadraticCurveTo(102,02,52,02);
popCtx.lineWidth=3;
popCtx.stroke();
popCtx.fill();
// draw theInfo
popCtx.font="10pt arial";
popCtx.fillStyle="black";
popCtx.fillText(theInfo,10,50);
popCtx.restore();
// move the balloon canvas to the target
$("#balloon").css({left:offsetX+X, top:offsetY+Y});
}
If you're not used to client-side javascript, here's how to get the position of the target-filled canvas relative to the window
<canvas id="canvas" width=300 height=300></canvas>
// get the position of canvas relative to window
var canvasOffset=$("#canvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
And here's how to listen for clicks on the target-filled canvas.
// listen for clicks on the canvas
$("#canvas").click(function(e){
// get the mouseclick position
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// see if we clicked on any targets, show the balloon
for(var i=0;i<circles.length;i++){
var circle=circles[i];
var dx=circle.x-mouseX;
var dy=circle.x-mouseY;
var radius=circle.radius;
// true if we clicked in the target circle
if(dx*dx+dy*dy<=radius*radius){
drawBalloon(circles[i].x+radius,circles[i].y-100,circles[i].info);
}
}
});
To test if any target location on the canvas was clicked, we can test a circular area around the target like this:
var dx=targetCircle.x-mouseX;
var dy=targetCircle.x-mouseY;
var radius=targetCircle.radius;
// true if we clicked in the target circle
if(dx*dx+dy*dy<=radius*radius){
// we hit a target, display the balloon
}
Here is working example code and a Fiddle: http://jsfiddle.net/m1erickson/AJvkN/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; padding:10px;padding-top:100px; }
#canvas{border:1px solid red;}
#balloon{ position:absolute; left:-200px; }
</style>
<script>
$(function(){
// get reference to our drawing canvas
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
// get reference to our balloon canvas
var balloon=document.getElementById("balloon");
var popCtx=balloon.getContext("2d");
// get the position of canvas relative to window
var canvasOffset=$("#canvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
// define some targets and their basic info
var circles=[];
circles.push({x:40, y:30, radius:15,color:"red", info:"I'm red."});
circles.push({x:150, y:150,radius:25,color:"green",info:"I'm centered."});
circles.push({x:110, y:85, radius:40,color:"blue", info:"I'm big."});
// draw the target circles on the canvas
for(var i=0;i<circles.length;i++){
drawCircle(circles[i]);
}
// listen for clicks on the canvas and show the balloon
$("#canvas").click(function(e){
// get the mouseclick position
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// see if we clicked on any targets
for(var i=0;i<circles.length;i++){
var circle=circles[i];
var dx=circle.x-mouseX;
var dy=circle.x-mouseY;
var radius=circle.radius;
// true if we clicked in the target circle
if(dx*dx+dy*dy<=radius*radius){
drawBalloon(circles[i].x+radius,circles[i].y-100,circles[i].info);
}
}
});
// listen for clicks on the balloon and then hide the balloon
$("#balloon").click(function hideBalloon(e){ $("#balloon").css({left:-200}); });
function drawCircle(circle){
ctx.save();
ctx.beginPath();
ctx.fillStyle=circle.color;
ctx.strokeStyle="black";
ctx.lineWidth=3;
ctx.arc(circle.x,circle.y,circle.radius,0,Math.PI*2,false);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
}
function drawBalloon(X,Y,theInfo){
popCtx.save();
popCtx.fillStyle="#FD0";
popCtx.strokeStyle="#000";
// draw the balloon
popCtx.beginPath();
popCtx.moveTo(52,02);
popCtx.quadraticCurveTo(02,02,02,42);
popCtx.quadraticCurveTo(02,77,27,77);
popCtx.quadraticCurveTo(27,102,07,102);
popCtx.quadraticCurveTo(37,102,42,77);
popCtx.quadraticCurveTo(102,77,102,42);
popCtx.quadraticCurveTo(102,02,52,02);
popCtx.lineWidth=3;
popCtx.stroke();
popCtx.fill();
// draw theInfo
popCtx.font="10pt arial";
popCtx.fillStyle="black";
popCtx.fillText(theInfo,10,50);
popCtx.restore();
// move the balloon canvas to the target
$("#balloon").css({left:offsetX+X, top:offsetY+Y});
}
}); // end $(function(){});
</script>
</head>
<body>
<p>Click circles to popup an info balloon</p>
<p>When info balloon appears, click it do dismiss it</p>
<canvas id="canvas" width=300 height=300></canvas>
<canvas id="balloon" width=105 height=105></canvas>
</body>
</html>

HTML5 Canvas: How to make a loading spinner by rotating the image in degrees?

I am making a loading spinner with html5 canvas. I have my graphic on the canvas but when i rotate it the image rotates off the canvas. How do I tell it to spin the graphic on its center point?
<!DOCTYPE html>
<html>
<head>
<title>Canvas test</title>
<script type="text/javascript">
window.onload = function() {
var drawingCanvas = document.getElementById('myDrawing');
// Check the element is in the DOM and the browser supports canvas
if(drawingCanvas && drawingCanvas.getContext) {
// Initaliase a 2-dimensional drawing context
var context = drawingCanvas.getContext('2d');
//Load the image object in JS, then apply to canvas onload
var myImage = new Image();
myImage.onload = function() {
context.drawImage(myImage, 0, 0, 27, 27);
}
myImage.src = "img/loading.png";
context.rotate(45);
}
}
</script>
</head>
<body>
<canvas id="myDrawing" width="27" height="27">
</canvas>
</body>
</html>
Here is the complete working example:)
<!DOCTYPE html>
<html>
<head>
<title>Canvas Cog</title>
<script type="text/javascript">
var cog = new Image();
function init() {
cog.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAYAAACN1PRVAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABK1JREFUeNqMVt1ZGzkUvVfS4IW1l8GO82w6IBXE7mCpAFMB+Pt4Z6iApALcAe4AU0HoAJfg7BPYHinnXmmciX+y0YdmJHnQ0bk/R5cvh5cUyFPwRD4EChgEvGWMB36R3+JaiTkmD5gOs8yNb25uLlerFf1pM2yIGA82TEY7xow1oj4GBU6S6yywPNG4JwDH+XGv0Whs7ndN8n97mmPsLCSYgy7ImPQE/pFDyAF+7L0fgTNFUDBcLal90taD1doQ/T6NT9DnW8zkT+jJuQVYukG3hifCVk/L3JOxMBa8VVlSp9MhHKLaB+zpNo1fdgEpmByuMqUAV5viOQLwXNax9KBAFNEEpN1pUwnQmvl6aTza6zNjrCKaymeyOdYAMgfg18iG4T/qw+AC94zvpzDjcwqOXo3VGH26H0xMZ7jPxgT0R2zUi4BYt6bAfEbJvJFZKA4ODgZ5nhcJLE9mk35X21vWC/TXKmiwr2xszoQd/PQv3t/QCzY2twpqBpb5FKOp+hCgzWaTWq0W1Xx0ij5An9WC5VtiLMwvNBrVaSGMvQk5jHQVPN7sb0HzAtE+QJrNgrcUNEARieWCut0ugR0tl8sKcJ5Ahc3jRviPK8ZGTaaBwGKyT+gTiwM4a3Jrba6MbeVXo5F4kp9shn29ndUYC9vLirGDXzRhrYhD8DME5Hkg22df5rDYS/RXmVIsaP/Q/SXs600YnifTjbeSWliEdTYb3QyTqYfdDKTL4B1KS6tVqf6SgGq3P9BvZGpvNIrPCgVKZlGlCDQDxJiCjVppCab05DJHzb+b1Gm36X80cVjLuzozexs0f6IgRkA5XRhzIixRL1+IzhwdHVHrn1Y9oXe1i10aKT6bGGhg1CKK+cT0zCGCs0oXTIogybJMw/779//o48duMvnO9rzLn+Kz8wgS5Shqo4njpCoOQA5Ajb8adHh4SMvVghaLhYb/HsBip88krNVISSEigOlhjmi0LziNhr6wOsgO9C1339vbGznnNAU2AM9Svk235cqKieKGkldAf7DGvTrjnjJnzyQoMu0ZTuZgUqvmlYR+f39XIE4uqCX1E/rDZpCYmKwOOmivAfYK9KF1AM7EdG4uAMLAOjmQideQXOJQkyUisqYiFRhtSFbxCxj8do0T30dmTvLhC+an0MZZVBHX09tBTG4qFigZEJEChjTIEwtRik81Qa7uOQU0IrYAe7FRjqYw6SlYjgAyN1GmHsFIGPfVnxzFuFITKEkfYK+oWZ5qKlIkcZ7UE92oXBmeIgIxtAO5UtSHqo9uiLW+sme5ejSIRASeAFR4LYy8MMzL1aq3EYWzJF28BgMEzGYpBkrMKelgl+P6uTcVY8NjLYyYPwMTCcufSaouH6al9xNJcjC82vDb9uVZKbrWIumNO+waVsu1TCC+Wxcg6xaSpsZSYM2wLO9/U8qZWH+wztQnsfAxV/E3MIKZVf1FsmJVV8mamhEmxZ0X7sSsABsGv1tZJGejmptU7FBUDYzPAXQBwFEEl+9+stFEroJEci2ELwIMmZuWoSTE9DYYcWVCjlJrZWMpeBhlAEqBiulPE84S3ixU5gSTwGGOdyEVNJXxA8nPevshwABHktBS1YoQ+QAAAABJRU5ErkJggg=='; // Set source path
setInterval(draw,10);
}
var rotation = 0;
function draw(){
var ctx = document.getElementById('myCanvas').getContext('2d');
ctx.globalCompositeOperation = 'destination-over';
ctx.save();
ctx.clearRect(0,0,27,27);
ctx.translate(13.5,13.5); // to get it in the origin
rotation +=1;
ctx.rotate(rotation*Math.PI/64); //rotate in origin
ctx.translate(-13.5,-13.5); //put it back
ctx.drawImage(cog,0,0);
ctx.restore();
}
init();
</script>
</head>
<body>
<canvas width="27" height="27" id="myCanvas"></canvas>
</body>
</html>
rotate turns the canvas(?) around your current position, which is 0, 0 to start. you need to "move" to your desired center point, which you can accomplish with
context.translate(x,y);
after you move your reference point, you want to center your image over that point. you can do this by calling
context.drawImage(myImage, -(27/2), -(27/2), 27, 27);
this tells the browser to start drawing the image from above and to the left of your current reference point, by have the size of the image, whereas before you were starting at your reference point and drawing entirely below and to the right (all directions relative to the rotation of the canvas).
since your canvas is the size of your image, your call to translate will use the same measurement, (27/2), for x and y coordinates.
so, to put it all together
// initialization:
context.translate(27/2, 27/2);
// onload:
context.rotate(Math.PI * 45 / 180);
context.drawImage(myImage, -(27/2), -(27/2), 27, 27);
edit: also, rotation units are radians, so you'll need to translate degrees to radians in your code.
edits for rearranging stuff.
For anyone else looking into something like this, you might want to look at this script which does exactly what was originally being requested:
http://projects.nickstakenburg.com/spinners/
You can find the github source here:
https://github.com/staaky/spinners
He uses rotate, while keeping a cache of rectangles which slowly fade out, the older they are.
I find another way to do html loading spinner. You can use sprite sheet animation. This approach can work both by html5 canvas or normal html/javascript/css. Here is a simple way implemented by html/javascript/css.
It uses sprite sheet image as background. It create a Javascript timer to change the background image position to control the sprite sheet animation. The example code is below. You can also check the result here: http://jmsliu.com/1769/html-ajax-loading-spinner.html
<html>
<head><title></title></head>
<body>
<div class="spinner-bg">
<div id="spinner"></div>
</div>
<style>
.spinner-bg
{
width:44px;
height:41px;
background: #000000;
}
#spinner
{
width: 44px;
height: 41px;
background:url(./preloadericon.png) no-repeat;
}
</style>
<script>
var currentbgx = 0;
var circle = document.getElementById("spinner");
var circleTimer = setInterval(playAnimation, 100);
function playAnimation() {
if (circle != null) {
circle.style.backgroundPosition = currentbgx + "px 0";
}
currentbgx -= 44; //one frame width, there are 5 frame
//start from 0, end at 176, it depends on the png frame length
if (currentbgx < -176) {
currentbgx = 0;
}
}
</script>
</body>

Categories

Resources