Circling Text Trail Around Cursor - javascript

I've been searching for a script that creates a cursor text trail moving in a circular motion for quite a while. I feel like such things were everywhere just five years ago on kitschy blog sites.
The only code(s) I've been able to find are authored by Tim Tilton,
with variations found
here and here
and repeated on a few other sites.
This code seems a bit heavy in that it separates and gives each character of the message it's own div and then use equations to place and move those divs around the cursor.
It's there another way to go about creating such a feature?
A bit of the heavy code here:
if (!window.addEventListener && !window.attachEvent || !document.createElement) return;
msg = msg.split('');
var n = msg.length - 1, a = Math.round(size * diameter * 0.208333), currStep = 20,
ymouse = a * circleY + 20, xmouse = a * circleX + 20, y = [], x = [], Y = [], X = [],
o = document.createElement('div'), oi = document.createElement('div'),
b = document.compatMode && document.compatMode != "BackCompat"? document.documentElement : document.body,
mouse = function(e){
e = e || window.event;
ymouse = !isNaN(e.pageY)? e.pageY : e.clientY; // y-position
xmouse = !isNaN(e.pageX)? e.pageX : e.clientX; // x-position
},
makecircle = function(){ // rotation/positioning
if(init.nopy){
o.style.top = (b || document.body).scrollTop + 'px';
o.style.left = (b || document.body).scrollLeft + 'px';
};
currStep -= rotation;
for (var d, i = n; i > -1; --i){ // makes the circle
d = document.getElementById('iemsg' + i).style;
d.top = Math.round(y[i] + a * Math.sin((currStep + i) / letter_spacing) * circleY - 15) + 'px';
d.left = Math.round(x[i] + a * Math.cos((currStep + i) / letter_spacing) * circleX) + 'px';
};
},
drag = function(){ // makes the resistance
y[0] = Y[0] += (ymouse - Y[0]) * speed;
x[0] = X[0] += (xmouse - 20 - X[0]) * speed;
for (var i = n; i > 0; --i){
y[i] = Y[i] += (y[i-1] - Y[i]) * speed;
x[i] = X[i] += (x[i-1] - X[i]) * speed;
};
makecircle();
},
init = function(){ // appends message divs, & sets initial values for positioning arrays
if(!isNaN(window.pageYOffset)){
ymouse += window.pageYOffset;
xmouse += window.pageXOffset;
} else init.nopy = true;
for (var d, i = n; i > -1; --i){
d = document.createElement('div'); d.id = 'iemsg' + i;
d.style.height = d.style.width = a + 'px';
d.appendChild(document.createTextNode(msg[i]));
oi.appendChild(d); y[i] = x[i] = Y[i] = X[i] = 0;
};
o.appendChild(oi); document.body.appendChild(o);
setInterval(drag, 25);
},
ascroll = function(){
ymouse += window.pageYOffset;
xmouse += window.pageXOffset;
window.removeEventListener('scroll', ascroll, false);
};
o.id = 'outerCircleText'; o.style.fontSize = size + 'px';
if (window.addEventListener){
window.addEventListener('load', init, false);
document.addEventListener('mouseover', mouse, false);
document.addEventListener('mousemove', mouse, false);
if (/Apple/.test(navigator.vendor))
window.addEventListener('scroll', ascroll, false);
}
else if (window.attachEvent){
window.attachEvent('onload', init);
document.attachEvent('onmousemove', mouse);
};

Related

Having trouble changing shape of confetti

