Properties lost when copying HTML canvas or converting toDataURL - html

I'm using a native HTML 5 canvas to create a text effect then attempting to create an image from the canvas or copy the canvas to a fabric.js object, but the output doesn't reflect the changes done to the text.
Fiddle: https://jsfiddle.net/rf8kdxq1/2/
Something simple I hope?
var ctx = demo.getContext('2d'),
font = '64px impact',
w = demo.width,
h = demo.height,
curve,
offsetY,
bottom,
textHeight,
isTri = false,
dltY,
angleSteps = 180 / w,
i = w,
y,
os = document.createElement('canvas'),
octx = os.getContext('2d');
os.width = w;
os.height = h;
octx.font = font;
octx.textBaseline = 'top';
octx.textAlign = 'center';
curve = parseInt(110, 10);
offsetY = parseInt(4, 10);
textHeight = parseInt(64, 10);
bottom = parseInt(200, 10);
octx.fillText('BRIDGE', w * 0.5, 0);
/// slide and dice
i = w;
dltY = curve / textHeight;
y = 0;
while (i--) {
y = bottom - curve * Math.sin(i * angleSteps * Math.PI / 180);
ctx.drawImage(os, i, 0, 1, textHeight,
i, h * 0.5 - offsetY / textHeight * y, 1, y);
}
// ctx.drawImage(os, i, 0);
dataURL = os.toDataURL();
img = new Image();
img.src = dataURL;
img.onload = function() {
console.log(img);
};
var newCanv = new fabric.Canvas('canvasd');
function xfer() {
var image = new fabric.Image(os);
setTimeout(function() {
newCanv.add(image);
},500);
}
xfer();

Related

How to display image landscape

I have a website which targets mobile phones, if a user clicks on a 16:9 scaled responsive image, I want clicked image to be displayed landscape, so that the user can rotate his phone to view the image in full size. I can't save the image rotated because it is an external resource. Is there any way I can achieve the desired effect?
I can't simply rotate 90° because that would rotate the scaled image.
If I rotate the unscaled image, it extends the portrait viewport to landscape width and displays the rotated image centered.
I already tried using a canvas, but it didn't nearly fit my needs, the image gets destroyed by bad downscaling on Firefox using JSFiddle while it didn't display at all on the Intel XDK emulator.
Since my scenario doesn't seem that uncommon to me, I'm wondering whether I missed an easy solution.
Found a jsfiddle doing that, and made it simpler for you.
Check it out: http://jsfiddle.net/7fw66/39/
html:
<div>
<canvas id="canvas"><img id="image" src="http://3.bp.blogspot.com/-JhISDA9aj1Q/UTECr1GzirI/AAAAAAAAC2o/5qmvWZiCMRQ/s1600/Twitter.png" /></canvas>
</div>
javascript:
var screenwidth = 400;
var imgurl = "http://3.bp.blogspot.com/-JhISDA9aj1Q/UTECr1GzirI/AAAAAAAAC2o/5qmvWZiCMRQ/s1600/Twitter.png";
$(document).ready(function () {
loadImage();
$('#restore').click(function () {
loadImage();
});
$('#rotate_ccw').click(function () {
rotate_ccw();
});
$('#rotate_cw').click(function () {
rotate_cw();
});
});
function loadImage() {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.setTransform(1, 0, 0, 1, 0, 0);
var img = new Image();
if (imgurl == null || imgurl == "") {
imgurl = defaultimgurl;
}
img.src = imgurl;
var maxsize = screenwidth;
var w = maxsize;
var ratio = (img.width / w);
var h = (img.height / ratio);
canvas.width = w;
canvas.height = h;
img.onload = function () {
ctx.drawImage(img, 0, 0, w, h);
};
ctx.save();
}
function rotate_cw() {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var img = new Image();
img.src = imgurl;
var maxsize = screenwidth;
var w = maxsize;
var ratio = (img.width / w);
var h = (img.height / ratio);
canvas.width = h;
canvas.height = w;
ctx.translate(w - h, w);
ctx.rotate((-90 * Math.PI) / 180);
ctx.translate(0, -(w - h));
ctx.drawImage(img, 0, 0, w, h);
ctx.save();
}
function rotate_ccw() {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var img = new Image();
img.src = imgurl;
var maxsize = screenwidth;
var w = maxsize;
var ratio = (img.width / w);
var h = (img.height / ratio);
canvas.width = h;
canvas.height = w;
ctx.translate(h, 0);
ctx.rotate((90 * Math.PI) / 180);
ctx.drawImage(img, 0, 0, w, h);
ctx.save();
}
function urlProvided() {
var userinput = document.getElementById('imageurl');
imgurl = userinput.value;
loadImage();
}

