I've been trying different options to make an animated gradient page background but the performance of the page just sucks. It's causing a delay in my slide out JS menu and menu animations. I tried a JS version of the gradient, a CSS only version and still no luck. I tried this suggestion CSS performance relative to translateZ(0) and that didn't work either.
Are there any solutions to make an animated page background gradient that does not hurt the performance of the rest of the page? It's especially bad in Chrome and Safari but Firefox seems to handle it better.
Here is my testing site https://stacylauren-wp-stacymoorhead.c9users.io/ please excuse the lack of formatting, I'm just getting started on the layout. Here's my repo for the project https://github.com/stacymoorhead/portfolio-wordpress
This is what my javascript looks like that is applied to the body element as an ID:
var colors = new Array(
[252,238,33],
[217,224,33],
[140,198,63],
[0,176,176],
[147,39,143],
[212,20,90]);
var step = 0;
//color table indices for:
// current color left
// next color left
// current color right
// next color right
var colorIndices = [0,1,2,3];
//transition speed
var gradientSpeed = 0.002;
function updateGradient()
{
if ( $===undefined ) return;
var c0_0 = colors[colorIndices[0]];
var c0_1 = colors[colorIndices[1]];
var c1_0 = colors[colorIndices[2]];
var c1_1 = colors[colorIndices[3]];
var istep = 1 - step;
var r1 = Math.round(istep * c0_0[0] + step * c0_1[0]);
var g1 = Math.round(istep * c0_0[1] + step * c0_1[1]);
var b1 = Math.round(istep * c0_0[2] + step * c0_1[2]);
var color1 = "rgb("+r1+","+g1+","+b1+")";
var r2 = Math.round(istep * c1_0[0] + step * c1_1[0]);
var g2 = Math.round(istep * c1_0[1] + step * c1_1[1]);
var b2 = Math.round(istep * c1_0[2] + step * c1_1[2]);
var color2 = "rgb("+r2+","+g2+","+b2+")";
$('#gradient').css({
background: "-webkit-gradient(linear, left top, right bottom, from("+color1+"), to("+color2+"))"}).css({
background: "-moz-linear-gradient(left top, "+color1+" 0%, "+color2+" 100%)"});
step += gradientSpeed;
if ( step >= 1 )
{
step %= 1;
colorIndices[0] = colorIndices[1];
colorIndices[2] = colorIndices[3];
//pick two new target color indices
//do not pick the same as the current one
colorIndices[1] = ( colorIndices[1] + Math.floor( 1 + Math.random() * (colors.length - 1))) % colors.length;
colorIndices[3] = ( colorIndices[3] + Math.floor( 1 + Math.random() * (colors.length - 1))) % colors.length;
}
}
setInterval(updateGradient,10);
Is there even a solution? I am new to web development, and new to WordPress development so I'm just playing around on my portfolio to try and learn things.
Related
In looking to build a table seating/planning app. currently got a round table that i can dynamically add chairs around using code i found on stackoverflow. function is calculating the x,y absolut position of each seat around the table.
https://www.dropbox.com/s/4kvb0vre0dwtc0i/table.mov?dl=0
the video shows what i got so far.
for anyone interested the code for that is
export const calcRoundDimensions = (totalChairs, chairSize) => {
var chairspos = [];
var squareSize = chairSize * 2;
for (var i = 0; i < totalChairs; i++) {
var top = String(squareSize/2 + (-squareSize/2-chairSize) * Math.cos((360 / totalChairs / 180) * (i + 0) * Math.PI)) + 'px';
var left = String(squareSize/2 + (squareSize/2+chairSize) * (true ? Math.sin((360 / totalChairs / 180) * (i + 0) * Math.PI) : -Math.sin((360 / totalChairs / 180) * (i + 0) * Math.PI))) + 'px';
chairspos.push({top:top, left:left});
}
return {chairpos:chairspos, size:squareSize+chairSize};
}
I'm looking to do the same with a square one (also a rectangular one, but first thing's first).
square table would be fixed width (150px). I'm looking too be able to add chairs clockwise and have them centred on the side. (will have a 12 or 16 chair limit but this shouldn't matter i guess).
rectangle table would have one chair at either end then be able to add 5 or six chair on each of the longer ends.
searched the site but wasn't able to find much direction.
any help would be appreciated!
Not super clear on what you need but the following will get you positions of elements compared to the absolute top and left of the page:
const box = element.getBoundingClientRect();
const elementPosition = {
x:box.x+window.scrollX,
y:box.y+window.scrollY
};
I've been working on a specific animation in which I need to convert(with animation) a Rounded Rectangle Shape to Circle. I've checked the documentation of paper.js and haven't found any predefined function to achieve this.
-->
The animation needs to be smooth. As the number of rectangles I'm working with is very high, I can't use the "remove current rounded rect and redraw one more rounded version" method. It reduces the performace and the animation gets laggy.
This is the code I'm using to generate rounded rectangle.
// Had to paste something to post the question
// Though the whole code can be seen on codepen link
var rect = new Rectangle();
var radius = 100, origin = {x: 100, y: 100};
rect.size = new Size(radius, radius);
rect.center = new Point(origin.x, origin.y);
var cornerSize = radius / 4;
var shape = new Path.Rectangle(rect, cornerSize);
Prepared this Codepen example to show the progress.
If we can work out the whole animation using any other object types, that will be fine too. For now I can't find any any property which can transform the rounded rectangle to circle.
I'm also animating color of the object and position. I've gone through many documents to find out color animation.
PS: If there is any other(better) technique to animate colors of object, please share that too.
You will first have to create a path as a rounded rectangle. Then with each step in your animation you have to modify the eight segments of the path. This will only work with Path objects, not if your rectangle is a Shape.
The segment points and the handles have to be set like this:
κ (kappa) is defined in paper.js as Numerical.KAPPA (more on Kappa here).
The code to change the radius could look like this (Click here for the Sketch):
var rect = new Path.Rectangle(new Point(100, 100), new Size(100, 100), 30);
rect.fullySelected = true;
var step = 1;
var percentage = 0;
function onFrame(event) {
percentage += step;
setCornerRadius(rect, percentage)
if (percentage > 50 || percentage < 0) {
step *= -1;
}
}
function setCornerRadius(rectPath, roundingPercent) {
roundingPercent = Math.min(50, Math.max(0, roundingPercent));
var rectBounds = rectPath.bounds;
var radius = roundingPercent/100 * Math.min(rectBounds.width, rectBounds.height);
var handleLength = radius * Numerical.KAPPA;
l = rectBounds.getLeft(),
t = rectBounds.getTop(),
r = rectBounds.getRight(),
b = rectBounds.getBottom();
var segs = rectPath.segments;
segs[0].point.x = segs[3].point.x = l + radius;
segs[0].handleOut.x = segs[3].handleIn.x = -handleLength;
segs[4].point.x = segs[7].point.x = r - radius;
segs[4].handleOut.x = segs[7].handleIn.x = handleLength;
segs[1].point.y = segs[6].point.y = b - radius;
segs[1].handleIn.y = segs[6].handleOut.y = handleLength;
segs[2].point.y = segs[5].point.y = t + radius;
segs[2].handleOut.y = segs[5].handleIn.y = -handleLength;
}
Edit: I just found a much easier way using a shape. Not sure which approach performs faster.
Here is the implementation using a Shape (Click here for the Sketch).
var size = 100;
var rect = new Shape.Rectangle(new Rectangle(new Point(100, 100), new Size(size, size)), 30);
rect.strokeColor = "red";
var step = 1;
var percentage = 0;
function onFrame(event) {
percentage = Math.min(50, Math.max(0, percentage + step));
rect.radius = size * percentage / 100;
if (percentage >= 50 || percentage <= 0) {
step *= -1;
}
}
Change the corner size to the following
var cornerSize = circle.radius / 1;
I want to change color of the dot every time it hits the wall. I saw few solutions, but I don't know why mine isn't working.
Here's the part responsible for changing color:
function chColor() {
hex = Math.floor(Math.random() * 100000 + 1);
color = '"' + "#" + hex + '"';
color.toString();
return color;
}
And here is not working fiddle:
https://jsfiddle.net/vpzd7ye6/
Colour overkill
This answer is way overkill and I was about to discard it, but, why not give a Better random colour for those who may need it... (|:D
When random seams less random
Selecting a random totally random colour for us humans does not work that well if you wish to have a clear distinct change that attracts the eye from one colour to the next.
The problem is that many of the colour values available are very close to white or black and a totally random colour may be very close to the last making the change impossible to notice.
Simple random colour
So first the simple random colour picks a totally random colour from all of the 16,777,216 possible colours.
function randColor(){
return "#" +
(Math.floor(Math.random() * 0x1000000) + 0x1000000)
.toString(16)
.substr(1);
}
The function works by finding a random 24 bit number (0 - 0xFFFFFF same as 0 - 16777216). Because numbers do not have leading zeros added all random values below 0x100000 will, when converted to hex have less than 6 digit (the CSS colour value requires 3 or 6 digit Hex value) so I add 0x1000000 to ensure that the number is > 0x100000 and will always have 7 digits. As the first (left most) digit is not needed I use substr to remove it. Then added the "#" and return.
The function Number.toString(radix) takes an argument called radix which specifies the base the number is converted to. It defaults if not supplied to 10 (base ten is what we humans use). The hex colour is base 16 so that must be specified. The toString radix argument can be any value from 2 (binary) to 36 (which uses characters 0-9 then A-Z)
Less is more Random
Ironically we humans tend to find less random sequences more random than true random sequences. Many music players use this type of random sequence when they have the play set to shuffle, to ensure tracks are not played twice in a row or that repeated sequences of tracks are played by random chance.
To make the random colour seem more random and distinct you should track the last colour return so that you can ensure you are not close to that colour. You should also use a random colour that stays away from the whites and blacks.
var randColour = (function(){ // as singleton so closure can track last colour
var lastHue = 0;
const minChange = 360 / 3; // Hue distance from last random colour
var lastVal = false; // for low high saturation and luminance
const randomAmount = 360 / 3; // random hue range
const minVal = 20; // how far from full black white to stay (percent)
const minSat = 80; // how far from grey to stay (percent)
return function(){
var hueChange = Math.random() * randomAmount ;
hueChange *= Math.random() < 0.5 ? -1 : 1; // randomly move forward or backward
lastHue += 360 + hueChange + minChange; // move away from last colour
lastHue %= 360; // ensure colour is in valid range
var sat = (Math.random() * (100 - minSat)) + minSat; // get saturation (amount of colour)
var val = (Math.random() * (50 - minVal * 2)) * 1.5; // get value (luminance)
// switch between high and low and luminance
lastVal = ! lastVal;
if(lastVal){
val = minVal + val;
} else {
val = 100 - minVal - val;
}
return "hsl(" + lastHue.toFixed(0) + "," + sat.toFixed(0) + "%," + val.toFixed(0) + "%)";
}
})(); // call singleton
This function returns a random colour but ensures that the saturation and value stay within a specific range and that the hue is at least 1/3 around the colour wheel from the last value. It cycles between low and low and high luminance values to make the colour change as clear as possible. Closure is used to keep track of the last colour returned. The function returns the random colour as a CSS hsl(hue, saturation, luminance) color string.
There are two constants that control the colour sequence. minVal set to 20 is the percentage to stay away from full black or full white. Valid range is 0-~50 and minSat set to 80 is how far to stay away from grays in percent.
const minSat = 80; // how far from grey to stay (percent)
Compare change
To compare the two methods the following demo shows side by side a set of random colours using both methods, then flashes a new random colour 4 times a second. The simple random colour will appear from time to time to miss a change. I leave it up to you to pick which side is which.
var canvas = document.createElement("canvas");
canvas.width = 620;
canvas.height = 200;
var ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
var randColour = (function(){ // as singleton so closure can track last colour
var lastHue = 0;
const minChange = 360 / 3; // min hue change
var lastVal = false; // for low high saturation and luminance
const randomAmount = 360 / 3; // amount of randomness
const minVal = 20; // how far from full black white to stay (percent)
const minSat = 80; // how far from grey to stay (percent)
return function(){
var hueChange = Math.random() * randomAmount ;
hueChange *= Math.random() < 0.5 ? -1 : 1; // randomly move forward or backward
lastHue += 360 + hueChange + minChange; // move away from last colour
lastHue %= 360; // ensure colour is in valid range
var sat = (Math.random() * (100 - minSat)) + minSat; // get saturation (amount of colour)
var val = (Math.random() * (50 - minVal * 2)) * 1.5; // get value (luminance)
// switch between high and low and luminance
lastVal = ! lastVal;
if(lastVal){
val = minVal + val;
} else {
val = 100 - minVal - val;
}
return "hsl(" + lastHue.toFixed(0) + "," + sat.toFixed(0) + "%," + val.toFixed(0) + "%)";
}
})(); // call singleton
function randColor(){
return "#" +
(Math.floor(Math.random() * 0x1000000) + 0x1000000)
.toString(16)
.substr(1);
}
const grid = 16;
var gridX = 0;
var gridY = 0;
var bigSize = grid - (grid / 3 ) * 2;
const xStep = Math.floor((canvas.width - 12) / (grid * 2));
const yStep = Math.floor(canvas.height / grid);
var count = 0;
function drawRandomColour(){
ctx.fillStyle = randColor(); // simple random colour
ctx.fillRect(gridX * xStep, gridY * yStep, xStep, yStep);
ctx.fillStyle = randColour(); // smart random colour
ctx.fillRect(gridX * xStep + canvas.width / 2, gridY * yStep, xStep, yStep);
if(count < grid * grid - 1){ // fill the grid
gridX += 1; // move to next grid
if(gridX > grid-1){
gridX = 0;
gridY += 1;
gridY %= grid;
}
count += 1;
setTimeout(drawRandomColour,1); // quickly fill grid
return; // done for now
}
// if grid is full pick a random grid loc and request the next random colour
gridY = gridX = (grid / 3);
setTimeout(centerChange,250); // every quarter second
}
function centerChange(){
ctx.fillStyle = randColor(); // simple random colour
ctx.fillRect(gridX * xStep, gridY * yStep, xStep * bigSize, yStep * bigSize);
ctx.fillStyle = randColour(); // smart random colour
ctx.fillRect(gridX * xStep + canvas.width / 2, gridY * yStep, xStep * bigSize, yStep * bigSize);
setTimeout(centerChange,250); // every quarter second
}
drawRandomColour(); // start it up.
Compare sequences
This demo just draws the random colours as a sequence of random values. Examine the sequences to see how often you see two or more colours in a row that are hard to distinguish between. You will find that the sequence on the left has more similar sequences than the one on the right.
Expand demo to full-page view to see both sequences.
Click to redraw sequences.
var canvas = document.createElement("canvas");
canvas.width = 1240;
canvas.height = 800;
var ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
var randColour = (function(){ // as singleton so closure can track last colour
var lastHue = 0;
const minChange = 360 / 3; // min hue change
var lastVal = false; // for low high saturation and luminance
const randomAmount = 360 / 3; // amount of randomness
const minVal = 20; // how far from full black white to stay (percent)
const minSat = 80; // how far from grey to stay (percent)
return function(){
var hueChange = Math.random() * randomAmount ;
hueChange *= Math.random() < 0.5 ? -1 : 1; // randomly move forward or backward
lastHue += 360 + hueChange + minChange; // move away from last colour
lastHue %= 360; // ensure colour is in valid range
var sat = (Math.random() * (100 - minSat)) + minSat; // get saturation (amount of colour)
var val = (Math.random() * (50 - minVal * 2)) * 1.5; // get value (luminance)
// switch between high and low and luminance
lastVal = ! lastVal;
if(lastVal){
val = minVal + val;
} else {
val = 100 - minVal - val;
}
return "hsl(" + lastHue.toFixed(0) + "," + sat.toFixed(0) + "%," + val.toFixed(0) + "%)";
}
})(); // call singleton
function randColor(){
return "#" +
(Math.floor(Math.random() * 0x1000000) + 0x1000000)
.toString(16)
.substr(1);
}
const grid = 32;
var gridX = 0;
var gridY = 0;
const xStep = Math.floor((canvas.width - 12) / (grid * 2));
const yStep = Math.floor(canvas.height / grid);
var count = 0;
function drawRandomColour(){
ctx.fillStyle = randColor(); // simple random colour
ctx.fillRect(gridX * xStep, gridY * yStep, xStep, yStep);
ctx.fillStyle = randColour(); // smart random colour
ctx.fillRect(gridX * xStep + canvas.width / 2, gridY * yStep, xStep, yStep);
if(count < grid * grid - 1){ // fill the grid
gridX += 1; // move to next grid
if(gridX > grid-1){
gridX = 0;
gridY += 1;
gridY %= grid;
}
count += 1;
setTimeout(drawRandomColour,1); // quickly fill grid
return; // done for now
}
}
drawRandomColour(); // start it up.
// redraw on click
canvas.addEventListener("click",function(){
if(count >= grid * grid - 1){
gridX = gridY = count = 0;
drawRandomColour();
}else {
gridX = gridY = count = 0;
}
});
Summary
Though the second random function is not perfect, It can from time to time get colours that within a context appear similar this occurs much less than by pure random. When it is important for the user to notice a visual changes the best approch is to cycle two complementary colours (hue + 180) with one having a high luminance and the other a low. The CSS hsl colour string makes it easy to pick luminance and hue and when you want random colours gives you better control.
The problem is in converting number to hex color string.
So you can write a function that converts random number to valid hex color (see what this function does):
function convertToColor(num){
return '#' + ('00000' + (num | 0).toString(16)).substr(-6);
}
and then just use it in chColor function:
function chColor() {
number = Math.floor(Math.random() * 100000 + 1);
color = convertToColor(number);
return color;
}
Here is the link with working example: jsfiddle
Also it makes sense to rename function to getRandomColor:
function getRandomColor(){
number = Math.floor(Math.random() * 100000 + 1);
return convertToColor(number);
}
Please check updated fiddle
I just changed your chColor function on this:
function chColor() {
color = "#" + ((1 << 24) * Math.random() | 0).toString(16);
return color;
}
I have updated the fiddle. Link https://jsfiddle.net/vpzd7ye6/2/
I made the following change to your change color function;
function chColor() {
hex = Math.floor(Math.random() * 1000000) + 1;
color = '' + '#' + hex + '';
return color;
}
I was working on a fun project that implicates creating "imperfect" circles by drawing them with lines and animate their points to generate a pleasing effect.
The points should alternate between moving away and closer to the center of the circle, to illustrate:
I think I was able to accomplish that, the problem is when I try to render it in a canvas half the render jitters like crazy, you can see it in this demo.
You can see how it renders for me in this video. If you pay close attention the bottom right half of the render runs smoothly while the top left just..doesn't.
This is how I create the points:
for (var i = 0; i < q; i++) {
var a = toRad(aDiv * i);
var e = rand(this.e, 1);
var x = Math.cos(a) * (this.r * e) + this.x;
var y = Math.sin(a) * (this.r * e) + this.y;
this.points.push({
x: x,
y: y,
initX: x,
initY: y,
reverseX: false,
reverseY: false,
finalX: x + 5 * Math.cos(a),
finalY: y + 5 * Math.sin(a)
});
}
Each point in the imperfect circle is calculated using an angle and a random distance that it's not particularly relevant (it relies on a few parameters).
I think it's starts to mess up when I assign the final values (finalX,finalY), the animation is supposed to alternate between those and their initial values, but only half of the render accomplishes it.
Is the math wrong? Is the code wrong? Or is it just that my computer can't handle the rendering?
I can't figure it out, thanks in advance!
Is the math wrong? Is the code wrong? Or is it just that my computer can't handle the rendering?
I Think that your animation function has not care about the elapsed time. Simply the animation occurs very fast. The number of requestAnimationFrame callbacks is usually 60 times per second, So Happens just what is expected to happen.
I made some fixes in this fiddle. This animate function take care about timestamp. Also I made a gradient in the animation to alternate between their final and initial positions smoothly.
ImperfectCircle.prototype.animate = function (timestamp) {
var factor = 4;
var stepTime = 400;
for (var i = 0, l = this.points.length; i < l; i++) {
var point = this.points[i];
var direction = Math.floor(timestamp/stepTime)%2;
var stepProgress = timestamp % stepTime * 100 / stepTime;
stepProgress = (direction == 0 ? stepProgress: 100 -stepProgress);
point.x = point.initX + (Math.cos(point.angle) * stepProgress/100 * factor);
point.y = point.initY + (Math.sin(point.angle) * stepProgress/100 * factor);
}
}
Step by Step:
based on comments
// 1. Calculates the steps as int: Math.floor(timestamp/stepTime)
// 2. Modulo to know if even step or odd step: %2
var direction = Math.floor(timestamp/stepTime)%2;
// 1. Calculates the step progress: timestamp % stepTime
// 2. Convert it to a percentage: * 100 / stepTime
var stepProgress = timestamp % stepTime * 100 / stepTime;
// if odd invert the percentage.
stepProgress = (direction == 0 ? stepProgress: 100 -stepProgress);
// recompute position based on step percentage
// factor is for fine adjustment.
point.x = point.initX + (Math.cos(point.angle) * stepProgress/100 * factor);
point.y = point.initY + (Math.sin(point.angle) * stepProgress/100 * factor);
I am using Javascript to drag and simulate rotating an image by using multiple frames showing the image in 360 degrees. I am relatively new to JavaScript and am having a hard time with the script in trying to insert a trigger that would cause overlaying images to fade in and out when certain frames (degrees) of the image are displayed. For example, when I drag, rotate and reveal the front side of the image, let's say a range of frame 10 to frame 45, 4 popup labels will fade in (simultaneously) and remain visible until I drag and rotate the image away from that range of frame, causing the labels to fade out. On the backside of the image I would like to have 3 popup labels appear once any frame within the acceptable range of frames are displayed, let's say, frames 95 through 135. Is this possible? Please see the code that I have been working off of below:
/*** configuration variables ***/
var
totalFrames = 72,
frameUrlTemplate =
'images/frames/Skeleton_[#frame].jpg'
;
/*** state variables ***/
var
rotation = 0,
lastFrameNo = -1,
dragStartRotation
;
/*** create the Uize.Widget.Drag instance ***/
var rotationViewer = page.addChild (
'rotationViewer',
Uize.Widget.Drag,
{
cancelFade:{duration:2000,curve:Uize.Curve.Rubber.easeOutBounce ()},
releaseTravel:function (speed) {
var
deceleration = 2000, // measured in pixels/s/s
duration = speed / deceleration
;
return {
duration:duration,
distance:Math.round (speed * duration / 2),
curve:function (_value) {return 1 - (_value = 1 - _value) * _value}
};
},
html:function (input) {
var
htmlChunks = [],
frameNodeIdPrefix = input.idPrefix + '-frame'
;
for (var frameNo = 0; ++frameNo <= totalFrames;) {
htmlChunks.push (
'<img' +
' id="' + frameNodeIdPrefix + frameNo + '"' +
' src="' + Uize.substituteInto (frameUrlTemplate,{frame:(frameNo < 10 ? '0' : '') + frameNo}) +'"' +
'/>'
);
}
return htmlChunks.join ('');
},
built:false
}
);
/*** wire up the drag widget with events for updating rotation degree ***/
function updateRotation (newRotation) {
rotation = ((newRotation % 360) + 360) % 360;
var frameNo = 1 + Math.round (rotation / 360 * (totalFrames - 1));
if (frameNo != lastFrameNo) {
rotationViewer.showNode ('frame'+ lastFrameNo,false);
rotationViewer.showNode ('frame'+ (lastFrameNo = frameNo));
}
}
rotationViewer.wire ({
'Drag Start':function () {dragStartRotation = rotation},
'Drag Update':function (e) {updateRotation (dragStartRotation - e.source.eventDeltaPos [0] / -2.5)}
});
/*** function for animating spin ***/
function spin (degrees,duration,curve) {
Uize.Fade.fade (updateRotation,rotation,rotation + degrees,duration,{quantization:1,curve:curve});
}
/*** initialization ***/
Uize.Node.wire (window,'load',function () {spin (-360,2700,Uize.Curve.easeInOutPow (4))});
/*** wire up the page widget ***/
page.wireUi ();
I'd appreciate any advice on this. Thanks!!
-Adam
there are 3d transforms in javascrip fot html elements, even a few libaries.
if its a flat image, use that.
if its 3d you wish to simulate you already get very realistc effect with just 120 pictures.
rotation = ((newRotation % 360) + 360) % 360;
var frameNo = 1 + Math.round (rotation / 360 * (totalFrames -1));
if (frameNo > 0 && frameNo< 60 )//code to show box