I've found this codepen that I'm integrating on a small website I have for a project. I don't want to put too much time into it, so I'll just be using a codepen I found. I'll do some adjustments to it, like the shape.
I managed to implement it, but now I'm having trouble to change the colors and the shape of the confetti.
The colors are completely random and I'd love for this to just be simple.
Also, I can't seem to be able to change the shape. I can only adjust the size.
If anyone here feels like giving me a nudge in the right direction, that'd be great!
'use strict';
// If set to true, the user must press
// UP UP DOWN ODWN LEFT RIGHT LEFT RIGHT A B
// to trigger the confetti with a random color theme.
// Otherwise the confetti constantly falls.
var onlyOnKonami = false;
$(function() {
// Globals
var $window = $(window)
, random = Math.random
, cos = Math.cos
, sin = Math.sin
, PI = Math.PI
, PI2 = PI * 2
, timer = undefined
, frame = undefined
, confetti = [];
// Settings
var konami = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65]
, pointer = 0;
var particles = 150
, spread = 40
, sizeMin = 3
, sizeMax = 12 - sizeMin
, eccentricity = 10
, deviation = 100
, dxThetaMin = -.1
, dxThetaMax = -dxThetaMin - dxThetaMin
, dyMin = .13
, dyMax = .18
, dThetaMin = .4
, dThetaMax = .7 - dThetaMin;
var colorThemes = [
function() {
return color(200 * random()|0, 200 * random()|0, 200 * random()|0);
}, function() {
var black = 200 * random()|0; return color(200, black, black);
}, function() {
var black = 200 * random()|0; return color(black, 200, black);
}, function() {
var black = 200 * random()|0; return color(black, black, 200);
}, function() {
return color(200, 100, 200 * random()|0);
}, function() {
return color(200 * random()|0, 200, 200);
}, function() {
var black = 256 * random()|0; return color(black, black, black);
}, function() {
return colorThemes[random() < .5 ? 1 : 2]();
}, function() {
return colorThemes[random() < .5 ? 3 : 5]();
}, function() {
return colorThemes[random() < .5 ? 2 : 4]();
}
];
function color(r, g, b) {
return 'rgb(' + r + ',' + g + ',' + b + ')';
}
// Cosine interpolation
function interpolation(a, b, t) {
return (1-cos(PI*t))/2 * (b-a) + a;
}
// Create a 1D Maximal Poisson Disc over [0, 1]
var radius = 1/eccentricity, radius2 = radius+radius;
function createPoisson() {
// domain is the set of points which are still available to pick from
// D = union{ [d_i, d_i+1] | i is even }
var domain = [radius, 1-radius], measure = 1-radius2, spline = [0, 1];
while (measure) {
var dart = measure * random(), i, l, interval, a, b, c, d;
// Find where dart lies
for (i = 0, l = domain.length, measure = 0; i < l; i += 2) {
a = domain[i], b = domain[i+1], interval = b-a;
if (dart < measure+interval) {
spline.push(dart += a-measure);
break;
}
measure += interval;
}
c = dart-radius, d = dart+radius;
// Update the domain
for (i = domain.length-1; i > 0; i -= 2) {
l = i-1, a = domain[l], b = domain[i];
// c---d c---d Do nothing
// c-----d c-----d Move interior
// c--------------d Delete interval
// c--d Split interval
// a------b
if (a >= c && a < d)
if (b > d) domain[l] = d; // Move interior (Left case)
else domain.splice(l, 2); // Delete interval
else if (a < c && b > c)
if (b <= d) domain[i] = c; // Move interior (Right case)
else domain.splice(i, 0, c, d); // Split interval
}
// Re-measure the domain
for (i = 0, l = domain.length, measure = 0; i < l; i += 2)
measure += domain[i+1]-domain[i];
}
return spline.sort();
}
// Create the overarching container
var container = document.createElement('div');
container.style.position = 'fixed';
container.style.top = '0';
container.style.left = '0';
container.style.width = '100%';
container.style.height = '0';
container.style.overflow = 'visible';
container.style.zIndex = '9999';
// Confetto constructor
function Confetto(theme) {
this.frame = 0;
this.outer = document.createElement('div');
this.inner = document.createElement('div');
this.outer.appendChild(this.inner);
var outerStyle = this.outer.style, innerStyle = this.inner.style;
outerStyle.position = 'absolute';
outerStyle.width = (sizeMin + sizeMax * random()) + 'px';
outerStyle.height = (sizeMin + sizeMax * random()) + 'px';
innerStyle.width = '100%';
innerStyle.height = '100%';
innerStyle.backgroundColor = theme();
outerStyle.perspective = '50px';
outerStyle.transform = 'rotate(' + (360 * random()) + 'deg)';
this.axis = 'rotate3D(' +
cos(360 * random()) + ',' +
cos(360 * random()) + ',0,';
this.theta = 360 * random();
this.dTheta = dThetaMin + dThetaMax * random();
innerStyle.transform = this.axis + this.theta + 'deg)';
this.x = $window.width() * random();
this.y = -deviation;
this.dx = sin(dxThetaMin + dxThetaMax * random());
this.dy = dyMin + dyMax * random();
outerStyle.left = this.x + 'px';
outerStyle.top = this.y + 'px';
// Create the periodic spline
this.splineX = createPoisson();
this.splineY = [];
for (var i = 1, l = this.splineX.length-1; i < l; ++i)
this.splineY[i] = deviation * random();
this.splineY[0] = this.splineY[l] = deviation * random();
this.update = function(height, delta) {
this.frame += delta;
this.x += this.dx * delta;
this.y += this.dy * delta;
this.theta += this.dTheta * delta;
// Compute spline and convert to polar
var phi = this.frame % 7777 / 7777, i = 0, j = 1;
while (phi >= this.splineX[j]) i = j++;
var rho = interpolation(
this.splineY[i],
this.splineY[j],
(phi-this.splineX[i]) / (this.splineX[j]-this.splineX[i])
);
phi *= PI2;
outerStyle.left = this.x + rho * cos(phi) + 'px';
outerStyle.top = this.y + rho * sin(phi) + 'px';
innerStyle.transform = this.axis + this.theta + 'deg)';
return this.y > height+deviation;
};
}
function poof() {
if (!frame) {
// Append the container
document.body.appendChild(container);
// Add confetti
var theme = colorThemes[onlyOnKonami ? colorThemes.length * random()|0 : 0]
, count = 0;
(function addConfetto() {
if (onlyOnKonami && ++count > particles)
return timer = undefined;
var confetto = new Confetto(theme);
confetti.push(confetto);
container.appendChild(confetto.outer);
timer = setTimeout(addConfetto, spread * random());
})(0);
// Start the loop
var prev = undefined;
requestAnimationFrame(function loop(timestamp) {
var delta = prev ? timestamp - prev : 0;
prev = timestamp;
var height = $window.height();
for (var i = confetti.length-1; i >= 0; --i) {
if (confetti[i].update(height, delta)) {
container.removeChild(confetti[i].outer);
confetti.splice(i, 1);
}
}
if (timer || confetti.length)
return frame = requestAnimationFrame(loop);
// Cleanup
document.body.removeChild(container);
frame = undefined;
});
}
}
$window.keydown(function(event) {
pointer = konami[pointer] === event.which
? pointer+1
: +(event.which === konami[0]);
if (pointer === konami.length) {
pointer = 0;
poof();
}
});
if (!onlyOnKonami) poof();
});
Look inside Confetto() it's just using a <div> inside another <div> and giving it random width, height, 3D rotation, etc., you should be able to manipulate innerStyle and/or outerStyle to your liking there.
Try adding something like this to make it rounded:
innerStyle.borderRadius = '100%';
Try something like this to make it squared:
innerStyle.borderRadius = '0';
Or a combination:
innerStyle.borderRadius = '100% 0 0 100%';
You should be able to set any style property you need, by camel-casing the css name (.border for border, .borderBottom for border-bottom, .borderBottomColor for border-bottom-color, etc.). Check this list for ideas