How to make rooftext effect and valley text effect in HTML5 (or Fabric.js)

I am using below code:
<script type='text/javascript'>//<![CDATA[
window.onload=function(){
/// (c) Ken Fyrstenberg Nilsen, Abidas Software .com
/// License: CC-Attribute
var ctx = demo.getContext('2d'),
font = '64px impact',
w = demo.width,
h = demo.height,
curve,
offsetY,
bottom,
textHeight,
angleSteps = 255/h,
i = h,
y,
os = document.createElement('canvas'),
octx = os.getContext('2d');
os.width = w;
os.height = h;
octx.font = font;
octx.textBaseline = 'top';
octx.textAlign = 'center';
function renderBridgeText() {
curve = parseInt(iCurve.value, 10);
offsetY = parseInt(iOffset.value, 10);
textHeight = parseInt(iHeight.value, 10);
bottom = parseInt(iBottom.value, 10);
vCurve.innerHTML = curve;
vOffset.innerHTML = offsetY;
vHeight.innerHTML = textHeight;
vBottom.innerHTML = bottom;
octx.clearRect(0, 0, w, h);
ctx.clearRect(0, 0, w, h);
octx.fillText(iText.value, w * 0.5, 0);
/// slide and dice
i = w;
while (i--) {
y = bottom + curve * Math.sin(i / angleSteps * Math.PI /160);
ctx.drawImage(os, i, offsetY, 1, textHeight,i,offsetY, 1, y);
}
}
iCurve.onchange = iOffset.onchange = iHeight.onchange = iBottom.onchange = iText.onkeyup = renderBridgeText;
renderBridgeText()
}//]]>
</script>
</head>
<body>
<canvas id=demo width=600 height=300></canvas>
<br>
<span>Curve:</span>
<input id="iCurve" type="range" min=0 max=200 value=110>
<span id="vCurve">110</span>
<br><span>OffsetY:</span>
<input id="iOffset" type="range" min=0 max=100 value=4>
<span id="vOffset">0</span>
<br><span>Text height:</span>
<input id="iHeight" type="range" min=0 max=200 value=64>
<span id="vHeight">64</span>
<br><span>Bottom:</span>
<input id="iBottom" type="range" min=0 max=200 value=200>
<span id="vBottom">200</span>
<br><span>Text:</span>
<input id="iText" type="text" value="BRIDGE TEXT">
</body>
I need the text effect like below images,I have tried a lot to make this but i cannot.
Can anyone please help me out?
Also can we use active object from fabric.js with context?
Here is a modified version of the original code (the provided code in question has changed values compared to my original code.. .-) ) which can produce all these shapes just by playing around with the parameters:
The roof is not super but I'll leave it to you to add scaling support as this is meant as an example.
ONLINE DEMO HERE
Initialization:
var ctx = demo.getContext('2d'), /// context
font = '64px impact', /// font
w = demo.width, /// cache canvas width and height
h = demo.height,
curve, /// radius
offsetY, /// offset for text
bottom, /// bottom of text
textHeight, /// text height (region of text)
isTri = false, /// is triangle shaped (roof)
dltY, /// delta for triangle
angleSteps = 180 / w, /// angle steps for curved text
i = w, /// "x" backwards
y, /// top of text
/// offscreen canvas that holds original text
os = document.createElement('canvas'),
octx = os.getContext('2d');
os.width = w;
os.height = h;
/// set font on off-screen canvas where we draw it
octx.font = font;
octx.textBaseline = 'top';
octx.textAlign = 'center';
Main function:
/// render
function renderBridgeText() {
/// demo stuff snipped (see link)
/// clear canvases
octx.clearRect(0, 0, w, h);
ctx.clearRect(0, 0, w, h);
/// draw text (text may change)
octx.fillText(iText.value.toUpperCase(), w * 0.5, 0);
/// slide and dice
dltY = curve / textHeight; /// calculate delta for roof/triangle
y = 0; /// reset y in case we do roof
i = w; /// init "x"
while (i--) {
if (isTri) {
/// bounce delta value mid-way for triangle
y += dltY;
if (i === (w * 0.5)|0) dltY = -dltY;
} else {
/// calc length based on radius+angle for curve
y = bottom - curve * Math.sin(i * angleSteps * Math.PI / 180);
}
/// draw a slice
ctx.drawImage(os, i, 0, 1, textHeight,
i, h * 0.5 - offsetY / textHeight * y, 1, y);
}
}
Thanks,
Above answer helped me a lot.
But while working in typescript. I've faced issue while passing the simple text image in 'drawImage' function.
So, below is the modified changes of the above code as per the typescript/angular.
Html:
<canvas #simpleText id="simpleText" width=220 height=80></canvas>
<canvas #myCanvas id="myCanvas" width=800 height=400></canvas>
Initialization:
#ViewChild('myCanvas', {static: false}) myCanvas: ElementRef<HTMLCanvasElement>;
context: CanvasRenderingContext2D;
#ViewChild('simpleText', {static: false}) simpleText: ElementRef<HTMLCanvasElement>;
simpleTextContext: CanvasRenderingContext2D;
// default values
shapeConfigure:any={
w : null,
h : null,
curve: 10 ,
offsetY: 50,
bottom: 200,
textHeight: 64,
isTri : false,
angleSteps : 0
};
// canvas width height
shapeCanvas={
w: 800,
h: 400
}
iText:string = 'check text';
sampleImage = new Image();
dataURL:any='';
ngAfterViewInit(): void {
this.context = this.myCanvas.nativeElement.getContext('2d');
var font = '60px impact';
this.simpleTextContext = this.simpleText.nativeElement.getContext('2d');
this.simpleText.nativeElement.height=60;
this.simpleText.nativeElement.width=400;
this.simpleTextContext.font = font;
this.simpleTextContext.textBaseline = 'top';
this.simpleTextContext.textAlign = 'left';
this.simpleTextContext.fillText(this.iText.toUpperCase(), 200* 0.5, 0);
this.dataURL = this.simpleText.nativeElement.toDataURL();
console.log(this.dataURL);
this.sampleImage.src = this.dataURL;
this.shapeConfigure={
w : this.myCanvas.nativeElement.width,
h : this.myCanvas.nativeElement.height,
curve: 10 ,
offsetY: 50,
bottom: 200,
textHeight: 64,
isTri : false,
angleSteps : 180 /this.shapeCanvas.w
}
this.renderBridgeText(false);
}
Main Function:
renderBridgeText(textChange) {
var curve = parseInt(this.shapeConfigure.curve, 10);
var offsetY = parseInt(this.shapeConfigure.offsetY, 10);
var textHeight = parseInt(this.shapeConfigure.textHeight, 10);
var bottom = parseInt(this.shapeConfigure.bottom, 10);
var isTri = this.shapeConfigure.isTri;
this.context.clearRect(0, 0, this.shapeCanvas.w , this.shapeCanvas.h );
if(textChange){
this.simpleTextContext.clearRect(0, 0, this.shapeCanvas.w , this.shapeCanvas.h );
this.simpleTextContext.fillText(this.iText.toUpperCase(), 200* 0.5, 0);
this.dataURL = this.simpleText.nativeElement.toDataURL();
}
this.sampleImage.src = this.dataURL;
this.sampleImage.onload = () => {
/// slide and dice
var i:number = this.shapeCanvas.w;
var dltY:number = curve / textHeight;
var y = 0;
while (i--) {
if (isTri) {
y += dltY;
if (i === (this.shapeCanvas.w * 0.5))
dltY = -dltY;
} else {
y = bottom - curve * Math.sin(i * this.shapeConfigure.angleSteps * Math.PI / 180);
}
this.context.drawImage(this.sampleImage, i, 0, 1, textHeight, i, this.shapeCanvas.h * 0.5 - offsetY / textHeight * y, 1, y);
}
}
}

