Please help me figure it out. There is a text animation effect on click on the screen, it is written in "tween.js". Does anyone know how to create such an effect on "tween.js"?
Here is the link: https://michalzalobny.com/orbit-gallery
I tried to read the "tween.js" documentation and looked at the examples, but nothing like that is written there.
Not sure about Tween.JS, but here's how to do it using vanilla JavaScript in order to toggle a class, and let CSS handle the rest.
The staggered characters animation effect is made possible by assigning a CSS var --anim-delay to each character SPAN with a value of the respective SPAN index, later used in CSS as the transition-delay:
// DOM helper functions:
const el = (sel, par) => (par || document).querySelector(sel);
const elNew = (tag, prop) => Object.assign(document.createElement(tag), prop);
// Staggered characters flip effect:
const elText = el("#text");
const words = ["Discover", "Swipe", "Culture"];
// Create SPANs for words and charactres
words.forEach(word => {
const elsChars = [...word].map((char, i) => {
const elChar = elNew("span", { className: "char", textContent: char });
elChar.style.setProperty("--anim-delay", i);
return elChar;
});
const elWord = elNew("span", { className: "word" });
elWord.append(...elsChars);
elText.append(elWord);
});
// Animate on pointer events:
el("body").addEventListener("pointerdown", () => {
elText.classList.add("is-pressed");
});
el("body").addEventListener("pointerup", () => {
elText.classList.remove("is-pressed");
});
#text {
display: flex;
justify-content: center;
gap: 2rem;
-webkit-font-smoothing: antialiased;
font-smoothing: antialiased;
perspective: 600px;
}
.word {
font-size: 9vw;
display: inline-flex;
pointer-events: none;
user-select: none;
}
.char {
transition:
transform 0.3s calc(var(--anim-delay) * 20ms) ease-in-out,
opacity 0.3s calc(var(--anim-delay) * 20ms) ease-in-out;
opacity: 1;
transform-origin: center center 0.4em;
}
.is-pressed .char {
transform: rotate3d(-1, -0.4, 0, 90deg);
opacity: 0;
}
(Click and hold)
<div id="text"></div>
ANSWER for the translateX value (thanks to Albert Portnoy):
var style = window.getComputedStyle(div);
var xVal = parseFloat(style.transform.split(" ")[4].replace(",", ''));
How do I get the current transform value of an element which is animated with #keyframes in javascript?
There doesn't seem to be a change of the css value I used (translateX) when it is animated or it has finished
<style>
#keyframes anim {
from {
transform: translateX(0px)
}
to {
transform: translateX(400px)
}
}
div {
width: 50px;
height: 50px;
background: black;
animation: anim 5s forwards linear;
}
</style>
<div></div>
<script>
var div = document.getElementsByTagName('div')[0];
function loop() {
setTimeout(function () {
console.log(div.style);
loop()
}, 100)
}
loop()
</script>
You can use (the not yet standard) feature CSSMatrix.
Another helpful explanation about Calculating element vertex data from CSS transforms
Here is a running example, note that i used requestanimationFrame instead of a callback loop with setTimeout to run the code on each frame.
var el = document.getElementById('root');
let count = 0;
function loop() {
requestAnimationFrame(() => {
var style = window.getComputedStyle(el);
var matrix = new WebKitCSSMatrix(style.webkitTransform);
console.log('translateX: ', matrix.m41);
if(count > 100){
// just to stop the infinite loop...
return;
}
count++;
loop();
})
}
loop()
#keyframes anim {
from {
transform: translateX(0px)
}
to {
transform: translateX(400px)
}
}
#root {
width: 50px;
height: 50px;
background: black;
animation: anim 5s forwards linear;
}
<div id="root"/>
I want to integrate this script to my website homepage and i don't know how. I tried to integrate code to function.php but it doesn't work.
The script :
(function(){
var PleaseRotate = {},
currentOrientation = null,
isMobile = /Android|iPhone|iPad|iPod|IEMobile|Opera Mini/i.test(navigator.userAgent),
init = false;
var options = {
startOnPageLoad: true,
onHide: function(){},
onShow: function(){},
forcePortrait: false,
message: "Please Rotate Your Device",
subMessage: "(or click to continue)",
allowClickBypass: true,
onlyMobile: true,
zIndex: 1000,
iconNode: null
};
var cssRules = [
"#pleaserotate-graphic { margin-left: 50px; width: 200px; animation: pleaserotateframes ease 2s; animation-iteration-count: infinite; transform-origin: 50% 50%; -webkit-animation: pleaserotateframes ease 2s; -webkit-animation-iteration-count: infinite; -webkit-transform-origin: 50% 50%; -moz-animation: pleaserotateframes ease 2s; -moz-animation-iteration-count: infinite; -moz-transform-origin: 50% 50%; -ms-animation: pleaserotateframes ease 2s; -ms-animation-iteration-count: infinite; -ms-transform-origin: 50% 50%; }",
"#pleaserotate-backdrop { background-color: white; top: 0; left: 0; position: fixed; width: 100%; height: 100%; }",
"#pleaserotate-container { width: 300px; position: absolute; top: 50%; left: 50%; margin-right: -50%; transform: translate(-50%, -50%); -webkit-transform: translate(-50%, -50%); }",
"#pleaserotate-message { margin-top: 20px; font-size: 1.3em; text-align: center; font-family: Verdana, Geneva, sans-serif; text-transform: uppercase }",
"#pleaserotate-message small { opacity: .5; display: block; font-size: .6em}"
];
var cssKeyframeRules = [
"pleaserotateframes{ 0% { transform: rotate(0deg) ; -moz-transform: rotate(0deg) ;-webkit-transform: rotate(0deg) ;-ms-transform: rotate(0deg) ;} 49% { transform: rotate(-90deg) ;-moz-transform: rotate(-90deg) ;-webkit-transform: rotate(-90deg) ; -ms-transform: rotate(-90deg) ; } 100% { transform: rotate(90deg) ;-moz-transform: rotate(-90deg) ;-webkit-transform: rotate(-90deg) ; -ms-transform: rotate(-90deg) ; } }",
];
/* private functions */
function overrideOptions(updates){
var prop;
for (var prop in updates){
options[prop] = updates[prop];
}
}
function setBodyClass(state){
if(document.documentElement){
document.documentElement.className = document.documentElement.className.replace( /(?:^|\s)pleaserotate-\S*/g , '' );
document.documentElement.className += " pleaserotate-" + state;
}
}
function addRules(sheet){
var i;
for(i = 0; i< cssRules.length; i++){
sheet.insertRule(cssRules[i], 0);
}
sheet.insertRule("#pleaserotate-backdrop { z-index: " + options.zIndex + "}", 0);
if(options.allowClickBypass){
sheet.insertRule("#pleaserotate-backdrop { cursor: pointer }", 0);
}
if(options.forcePortrait){
sheet.insertRule("#pleaserotate-backdrop { -webkit-transform-origin: 50% }", 0);
}
for(i = 0; i< cssKeyframeRules.length; i++){
if (CSSRule.WEBKIT_KEYFRAMES_RULE) { // WebKit
sheet.insertRule("#-webkit-keyframes " + cssKeyframeRules[i], 0);
}
else if (CSSRule.MOZ_KEYFRAMES_RULE) { // Mozilla
sheet.insertRule("#-moz-keyframes " + cssKeyframeRules[i], 0);
}
else if (CSSRule.KEYFRAMES_RULE) { // W3C
sheet.insertRule("#keyframes " + cssKeyframeRules[i], 0);
}
}
}
function createStyleSheet(){
var style = document.createElement("style");
style.appendChild(document.createTextNode("")); // I'm told we need this hack... something to do with safari but I don't feel like checking for sure
document.head.insertBefore(style, document.head.firstChild);
addRules(style.sheet);
}
function createElements(){
var backdrop = document.createElement("div"),
container = document.createElement("div"),
message = document.createElement("div"),
subMessage = document.createElement("small");
backdrop.setAttribute("id", "pleaserotate-backdrop");
container.setAttribute("id", "pleaserotate-container");
message.setAttribute("id", "pleaserotate-message");
backdrop.appendChild(container);
if(options.iconNode !== null){
container.appendChild(options.iconNode);
} else {
container.appendChild(createPhoneSVG());
}
container.appendChild(message);
message.appendChild(document.createTextNode(options.message));
subMessage.appendChild(document.createTextNode(options.subMessage));
message.appendChild(subMessage);
document.body.appendChild(backdrop);
}
function createPhoneSVG(){
var svg = document.createElementNS('http://www.w3.org/2000/svg','svg');
svg.setAttributeNS('http://www.w3.org/2000/xmlns/','xmlns:xlink','http://www.w3.org/1999/xlink');
svg.setAttribute('id','pleaserotate-graphic');
svg.setAttribute('viewBox','0 0 250 250');
var group = document.createElementNS('http://www.w3.org/2000/svg','g');
group.setAttribute('id','pleaserotate-graphic-path');
if(options.forcePortrait){
group.setAttribute('transform','rotate(-90 125 125)');
}
var path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
path.setAttribute('d', 'M190.5,221.3c0,8.3-6.8,15-15,15H80.2c-8.3,0-15-6.8-15-15V28.7c0-8.3,6.8-15,15-15h95.3c8.3,0,15,6.8,15,15V221.3z' +
'M74.4,33.5l-0.1,139.2c0,8.3,0,17.9,0,21.5c0,3.6,0,6.9,0,7.3c0,0.5,0.2,0.8,0.4,0.8s7.2,0,15.4,0h75.6c8.3,0,15.1,0,15.2,0' +
's0.2-6.8,0.2-15V33.5c0-2.6-1-5-2.6-6.5c-1.3-1.3-3-2.1-4.9-2.1H81.9c-2.7,0-5,1.6-6.3,4C74.9,30.2,74.4,31.8,74.4,33.5z' +
'M127.7,207c-5.4,0-9.8,5.1-9.8,11.3s4.4,11.3,9.8,11.3s9.8-5.1,9.8-11.3S133.2,207,127.7,207z');
svg.appendChild(group);
group.appendChild(path);
return svg;
}
function setVisibility(visible){
var backdropElement = document.getElementById("pleaserotate-backdrop");
if(visible){
if(backdropElement){
backdropElement.style["display"] = "block";
}
} else {
if(backdropElement){
backdropElement.style["display"] = "none";
}
}
}
function orientationChanged(){
var triggerOn = currentOrientation && !options.forcePortrait || !currentOrientation && options.forcePortrait,
propogate;
if(triggerOn){
propogate = options.onShow();
setBodyClass("showing");
} else {
propogate = options.onHide();
setBodyClass("hiding");
}
if(propogate !== undefined && !propogate){
return;
}
PleaseRotate.Showing = triggerOn;
setVisibility(triggerOn);
}
function isPortrait(){
return ( window.innerWidth < window.innerHeight);
}
function checkOrientationChange(){
if(!isMobile && options.onlyMobile){
if(!init){
init = true;
setVisibility(false);
setBodyClass("hiding");
options.onHide(); // run this exactly once if not mobile
}
return;
}
if(currentOrientation !== isPortrait()){
currentOrientation = isPortrait();
orientationChanged();
}
}
/* public functions */
PleaseRotate.start = function(opts){
if(!document.body){
window.addEventListener('load', PleaseRotate.start.bind(null, opts), false);
return;
}
if(opts){
overrideOptions(opts);
}
createStyleSheet();
createElements();
checkOrientationChange();
window.addEventListener( 'resize', checkOrientationChange, false );
if(options.allowClickBypass){
document.getElementById("pleaserotate-backdrop").addEventListener("click", function(){
var propogate = options.onHide();
setBodyClass("hiding");
PleaseRotate.Showing = false;
if(propogate === undefined || propogate){
setVisibility(false);
}
});
}
}
PleaseRotate.stop = function(){
window.removeEventListener('resize', onWindowResize, false);
}
PleaseRotate.onShow = function(fn){
options.onShow = fn;
if(init){
// if we have already been initialized, force a check
init = false;
currentOrientation = null;
checkOrientationChange();
}
};
PleaseRotate.onHide = function(fn){
options.onHide = fn;
if(init){
// if we have already been initialized, force a check so that onHide gets called
currentOrientation = null;
init = false;
checkOrientationChange();
}
};
PleaseRotate.Showing = false;
/* plumbing to support AMD, CommonJS, or Globals */
if (typeof define === 'function' && define.amd) {
setBodyClass("initialized");
define(['PleaseRotate'], function() {
return PleaseRotate;
});
} else if (typeof exports === 'object') {
setBodyClass("initialized");
module.exports = PleaseRotate;
} else {
setBodyClass("initialized");
window.PleaseRotate = PleaseRotate;
overrideOptions(window.PleaseRotateOptions);
if (options.startOnPageLoad) {
PleaseRotate.start();
}
}
})();
If you want the JavaScript to be on the homepage only, you can do this:
function wpdocs_scripts_method() {
if ( is_home() ) {
wp_enqueue_script( 'custom-script', get_stylesheet_directory_uri() . '/js/custom_script.js', false ) );
}
}
add_action( 'wp_enqueue_scripts', 'wpdocs_scripts_method' );
Create a JavaScript file, and then place your code in there. Then replace the path and filename in the function above, and the script should be included on the homepage of your website. This code snippet should be placed in your functions.php file.
To read more: https://developer.wordpress.org/reference/functions/wp_enqueue_script/
This codepen shows my problem: http://codepen.io/PiotrBerebecki/pen/pNvpdG
When the user clicks on the big button the css opacity is reduced to 0. Since I've applied the following rule: transition: opacity 0.5s ease-in-out; the fade out animation is smooth.
I would like to achieve the same smooth transition when the next button fades in.
However for some reason the next button appears suddenly without any transition.
Would you know what causes the issue and how to fix it?
console.clear();
(function() {
// Data for the app
const model = {
buttons: ['tomato', 'blue'],
currentButton: -1
};
// Logic for the app
const controller = {
init: function() {
view.init();
},
getButtonName: function() {
model.currentButton = (model.currentButton + 1) % model.buttons.length;
return model.buttons[model.currentButton];
}
};
// View for the app
const view = {
init: function() {
this.root = document.getElementById('root');
this.showNext();
},
animationDelay: 500,
showNext: function() {
// Get next button name
const buttonName = controller.getButtonName();
// Create button DOM element
const buttonElement = document.createElement('div');
buttonElement.className = 'button';
buttonElement.id = buttonName;
buttonElement.textContent = buttonName;
buttonElement.style.opacity = 0;
// Add event listender for the button
buttonElement.addEventListener('click', event => {
// Reduce opacity
buttonElement.style.opacity = 0;
// Remove the button from DOM
setTimeout(() => {
this.root.removeChild(buttonElement);
}, this.animationDelay + 10);
// Start the function to show next button
setTimeout(() => {
this.showNext();
}, this.animationDelay + 20);
});
// Add button to DOM
this.root.appendChild(buttonElement);
// Show button by increasing opacity
buttonElement.style.opacity = 1;
}
};
// Start the app
controller.init();
}());
#tomato {
background: tomato;
}
#blue {
background: DeepSkyBlue;
}
.button {
transition: opacity 0.5s ease-in-out;
width: 100%;
height: 50vh;
border: solid 3px black;
cursor: pointer;
}
<div id="root"></div>
This should work , Code pen link: http://codepen.io/saa93/pen/gLbvmQ
You would need to add this instead of directly setting opacity to 1
// Show button by increasing opacity
buttonElement.style.opacity = 0;
setTimeout(() => {
buttonElement.style.opacity = 1;
}, this.animationDelay + 20);
Add a class (in the Snippet is .active) add the following:
CSS
.button {
opacity: 0;
transition: opacity 0.5s ease-in-out;
width: 100%;
height: 50vh;
border: solid 3px black;
cursor: pointer;
}
.button.active {
opacity: 1;
transition: opacity 0.5s ease-in-out;
}
JavaScript
...
// Reduce opacity
buttonElement.classList.toggle('active');
buttonElement.style.opacity = 0;
...
// Show button by increasing opacity
buttonElement.classList.toggle('active');
buttonElement.style.opacity = 1;
SNIPPET
console.clear();
(function() {
// Data for the app
const model = {
buttons: ['tomato', 'blue'],
currentButton: -1
};
// Logig for the app
const controller = {
init: function() {
view.init();
},
getButtonName: function() {
model.currentButton = (model.currentButton + 1) % model.buttons.length;
return model.buttons[model.currentButton];
}
};
// View for the app
const view = {
init: function() {
this.root = document.getElementById('root');
this.showNext();
},
animationDelay: 500,
showNext: function() {
// Get next button name
const buttonName = controller.getButtonName();
// Create button DOM element
const buttonElement = document.createElement('div');
buttonElement.className = 'button';
buttonElement.id = buttonName;
buttonElement.textContent = buttonName;
buttonElement.style.opacity = 0;
// Add event listender for the button
buttonElement.addEventListener('click', event => {
// Reduce opacity
buttonElement.classList.toggle('active');
buttonElement.style.opacity = 0;
// Remove the button from DOM
setTimeout(() => {
this.root.removeChild(buttonElement);
}, this.animationDelay + 10);
// Start the function to show next button
setTimeout(() => {
this.showNext();
}, this.animationDelay + 20);
});
// Add button to DOM
this.root.appendChild(buttonElement);
// Show button by increasing opacity
buttonElement.classList.toggle('active');
buttonElement.style.opacity = 1;
}
};
// Start the app
controller.init();
}());
#tomato {
background: tomato;
}
#blue {
background: DeepSkyBlue;
}
.button {
opacity: 0;
transition: opacity 0.5s ease-in-out;
width: 100%;
height: 50vh;
border: solid 3px black;
cursor: pointer;
}
.button.active {
opacity: 1;
transition: opacity 0.5s ease-in-out;
}
<div id="root"></div>
after this.root.appendChild(buttonElement);
you should set opacity to 0 and let the browser time to render before buttonElement.style.opacity = 1;
BTW I think removing and adding the element of not a good way to do this
.button {
width: 100%;
height: 50vh;
border: solid 3px black;
cursor: pointer;
animation-name: example;
animation-duration:3.5s;
}
#keyframes example {
0% {opacity:1}
50% {opacity:0}
100% {opacity:1}
}
What U really want is to use animation like this:JSFIDDLE EXAMPLE
This way the animation does all this timing and opacity back and forth using the css only
I have a blinking red box in my html it uses css animations. I want to to be able to change it from blinking red and white to green and white. I know this can be done on id elements by using getElementbyId but how would get access to the green aminated box in the css.
The red box looks like this:
#-webkit-keyframes 'noConnection'
{
1% { background-color: red; }
33% { background: white; }
66% { background: red; }
100% { background: white; }
}
The green is this:
#-webkit-keyframes 'Connection'
{
1% { background-color: green; }
33% { background: white; }
66% { background: green; }
100% { background: white; }
}
The animate looks like this:
#animate {
height: 15px;
width: 15px;
}
.cssanimations #animate {
-webkit-animation-direction: normal;
-webkit-animation-duration: 5s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-name: Connection;
-webkit-animation-timing-function: ease;
and I think I have to change the attribute -webkit-animation-name: from javascript to do this but I dont know how to get a handle on it to change it.
Or would I be better off creating a duplicate #animate and renaming it using the getElementById?
Here is a simple web page that demonstrates how to use Javascript to modify a CSS animation. It contains a simple div, and a little Javascript causes the div to move randomly around the page.
In your specific case, you just need to touch up the line that calls "insertRule" to insert your new blinking rule.
<html><head><style></style></head>
<body>
<div id="mymovingdiv">
<h1>Moving Div</h1>
<p>And some little text too</p>
</div>
<script>
function animatedMove(id, xStart, yStart, xEnd, yEnd, secs)
{
// Remove any CSS rules inserted by a previous call to this method
let rulename = `AnimMove${id}`;
let ss = document.styleSheets; // all stylesheets
for (let i = 0; i < ss.length; ++i) { // for each stylesheet...
for (let j = ss[i].cssRules.length - 1; j > 0; j--) { // for each rule...
if (ss[i].cssRules[j].name === rulename) { // does the name match?
ss[i].deleteRule(j);
}
}
}
// Insert a CSS rule for this animation
document.styleSheets[0].insertRule(`#keyframes ${rulename} { 0% { left: ${xStart}px; top: ${yStart}px; } 100% { left: ${xEnd}px; top: ${yEnd}px } }`);
// Remove any CSS rules inserted by a previous call to this method
for (let i = 0; i < ss.length; ++i) { // for each stylesheet...
for (let j = ss[i].cssRules.length - 1; j > 0; j--) { // for each rule...
if (ss[i].cssRules[j].name === rulename) { // does the name match?
ss[i].deleteRule(j);
}
}
}
// Insert a CSS rule for this animation
document.styleSheets[0].insertRule(`#keyframes ${rulename} { 0% { left: ${xStart}px; top: ${yStart}px; } 100% { left: ${xEnd}px; top: ${yEnd}px } }`);
// assign the animation to our element
let el = document.getElementById(id);
el.style.position = 'absolute';
el.style.animation = `${rulename} ${secs}s`;
// Make the element stay where the animation ends
el.style.left = `${xEnd}px`;
el.style.top = `${yEnd}px`;
// Re-clone the element, to reset the animation
el.parentNode.replaceChild(el.cloneNode(true), el);
}
let x = 0;
let y = 0;
function randomMove()
{
let newX = Math.floor(Math.random() * 800);
let newY = Math.floor(Math.random() * 600);
animatedMove('mymovingdiv', x, y, newX, newY, 1);
x = newX;
y = newY;
}
setInterval(randomMove, 1000);
</script>
</body>
</html>
The easiest way to do this is to created two classes in CSS and then toggle between the two.
So something like:
.connection {
animation: 'Connection' 5s ease infinite
}
.no-connection {
animation 'noConnection' 5s ease infinite
}
And then use Javascript to toggle between the two
function toggleConnectionStatus(){
var element = document.getElementById('animate');
if(/* connection is active */) element.className = 'connection';
else element.className = 'no-connection'
}