Making javascript animation smooth?

Basically what I want to achieve is to drag some div within another container div. Inner div should stop when it reaches the boundaries of the container div. I managed to do the most parts. But the problem is that if I drag inner div slowly & carefully it stops where it is supposed to be on the edges, however if I drag it faster, it sometimes overflow the edges or stops way before the edges. What is the problem here? What should I do to fix this?
Here is full code
function mouseMove(e) {
e.preventDefault();
console.log("mouse moving");
if(isMouseDown > 0 && currentElement) {
mouseX = e.clientX;
mouseY = e.clientY;
var diffX = mouseX - lastMouseX;
var diffY = mouseY - lastMouseY;
if(diffX + lastElementX + elementWidth < rightLimit && diffX + lastElementX > leftLimit) {
lastElementX += diffX;
lastMouseX = mouseX;
}
if(diffY + lastElementY + elementHeight < bottomLimit && diffY + lastElementY > topLimit) {
lastElementY += diffY;
lastMouseY = mouseY;
}
setCurrentElementPosition(lastElementX, lastElementY);
}
}
Above code runs on mouse move event changing inner div's position.
Here's my solution for you, I've programmed video games before, and you run into this problem a lot.
You're checking if it'll go out, but not doing anything if it does! If it goes outside, you have to set it to the edge.
https://jsfiddle.net/7btv7oqy/3/
var lastElementX = 0; //last X position of element
var lastElementY = 0; //last Y position of element
var lastMouseX = 0; //last X position of mouse
var lastMouseY = 0;//last Y position of mouse
var mouseX = 0; //current mouse position X
var mouseY = 0; //current mouse position Y
var currentElement = null; //currently selected div
var elementWidth = 0;
var elementHeight = 0;
var container = null; //container div
var isMouseDown = 0; //if greater than zero, mouse is down
//limits of container div
var bottomLimit = 0;
var topLimit = 0;
var leftLimit = 0;
var rightLimit = 0;
function init() {
container = document.getElementsByClassName("container")[0];
topLimit = container.getBoundingClientRect().top;
bottomLimit = container.getBoundingClientRect().bottom;
leftLimit = container.getBoundingClientRect().left;
rightLimit = container.getBoundingClientRect().right;
document.addEventListener("mousedown", function mouseDown(e) {
e.preventDefault();
++isMouseDown;
document.addEventListener("mousemove", mouseMove);
setCurrentElement(getElementUnderMouse(e)); //set current element
currentElement.style.position = "absolute";
lastElementX = currentElement.getBoundingClientRect().left;
lastElementY = currentElement.getBoundingClientRect().top;
lastMouseX = e.clientX;
lastMouseY = e.clientY;
});
document.addEventListener("mouseup", function mouseUp(e) {
e.preventDefault();
--isMouseDown;
setCurrentElement(null);
document.removeEventListener("mousemove", mouseMove);
});
}
function mouseMove(e) {
e.preventDefault();
console.log("mouse moving");
// report(e);
if(isMouseDown > 0 && currentElement) {
mouseX = e.clientX;
mouseY = e.clientY;
var diffX = mouseX - lastMouseX;
var diffY = mouseY - lastMouseY;
if(diffX + lastElementX + elementWidth < rightLimit && diffX + lastElementX > leftLimit) {
lastElementX += diffX;
} else {
//without this, the location wouldn't update at all:
//check if it would go off the right edge, set to right edge
if (diffX + lastElementX + elementWidth >= rightLimit) {
lastElementX = rightLimit - elementWidth;
}
//check if it would go off the left edge, set to left edge
if(diffX + lastElementX <= leftLimit) {
lastElementX = leftLimit;
}
}
//this will always happen:
lastMouseX = mouseX;
if(diffY + lastElementY + elementHeight < bottomLimit && diffY + lastElementY > topLimit) {
lastElementY += diffY;
} else {
//without this, the location wouldn't update at all:
//check if it would go off the bottom edge, set to bottom edge
if(diffY + lastElementY + elementHeight >= bottomLimit) {
lastElementY = bottomLimit - elementHeight;
}
//check if it would go off the top edge, set to top edge
if(diffY + lastElementY <= topLimit) {
lastElementY = topLimit;
}
}
//this will always happen:
lastMouseY = mouseY;
setCurrentElementPosition(lastElementX, lastElementY);
}
}
function setCurrentElementPosition(left = null, top = null) {
if(currentElement) {
currentElement.style.top = top + 'px'
currentElement.style.left = left + 'px';
}
}
function setCurrentElement(element) {
currentElement = element;
if(element) {
elementWidth = currentElement.offsetWidth;
elementHeight = currentElement.offsetHeight;
} else {
elementWidth = 0;
elementHeight = 0;
}
}
function hasClass(element, cls) {
return ("" + element.className + "").indexOf("" + cls + "") > -1;
}
function getElementUnderMouse(e) {
var x = e.clientX;
var y = e.clientY;
return document.elementFromPoint(x, y);
}
function report(e) {
console.log("isMouseDown: " + isMouseDown);
console.log("mouseX: " + e.clientX);
console.log("mouseY: " + e.clientY);
console.log("currentElement: " + currentElement);
console.log("currentElement top: " + currentElement.getBoundingClientRect().top);
console.log("currentElement bottom: " + currentElement.getBoundingClientRect().bottom);
console.log("container top: " + container.getBoundingClientRect().top);
console.log("container bottom: " + container.getBoundingClientRect().bottom);
}
init();
EDIT: Not sure why it's missing by one pixel at the right and bottom, you'll have to do some investigation on that front. Seems like it's not taking into consideration the border, despite you using offsetWidth. Good luck!
Here's my take; I've decoupled the element's movement from diffX/diffY:
https://jsfiddle.net/ttyrtjez/
// in onmousedown
offsetX = e.clientX - lastElementX;
offsetY = e.clientY - lastElementY;
// in onmousemove
var newElementX = mouseX - offsetX;
var newElementY = mouseY - offsetY;
if (newElementX + elementWidth >= rightLimit - 1) newElementX = rightLimit - elementWidth - 2;
if (newElementX < leftLimit) newElementX = leftLimit;
if (newElementY + elementHeight >= bottomLimit - 1) newElementY = bottomLimit - elementHeight - 2;
if (newElementY < topLimit) newElementY = topLimit;
setCurrentElementPosition(newElementX, newElementY);