Ball movement path in canvas, and other ideas you may have?

I've created this animation for my project that had to use any form of physics.
I am a total beginner, too :) Anyway, this is my project now :
Bouncing Balls
You can setup gravity and force, then click play, and just drag and drop to shoot the balls. You can change the values and hit update too see an effect.
My question is, how can I create an effect that when I press ratio button (for example) I can see the path that ball makes? Is it complicated? As I was saying I am a beginner, so no complex code for me :)
Also, doyou have any ideas to make the project better? Any additional "physics" effects? Or maybe you know a website that shows tutorials for simile (please) effects made in HTML5/js so I can add additional effects to my project.
One possibility (as you're clearing the canvas each frame) would be to draw ball paths onto a secondary canvas, which would not be cleared each frame. Then, when you come to clear the first frame, render the second frame after clearing, and before rendering the balls.
The second canvas would of course have to be the same dimensions as the first, so that all of the ball points line up correctly. The second canvas should also have a z-index lower than the first, so that it is only shown when you specifically render it to the first canvas (i.e. when the radio button is checked).
To decrease any lag while the radio is not checked, you could skip drawing the ball paths to the second canvas, although I don't think you would see any great increase in performance.
On each frame update, you would mark the position of each ball with a pixel, or line (from the previous position to the current) on the second canvas.
Looking at your code, you seem pretty competent, so I've skipped writing an example as I think this would be good experience for you :)
Modified 'script.js' source demonstrating solution
window.onload = function(){
$("#canvas").hide();
var howManyPaths = 0;
var showPath=false;
// SLIDERS
var gravitySlider = document.getElementById('gravitySlider');
var gravityVal = document.getElementById('gravityValue');
gravitySlider.onchange = function(){
gravityVal.value = gravitySlider.value;
}
gravityVal.onkeyup = function(){
gravitySlider.value = gravityVal.value;
}
var forceSlider = document.getElementById('forceSlider');
var forceValue = document.getElementById('forceValue');
forceSlider.onchange = function(){
forceValue.value = forceSlider.value;
}
forceValue.onkeyup = function(){
forceSlider.value = forceValue.value;
}
// GLOBAL VARIABLES
var test = false;
var gravityCount = $("#gravity").val();
var forceCount = $("#rectangles").val();
// CSS :
var playCSS = document.getElementById("play");
var restartCSS = document.getElementById("restart");
var clickableCSS = document.getElementById("setup");
var clickableBG = document.getElementById("img");
//restartCSS.style.visibility="hidden";
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var canvas2 = document.getElementById("canvas2");
var ctx2 = canvas2.getContext("2d");
//var ctx;
var gravity = 9.86;
var forceFactor = 0.5;
var mouseDown = false;
var balls = new Array();
var mousePos = new Array();
// EVENT HANDLER
function onMouseDown(evt){
mouseDown = true;
mousePos['downX'] = evt.pageX;
mousePos['downY'] = evt.pageY;
}
function onMouseUp(evt){
mouseDown = false;
setup.style.visibility="visible";
if(test == true && !( mousePos['downX'] < 200 && mousePos['downY'] < 150) ){
restartCSS.style.visibility="visible";
forceFactor = forceCount;
balls.push(new ball(mousePos["downX"],
mousePos["downY"],
(evt.pageX - mousePos["downX"]) * forceFactor,
(evt.pageY - mousePos["downY"]) * forceFactor,
10 + (Math.random() * 10),
0.8,
randomColor()
));
}
ctx2.clearRect(0, 0, canvas2.width, canvas2.height);
}
function onMouseMove(evt){
mousePos['currentX'] = evt.pageX;
mousePos['currentY'] = evt.pageY;
}
function resizeWindow(evt){
//canvas.height = 960;
//canvas.width = 720;
canvas.height = $(window).height()-6;
canvas.width = $(window).width();
canvas2.height = $(window).height()-6;
canvas2.width = $(window).width();
}
$(document).mousedown(onMouseDown);
$(document).mouseup(onMouseUp);
$(document).mousemove(onMouseMove);
$(window).bind("resize", resizeWindow);
// GRAPHICS CODE
function circle(x, y, r, col){
ctx.beginPath();
ctx.arc(x, y, r, 0, Math.PI*2, true);
ctx.closePath;
// fill
ctx.fillStyle = col;
ctx.fill();
// stroke
ctx.lineWidth = r * 0.1;
ctx.strokeStyle = "#000000";
ctx.stroke();
}
function circlePath(x, y)
{
ctx2.clearRect(0, 0, canvas2.width, canvas2.height);
ctx2.fillStyle = '#3f4043';
ctx2.fillRect(x, y, 5, 5);
ctx2.strokeStyle = "black";
ctx2.strokeRect(x, y, 5, 5);
}
function randomColor(){
var letter = "0123456789ABCDEF".split("");
var color = "#";
for(var i=0; i<6; i++){
color += letter[Math.round(Math.random()*15)];
}
return color;
}
function arrow(fromX, fromY, toX, toY, color){
// path
ctx.beginPath();
var headLen = 10;
var angle = Math.atan2(toY - fromY, toX - fromX);
ctx.moveTo(fromX, fromY);
ctx.lineTo(toX, toY);
ctx.lineTo(toX - headLen * Math.cos(angle - Math.PI/6), toY - headLen * Math.sin(angle - Math.PI/6));
ctx.moveTo(toX, toY);
ctx.lineTo(toX - headLen * Math.cos(angle + Math.PI/6), toY - headLen * Math.sin(angle + Math.PI/6));
// style
ctx.lineWith = 1;
ctx.strokeStyle = color;
ctx.lineCap = "butt";
ctx.stroke();
}
function drawBall(){
// Gravity
gravity = gravityCount;
this.speedY += gravity * 0.5; // v = a * t
this.x += this.speedX * 0.05; // s = v * t
this.y += this.speedY * 0.05;
// prawa ściana
if(this.x + this.r > canvas.width){
this.x = canvas.width - this.r;
this.speedX *= -1 * this.bounce;
}
// lewa ściana
if(this.x - this.r < 0){
this.x = this.r;
this.speedX *= -1 * this.bounce;
}
// dolna ściana
if(this.y + this.r > canvas.height){
this.y = canvas.height - this.r;
this.speedY *= -1 * this.bounce;
}
// górna ściana
if(this.y - this.r < 0){
this.y = this.r;
this.speedY *= -1 * this.bounce;
}
// zwalnianie na ziemi
if (this.speedX > 0.25){
this.speedX -= 0.25;
if (this.speedY > 0.25)
this.speedY -= 0.25;
}
if (this.speedX < -0.25){
this.speedX += 0.25;
//if (this.speedY < -0.25)
// this.speedY += 0.25;
}
circle(this.x, this.y, this.r, this.col);;
}
// OBJECTS
function ball(positionX, positionY, sX, sY, radius, b, color){
this.x = positionX;
this.y = positionY;
this.speedX = sX;
this.speedY = sY;
this.r = radius;
this.bounce = b;
this.col = color;
this.draw = drawBall;
}
//GAME LOOP
function gameLoop(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
//grab the context from your destination canvas
//if path drawing is enabled, first draw the path canvas to the display canvas
if (showPath) ctx.drawImage(canvas2,0,0);
if(mouseDown == true){
// ctx.clearRect(0, 0, canvas.width, canvas.height); /* !important !!!!!!!!!!!!!!! */
arrow(mousePos['downX'], mousePos['downY'], mousePos['currentX'], mousePos['currentY'], "red");
}
for(var i=0; i<balls.length; i++){
balls[i].draw();
if (i==balls.length-1) {
//draw path
ctx2.fillStyle = '#3f4043';
ctx2.fillRect(balls[i].x, balls[i].y, 5, 5);
ctx2.strokeStyle = "black";
ctx2.strokeRect(balls[i].x, balls[i].y, 5, 5);
}
}
ctx.fillStyle = "#000000";
ctx.font = "15px Arial";
ctx.fillText("Balls: " + balls.length + " " + gravityCount + " " + forceCount + " " + howManyPaths, 10, canvas.height -10);
}
// START THE GAME
function init(){
//$("#setup").hide();
$("#canvas").show();
$("#canvas2").hide();
ctx = $('canvas')[0].getContext("2d");
canvas.height = $(window).height()-6;
canvas.width = $(window).width();
//canvas.width = 960;
//canvas.height = 720;
canvas2.height = $(window).height()-6;
canvas2.width = $(window).width();
return setInterval(gameLoop, 10);
}
$("#play").click(function() {
test = true;
playCSS.style.visibility="hidden";
gravityCount = $("#gravitySlider").val();
forceCount = $("#forceSlider").val();
init();
});
$("#restart").click(function() {
window.location.href="index.html";
});
$("#refresh").click(function() {
gravityCount = $("#gravitySlider").val();
forceCount = $("#forceSlider").val();
});
$("#showPath").click(function() {
showPath=true;
});
$("#hidePath").click(function() {
showPath=false;
});
}

Chart Label text rotation

I am using very similar code to create a pie chart using canvas as per this article:
http://wickedlysmart.com/how-to-make-a-pie-chart-with-html5s-canvas/
As you can see from this image, there are cases where the labels are upside down:
Here is the code that writes the labels to the graph:
var drawSegmentLabel = function(canvas, context, i) {
context.save();
var x = Math.floor(canvas.width / 2);
var y = Math.floor(canvas.height / 2);
var degrees = sumTo(data, i);
var angle = degreesToRadians(degrees);
context.translate(x, y);
context.rotate(angle);
context.textAlign = 'right';
var fontSize = Math.floor(canvas.height / 32);
context.font = fontSize + 'pt Helvetica';
var dx = Math.floor(canvas.width * 0.3) - 20;
var dy = Math.floor(canvas.height * 0.05);
context.fillText(labels[i], dx, dy);
context.restore();
};
I am trying to rectify this so the text is always readable and not upside down but cant work out how to do it!
Here's my solution! (A little kludgey but seems to work on the basic example, I haven't tested in on edge cases...)
var drawSegmentLabel = function(canvas, context, i) {
context.save();
var x = Math.floor(canvas.width / 2);
var y = Math.floor(canvas.height / 2);
var angle;
var angleD = sumTo(data, i);
var flip = (angleD < 90 || angleD > 270) ? false : true;
context.translate(x, y);
if (flip) {
angleD = angleD-180;
context.textAlign = "left";
angle = degreesToRadians(angleD);
context.rotate(angle);
context.translate(-(x + (canvas.width * 0.5))+15, -(canvas.height * 0.05)-10);
}
else {
context.textAlign = "right";
angle = degreesToRadians(angleD);
context.rotate(angle);
}
var fontSize = Math.floor(canvas.height / 25);
context.font = fontSize + "pt Helvetica";
var dx = Math.floor(canvas.width * 0.5) - 10;
var dy = Math.floor(canvas.height * 0.05);
context.fillText(labels[i], dx, dy);
context.restore();
};
To display the text in the correct way you have to check if the rotation angle is between 90 and 270 degree. If it is then you know the text will be display upside down.
To switch it correctly you then have to rotate you canvas of planed rotation - 180 degree and then to align it in left not right :
var drawSegmentLabel = function(canvas, context, i) {
context.save();
var x = Math.floor(canvas.width / 2);
var y = Math.floor(canvas.height / 2);
var degrees = sumTo(data, i);
var angle = 0;
if (degree > 90 && degree < 270)
angle = degreesToRadians(degrees - 180);
else
angle = degreesToRadians(degrees);
context.translate(x, y);
context.rotate(angle);
context.textAlign = 'right';
var fontSize = Math.floor(canvas.height / 32);
context.font = fontSize + 'pt Helvetica';
var dx = Math.floor(canvas.width * 0.3) - 20;
if (degree > 90 && degree < 270)
dx = 20;
var dy = Math.floor(canvas.height * 0.05);
context.fillText(labels[i], dx, dy);
context.restore();
};