pass a random generated variable to setInterval

I have animated a dynamic created element with setInterval. When the element is clicked I want it to change to a random direction (left, right, up or down).
I think the problem is that I canĀ“t pass the randomly created direction into the setInterval function.
The html here....
<div id="klicker"></div>
The JavaScript here.....
var box = document.getElementById("klicker");
var x = 1;
var startp = 200;
box.onclick = function() {
var newdiv = document.createElement('div');
document.body.appendChild(newdiv);
newdiv.style.width = 200 + 'px';
newdiv.style.height = 200 + 'px';
newdiv.style.backgroundColor = 'grey';
newdiv.style.position = 'absolute';
newdiv.style.left = startp + "px";
newdiv.style.top = startp + "px";
newdiv.setAttribute('id', 'runner')
var run = document.getElementById('runner');
var dire = 'right';
run.onclick = function() {
var mov = function() {
randoms();
};
function randoms() {
alert('ddddd');
var rnd = (Math.random() * 4) + 1; //ranom number 1-4
var rnd_down = Math.floor(rnd); //make it en integer
/*--- make each number a uniqe direction---*/
if (rnd_down == 1) {
dire = 'right';
} else if (rnd_down == 2) {
dire = 'left';
} else if (rnd_down == 3) {
dire = 'up';
} else {
dire = 'down';
}
};
var moveit = setInterval(function() {
movefunc();
}, 50);
function movefunc() {
/*----each direction will make the div travel in diffrent directions--*/
if (dire = 'right') {
x = x + 1;
newdiv.style.left = x + 'px';
} else if (dire = 'left') {
x = x - 1;
newdiv.style.left = x + 'px';
} else if (dire = 'up') {
x = x - 1;
newdiv.style.top = x + 'px';
} else {
x = x + 1;
newdiv.style.top = x + 'px';
}
};
};
}
function movefunc() {
/*----each direction will make the div travel in diffrent directions--*/
if (dire = 'right') {
x = x + 1;
newdiv.style.left = x + 'px';
} else if (dire = 'left') {
x = x - 1;
newdiv.style.left = x + 'px';
} else if (dire = 'up') {
x = x - 1;
newdiv.style.top = x + 'px';
} else {
x = x + 1;
newdiv.style.top = x + 'px';
}
};
Rookie mistake :) ( even though it's one of the most common error in programming, see #4 ) In your condition, you should use == and not = ( which is meant for assignation, == is made for comparison ). I'd even suggest you to use === which will also compare the types. ( 1 == '1' will return true while 1 === '1' will return false cause 1 is an integer type, and '1' is a char type )

jqplotToImageCanvas not working in chrome version 47.0 and firefox 41.0.1

I have multiple charts generated by PHPChart but when i use from print option to print the chart in pdf, and png in chrome it is not working for bar chart types but work for line chart, but if there is one bar chart it works, in Firefox it is not working for vertical bar chart but work for horizontal bar chart.
all type of charts are generated dynamically using database data there is no difference in case of html wrapper tags.
when i click on export button browser hung up.
The javascript code:
function getImageData(obj, type, title)
{
var str;
imgtype = type;
if (type == 'jpg-pdf')
{
imgtype = 'jpg';
type = 'pdf';
}
var imgCanvas = $('#'+obj).jqplotToImageCanvas();
if (imgCanvas) {
str = imgCanvas.toDataURL("image/"+imgtype);
}
else {
str = null;
}
$('#pngdata').val(str);
$('#imgtype').val(type);
$('#imgtitle').val(title);
$('#imgform').submit();
}
and the jqplot function
$.fn.jqplotToImageCanvas = function(options) {
options = options || {};
var x_offset = (options.x_offset == null) ? 0 : options.x_offset;
var y_offset = (options.y_offset == null) ? 0 : options.y_offset;
var backgroundColor = (options.backgroundColor == null) ? 'rgb(255,255,255)' : options.backgroundColor;
if ($(this).width() == 0 || $(this).height() == 0) {
return null;
}
// excanvas and hence IE < 9 do not support toDataURL and cannot export images.
if ($.jqplot.use_excanvas) {
return null;
}
var newCanvas = document.createElement("canvas");
var h = $(this).outerHeight(true);
var w = $(this).outerWidth(true);
var offs = $(this).offset();
var plotleft = offs.left;
var plottop = offs.top;
var transx = 0, transy = 0;
// have to check if any elements are hanging outside of plot area before rendering,
// since changing width of canvas will erase canvas.
var clses = ['jqplot-table-legend', 'jqplot-xaxis-tick', 'jqplot-x2axis-tick', 'jqplot-yaxis-tick', 'jqplot-y2axis-tick', 'jqplot-y3axis-tick',
'jqplot-y4axis-tick', 'jqplot-y5axis-tick', 'jqplot-y6axis-tick', 'jqplot-y7axis-tick', 'jqplot-y8axis-tick', 'jqplot-y9axis-tick',
'jqplot-xaxis-label', 'jqplot-x2axis-label', 'jqplot-yaxis-label', 'jqplot-y2axis-label', 'jqplot-y3axis-label', 'jqplot-y4axis-label',
'jqplot-y5axis-label', 'jqplot-y6axis-label', 'jqplot-y7axis-label', 'jqplot-y8axis-label', 'jqplot-y9axis-label' ];
var temptop, templeft, tempbottom, tempright;
for (var i = 0, j = clses.length; i < j; i++) {
$(this).find('.'+clses[i]).each(function() {
temptop = $(this).offset().top - plottop;
templeft = $(this).offset().left - plotleft;
tempright = templeft + $(this).outerWidth(true) + transx;
tempbottom = temptop + $(this).outerHeight(true) + transy;
if (templeft < -transx) {
w = w - transx - templeft;
transx = -templeft;
}
if (temptop < -transy) {
h = h - transy - temptop;
transy = - temptop;
}
if (tempright > w) {
w = tempright;
}
if (tempbottom > h) {
h = tempbottom;
}
});
}
newCanvas.width = w + Number(x_offset);
newCanvas.height = h + Number(y_offset);
var newContext = newCanvas.getContext("2d");
newContext.save();
newContext.fillStyle = backgroundColor;
newContext.fillRect(0,0, newCanvas.width, newCanvas.height);
newContext.restore();
newContext.translate(transx, transy);
newContext.textAlign = 'left';
newContext.textBaseline = 'top';
function getLineheight(el) {
var lineheight = parseInt($(el).css('line-height'), 10);
if (isNaN(lineheight)) {
lineheight = parseInt($(el).css('font-size'), 10) * 1.2;
}
return lineheight;
}
function writeWrappedText (el, context, text, left, top, canvasWidth) {
var lineheight = getLineheight(el);
var tagwidth = $(el).innerWidth();
var tagheight = $(el).innerHeight();
var words = text.split(/\s+/);
var wl = words.length;
var w = '';
var breaks = [];
var temptop = top;
var templeft = left;
for (var i=0; i<wl; i++) {
w += words[i];
if (context.measureText(w).width > tagwidth && w.length > words[i].length) {
breaks.push(i);
w = '';
i--;
}
}
if (breaks.length === 0) {
// center text if necessary
if ($(el).css('textAlign') === 'center') {
templeft = left + (canvasWidth - context.measureText(w).width)/2 - transx;
}
context.fillText(text, templeft, top);
}
else {
w = words.slice(0, breaks[0]).join(' ');
// center text if necessary
if ($(el).css('textAlign') === 'center') {
templeft = left + (canvasWidth - context.measureText(w).width)/2 - transx;
}
context.fillText(w, templeft, temptop);
temptop += lineheight;
for (var i=1, l=breaks.length; i<l; i++) {
w = words.slice(breaks[i-1], breaks[i]).join(' ');
// center text if necessary
if ($(el).css('textAlign') === 'center') {
templeft = left + (canvasWidth - context.measureText(w).width)/2 - transx;
}
context.fillText(w, templeft, temptop);
temptop += lineheight;
}
w = words.slice(breaks[i-1], words.length).join(' ');
// center text if necessary
if ($(el).css('textAlign') === 'center') {
templeft = left + (canvasWidth - context.measureText(w).width)/2 - transx;
}
context.fillText(w, templeft, temptop);
}
}
function _jqpToImage(el, x_offset, y_offset) {
var tagname = el.tagName.toLowerCase();
var p = $(el).position();
var css = window.getComputedStyle ? window.getComputedStyle(el, "") : el.currentStyle; // for IE < 9
var left = x_offset + p.left + parseInt(css.marginLeft, 10) + parseInt(css.borderLeftWidth, 10) + parseInt(css.paddingLeft, 10);
var top = y_offset + p.top + parseInt(css.marginTop, 10) + parseInt(css.borderTopWidth, 10)+ parseInt(css.paddingTop, 10);
var w = newCanvas.width;
// var left = x_offset + p.left + $(el).css('marginLeft') + $(el).css('borderLeftWidth')
// somehow in here, for divs within divs, the width of the inner div should be used instead of the canvas.
if ((tagname == 'div' || tagname == 'span') && !$(el).hasClass('jqplot-highlighter-tooltip')) {
$(el).children().each(function() {
_jqpToImage(this, left, top);
});
var text = $(el).jqplotChildText();
if (text) {
newContext.font = $(el).jqplotGetComputedFontStyle();
newContext.fillStyle = $(el).css('color');
writeWrappedText(el, newContext, text, left, top, w);
}
}
// handle the standard table legend
else if (tagname === 'table' && $(el).hasClass('jqplot-table-legend')) {
newContext.strokeStyle = $(el).css('border-top-color');
newContext.fillStyle = $(el).css('background-color');
newContext.fillRect(left, top, $(el).innerWidth(), $(el).innerHeight());
if (parseInt($(el).css('border-top-width'), 10) > 0) {
newContext.strokeRect(left, top, $(el).innerWidth(), $(el).innerHeight());
}
// find all the swatches
$(el).find('div.jqplot-table-legend-swatch-outline').each(function() {
// get the first div and stroke it
var elem = $(this);
newContext.strokeStyle = elem.css('border-top-color');
var l = left + elem.position().left;
var t = top + elem.position().top;
newContext.strokeRect(l, t, elem.innerWidth(), elem.innerHeight());
// now fill the swatch
l += parseInt(elem.css('padding-left'), 10);
t += parseInt(elem.css('padding-top'), 10);
var h = elem.innerHeight() - 2 * parseInt(elem.css('padding-top'), 10);
var w = elem.innerWidth() - 2 * parseInt(elem.css('padding-left'), 10);
var swatch = elem.children('div.jqplot-table-legend-swatch');
newContext.fillStyle = swatch.css('background-color');
newContext.fillRect(l, t, w, h);
});
// now add text
$(el).find('td.jqplot-table-legend-label').each(function(){
var elem = $(this);
var l = left + elem.position().left;
var t = top + elem.position().top + parseInt(elem.css('padding-top'), 10);
newContext.font = elem.jqplotGetComputedFontStyle();
newContext.fillStyle = elem.css('color');
writeWrappedText(elem, newContext, elem.text(), l, t, w);
});
var elem = null;
}
else if (tagname == 'canvas') {
newContext.drawImage(el, left, top);
}
}
$(this).children().each(function() {
_jqpToImage(this, x_offset, y_offset);
});
return newCanvas;
};
kindly help me.

Ease in/out camera movement for canvas

I have a function which moves a camera to a position that the user clicks on the canvas. But currently the movement is linear. I would like it to use an ease in/out transition but am having difficulty understanding how to implement it with my current function.
This is the code I have:
animate.mouseEvent = function(e,el){
var mousePos = mouse.relativePosition(e,el);
var parent = el;
if(e.button == 0){
function update(){
if(centerX == mousePos.x && centerY == mousePos.y){
clearInterval(parent.timer);
//center X / Y is canvas width & height halved
}
var difx = centerX - mousePos.x,
dify = centerY - mousePos.y,
distance = Math.sqrt(difx*difx + dify*dify),
normalX = difx/distance,
normalY = dify/distance,
speed = 1, //currently linear [replace with ease in/out]
x = normalX * speed,
y = normalY * speed;
updateOffsets(x,y);
mousePos.x += x;
mousePos.y += y;
}
parent.timer = setInterval(update,1);
}
}
animate.updateOffsets = function(x,y){
canvas.offsetX -= x;
canvas.offsetY -= y;
}
So i was wondering how i would implement an ease in/out from my current linear method. Using the below function:
Math.easeInOutQuad = function (t, b, c, d) {
t /= d/2;
if (t < 1) return c/2*t*t + b;
t--;
return -c/2 * (t*(t-2) - 1) + b;
};
I don't fully know how to implement it or what exactly it would be returning for me to calculate the new offset with. Was hoping some one could explain.
This should give you an idea. I used another easing function, you can substitute your own. Example
var element = document.getElementById('moving');
var bg = document.getElementById('background');
bg.addEventListener('click', function(evt) {
animate({
x: evt.offsetX,
y: evt.offsetY
});
}, false);
function getPosition() {
return {
x: element.offsetLeft,
y: element.offsetTop
};
}
function setPosition(x, y) {
element.style.left = x + 'px';
element.style.top = y + 'px';
}
function easing(x) {
return 0.5 + 0.5 * Math.sin((x - 0.5) * Math.PI);
}
function animate(target) {
var initial = getPosition();
var initialX = initial.x;
var initialY = initial.y;
var targetX = target.x;
var targetY = target.y;
var deltaX = targetX - initialX;
var deltaY = targetY - initialY;
var timeStart = timestamp();
var timeLength = 800;
var timer = setInterval(update, 10);
function timestamp() {
return Date.now();
}
function stop() {
clearInterval(timer);
}
function update() {
var t = (timestamp() - timeStart) / timeLength;
if (t > 1) {
fraction(1);
stop();
} else {
fraction(easing(t));
}
}
function fraction(t) {
setPosition(initialX + t * deltaX, initialY + t * deltaY);
}
}
EDIT
Applied to the fiddle you provided:
var element = document.getElementById('background');
var ctx = element.getContext("2d");
var camera = {};
// camera.offset marks the position seen at the upper left corner
// (It would be better if it marked the center)
// Let these be negative, so (0,0) scene position is at the center of the image
camera.offsetX = -element.width/2;
camera.offsetY = -element.height/2;
var obj = {};
obj.x = 50;
obj.y = 50;
element.addEventListener('click', animate, false);
function easing(x) {
return 0.5 + 0.5 * Math.sin((x - 0.5) * Math.PI);
}
function animate(evt){
// Transform click position from screen coordinates to scene coordinates
var targetX = evt.offsetX + camera.offsetX - element.width / 2,
targetY = evt.offsetY + camera.offsetY - element.height / 2;
var initialX = camera.offsetX,
initialY = camera.offsetY;
var deltaX = targetX - initialX,
deltaY = targetY - initialY;
var timeStart = Date.now();
var timeLength = 800;
var timer = setInterval(update, 10);
function stop(){
clearInterval(timer);
}
function update(){
var t = (Date.now() - timeStart) / timeLength;
if (t > 1) {
fraction(1);
stop();
} else {
fraction(easing(t));
}
}
function fraction(t){
camera.offsetX = initialX + t * deltaX,
camera.offsetY = initialY + t * deltaY;
}
}
function draw(){
ctx.clearRect(0,0,element.width,element.height);
ctx.fillStyle = 'red';
ctx.fillRect((element.width/2)-2,(element.height/2)-2,4,4);
ctx.fillStyle = 'blue';
// ===> Here the size and position arguments were swapped
ctx.fillRect(obj.x-camera.offsetX,obj.y-camera.offsetY, 20, 20);
}
// Consider using requestAnimationFrame
setInterval(draw, 10);

Categories