How to produce such page flip effects in Canvas?

google has published an e-book : http://www.20thingsilearned.com/
the reading experience is kind of fun.
I notice they used canvas to produce the page flip effects over reading areas.
Technically, you can draw a customized shape, filled with gradient, decorated with shadow.
but the shape has to be drawn with two beizer curves (for top and bottom edges) and two straight lines.
The problem is how to dynamically draw those two beizer curves. I spent a whole day to draw these two curves. here is some code of.
Does anyone knows how to produce the same effects on Google's ebook.
or i basically ran into wrong direction?
/**
* PageFlip effects using HTML Canvas
* #author RobinQu
* #version 0.1
*/
/*global x$ */
var elf = {};
elf.fx = {};
elf.fx.pageflip = {
/**
* initialize the pageflip
* #param {String} cId The id of canvas element
*/
init: function(cId, width, height) {
var canvas,
ctx;
this.$ = x$("#" + cId);
canvas = this.canvas = this.$[0];
this.width = canvas.width = width;
this.height = canvas.height = height;
this.margin = 60;
this.context = canvas.getContext("2d");
//this.bind();
},
bind: function() {
this.$.on("mouseover", this.beginRoll.bind(this));
this.$.on("mousemove", this.doRoll.bind(this));
this.$.on("mouseout", this.endRoll.bind(this));
},
_over: false,
beginRoll: function() {
this._over = true;
},
_clear: function() {
var ctx = this.context;
ctx.clearRect(0, 0, this.width, this.height);
var w = this.width;
this.canvas.width = 1;
this.canvas.width = w;
},
doRoll: function(e) {
//offset, plus scroll; client, no scroll
if (this._over) {
//console.log(e.offsetX, e.offsetY, e.clientX, e.clientY);
var x = e.offsetX,
y = e.offsetY,
ctx = this.context,
startx = x,
starty = x / this.width * this.margin,
endx = (this.width - x)/2 + x,
endy = this.margin + 8,
cp1x = x + 10,
cp1y = Math.min(this.margin * Math.sin(x * Math.PI / this.width), 5),
cp2x = endx - 10,
cp2y = Math.min(this.margin * Math.cos(x * Math.PI / this.width), 5);
console.log(this.margin * Math.sin(x * Math.PI / this.width));
//enxy = this.margin * Math.sin(x * Math.PI * 2 / this.width),
//cp2x = ;
console.log(this.width, this.height);
this._clear();
ctx.beginPath();
ctx.moveTo(startx, starty);
ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, endx, endy);
ctx.strokeStyle = "#000";
ctx.stroke();
}
},
endRoll: function() {
this._over = false;
}
};