First post here. Hope you can help me out with a problem I'm having:
I am writing a game, where a user needs to guess a word from shuffled letters by clicking on each letter to insert it in the first empty space of a "correct" field.
Now, when a letter is clicked, it needs to move to its new spot in an animated way. As I'm using span to create a separate field for each letter I couldn't figure out how to make this span move to its new location in an animated way using CCS3/JavaScript/JQuery.
The code is in JSFiddle here: http://jsfiddle.net/Pfsqu/
JS:
var randomNumber = Math.floor(Math.random() * words.length);
var word = words[randomNumber];
var chars = word.split('');
chars=_.shuffle(chars);
for (var i in chars) {
$('#shuffled').append('<span>'+chars[i]+'</span>');
$('#correct').append('<span>');
}
$('#shuffled > span').click(function() {
var letter = $(this);
letter.replaceWith('<span>');
$('#correct > span:empty').first().append( letter ); /* this part needs to be animated*/
CSS:
p > span{
background-color: white;
margin: 10px;
-webkit-border-radius: 15px;
border-radius: 15px;
width: 2.5em;
height: 2.5em;
display: inline-block;
text-align: center;
line-height: 2.5em;
vertical-align: middle;
animation: 1000ms move ease-in-out;
-webkit-animation: 1000ms move ease-in-out;
}
I think that it is quite difficult to animate the items the way that you are intending.
The way I would solve it would be keeping the same DOM element, and changing its properties.
For instance, see this
demo
The HTML is
<div class="solution">
<span class="q q4">W</span>
<span class="q q2">O</span>
<span class="q q3">R</span>
<span class="q q1">D</span>
</div>
I have set the letters of WORD in order, and then I have set to them one of the classes q1 to q4. This class will set the span to a specific position on screen.
This is achieved in this CSS (and also the position for the "solved" status
.solution {
margin-top: 100px;
-webkit-transition: all 5s;
position: relative;
}
.solution span {
border: solid 1px green;
padding: 10px;
margin-top: 80px;
-webkit-transition: all 2s;
position: absolute;
background-color: lightgreen;
font-size: 30px;
}
.solution span:nth-child(1) {
-webkit-transform: translate(0px, 0px) rotate(0deg);
}
.solution span:nth-child(2) {
-webkit-transform: translate(80px, 0px) rotate(0deg);
}
.solution span:nth-child(3) {
-webkit-transform: translate(160px, 0px) rotate(0deg);
}
.solution span:nth-child(4) {
-webkit-transform: translate(240px, 0px) rotate(0deg);
}
div.solution span.q {
background-color: yellow !important;
border: solid 1px red;
border-radius: 50%;
}
.solution .q.q1 {
-webkit-transform: translate(0px, -100px) rotate(360deg);
}
.solution .q.q2 {
-webkit-transform: translate(80px, -100px) rotate(360deg);
}
.solution .q.q3 {
-webkit-transform: translate(160px, -100px) rotate(360deg);
}
.solution .q.q4 {
-webkit-transform: translate(240px, -100px) rotate(360deg);
}
Now the jQuery is very easy
$('.q').click(function(){
$(this).removeClass('q');
});
I have used the webkit prefixes, but you can easily set it to work for others browsers
Edited answer:
Changing the nth-child styles to:
.answer1 {
-webkit-transform: translate(0px, 0px) rotate(0deg);
}
.answer2 {
-webkit-transform: translate(80px, 0px) rotate(0deg);
}
.answer3 {
-webkit-transform: translate(160px, 0px) rotate(0deg);
}
.answer4 {
-webkit-transform: translate(240px, 0px) rotate(0deg);
}
and the script to:
var element = 1;
$('.q').click(function(){
$(this).removeClass('q').addClass("answer" + element);
element = element + 1;
});
You got, as per your request, that the letters go to the first available place.
The only remining task is to construct the spans from the array of letters.
I think that you have already some code that does quite a similar job; it's only a matter of adapting it.
updated demo
Related
Take a look at this simple JsFiddle I created.
What it does is simply inserts a new li element with a slide effect from left, when the ul display is on flex and inline-block.
Something similar to that is Stackoverflow chat avatars when someone joins.
#-webkit-keyframes enter {
0% { /*opacity:0;*/ -webkit-transform: translateX(-100%); }
100% { /*opacity:1;*/ -webkit-transform: translateX(0px); }
}
#-webkit-keyframes moves {
0% { /*opacity:0;*/ -webkit-transform: translateX(-50px); }
100% { /*opacity:1;*/ -webkit-transform: translateX(0px); }
}
in my enter animation, I start with translate -100% because I want my item come from left distanced by his size.
and in the moves animation, I want to move the whole ul to the right, by the size of the entering element.
Now I set it hard-coded, to 50px because my elements are set to 50px:
li {
width: 50px;
height: 50px;
display: inline-block;
background-color: red;
}
How can I make it calculate the width OR height automatically, on how much to translate the ul?
Example: Calculate these 50px automatically
You can do this by animating only the added element by using negative margin:
setTimeout(() => {
var item = $("<li></li>").addClass("enter");
$("ul").prepend(item).addClass('move');
}, 2000);
ul {
display: flex;
transition-timing-function: ease-out;
transition: all .2s;
}
li {
--h:50px;
width: 50px;
height: var(--h);
display: inline-block;
background-color: red;
}
.enter {
animation: enter 1s;
}
#keyframes enter {
0% {
transform: translateX(-100%);
margin-left: calc(var(--h) * -1);
}
100% {
transform: translateX(0px);
margin-left: 0
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="my-flex-thing">a</li>
<li class="my-flex-thing">b</li>
</ul>
I am trying to use ngRepeat to load an image and play it's associated tone, then move the image from the center of the circle to a specific position on a circle, and proceed with the doing the same thing with the next image. I got the images to display and move one by one using ng-enter-stagger, however the images have different positions so when I change it to to use a different class for each repetition, ng-enter-stagger does not work.
How can I go about loading one image, moving it to the proper position, hiding the image, then proceeding with the next image?
I have created a plunkr but the animation does not work in it https://plnkr.co/edit/DddST6JsemsCKKf3mQ6N?p=preview.
An example of what I want to do is the Learn the sounds part of this (http://www.absolutepitchstudy.com/animalgame/) click either Start Control or Start Animal Game
The data looks like this:
"ImageTones":[{"CPosition":"deg60","Image":{"ImageFileName":"Alligator.png","ImageId":1},"Tone":{"ToneFileName":"C3.mp4","ToneId":1}},
{"CPosition":"deg0","Image":{"ImageFileName":"Cow.png","ImageId":4},"Tone":{"ToneFileName":"B5.mp4","ToneId":2}},
{"CPosition":"deg270","Image":{"ImageFileName":"Bird.png","ImageId":3},"Tone":{"ToneFileName":"E3.mp4","ToneId":3}}]
Html page:
<div class="circle-container">
<div ng-repeat="it in model.imageTones" class="it.CPosition">
<img ng-src="../Content/Game/Animals/{{it.Image.ImageFileName}}"/>
<!--Audio tag goes here-->
</div>
</div>
My CSS (I may be able to fix this to not have as many classes, just am unsure how)
.circle-container {
position: relative;
width: 38em;
height: 38em;
padding: 2.8em;
/*2.8em = 2em*1.4 (2em = half the width of a link with img, 1.4 = sqrt(2))*/
border: dashed 1px;
border-radius: 80%;
margin: -5.25em auto 0;
}
.circle-container div {
display: block;
position: absolute;
top: 50%;
left: 50%;
width: 4em;
height: 4em;
margin: -2em;
}
.circle-container div.ng-enter {
transition: 5s linear all;
opacity: 0;
}
.circle-container div.ng-enter-stagger {
/* this will have a 100ms delay between each successive leave animation */
transition-delay: 5.0s;
/* As of 1.4.4, this must always be set: it signals ngAnimate
to not accidentally inherit a delay property from another CSS class */
transition-duration: 0s;
}
.circle-container div.ng-enter.ng-enter-active {
/* standard transition styles */
opacity:1;
}
.deg0.ng-enter-active {
transform: translate(19em);
}
.deg30.ng-enter-active {
transform: rotate(30deg) translate(19em) rotate(-30deg);
}
.deg60.ng-enter-active {
transform: rotate(60deg) translate(19em) rotate(-60deg);
}
.deg90.ng-enter-active {
transform: rotate(90deg) translate(19em) rotate(-90deg);
transition: transform 5s;
}
.deg120.ng-enter-active {
transform: rotate(120deg) translate(19em) rotate(-120deg);
}
.deg150.ng-enter-active {
transform: rotate(150deg) translate(19em) rotate(-150deg);
}
.deg180.ng-enter-active {
transform: rotate(180deg) translate(19em) rotate(-180deg);
}
.deg210.ng-enter-active {
transform: rotate(210deg) translate(19em) rotate(-210deg);
}
.deg240.ng-enter-active {
transform: rotate(240deg) translate(19em) rotate(-240deg);
}
.deg270.ng-enter-active {
transform: rotate(270deg) translate(19em) rotate(-270deg);
}
.deg300.ng-enter-active {
transform: rotate(300deg) translate(19em) rotate(-300deg);
}
.deg330.ng-enter-active {
transform: rotate(330deg) translate(19em) rotate(-330deg);
}
There's a couple of errors to look at 1st, To get a value of a class from an angular item, it's ng-class you should be looking for:
<div ng-repeat="it in model.imageTones" ng-class="it.CPosition" ng-if="!it.hidden" >
<img ng-src="http://www.absolutepitchstudy.com/animalgame/content/images/{{it.Image.ImageFileName}}" />
</div>
Then in you style sheet there seems to be something wrong with the CSS, so I removed a class that wasn't being used:
.deg60{
transform: rotate(60deg) translate(19em) rotate(-60deg);
}
Although to hide stuff you may want that back.
The updated plunk with the work so far is at:
plunky
Now it's being rendered in the right place, you can use $timeout, ng-click or someother method to alter the class definition in your model. The position of the graphic should automatically update.
What method were you going to use?
I am setting up a diamond div using CSS. But the diamond div is going out or the parent div.
Is there any way to calculate the diagonal length of the diamond div so I can set the width to the parent width?
HTML
<div class="col-md-2">
<div class="ab-iconbar text-center">
<div class="ab-baric">
<img src="images/icons/baby63.svg" alt="baby">
</div>
<div class="ab-icobox">
<h3>19<small>to</small>34</h3>
</div>
</div>
</div>
SCSS
.ab-iconbar {
#extend .ab-bg-yellow;
.ab-baric {
margin: 0 auto;
display: block;
width: 100%;
#extend .ab-bg-gsea; //bg color
text-align: center;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
img, .fa {
-webkit-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
-o-transform: rotate(-45deg);
transform: rotate(-45deg);
}
}
.ab-icobox {
#extend .ab-c-midnit;
padding: 10px;
}
}
JS
var ab_icbar_w = $('.ab-iconbar').width();
var ab_baric_w = $('.ab-baric').css('width', ab_icbar_w);
$('.ab-baric').css('height', ab_baric_w);
Current Output
You could use the Pythagorean theorem.
So
var diagLength = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2))
Pythagorus theorem would give you the diagonal length .
Get the height and width from jQuery,and use pythagorus theorem.
I had a button that rotated text along the Y axis , giving it a mirrored look. This no longer works for some reason because the button has been placed on the child (popup) and the text to be mirrored is on the parent.
Is there a javascript function i could use to rotate the text on the parent when a button is clicked / rotate it back when its clicked again. (preferably a toggle switch)
This is what I originally had when it was only one the parent page:
HTML link :
<li><a class="button small icon-text-height flipx" href="#" onclick="return false;"></a></li>
The CSS for the div with the text:
article .teleprompter
{
padding: 300px 50px 1000px 100px;
font-size: 30px !important;
line-height: 86px;
z-index: 1;
background-color: #141414;
-webkit-transform: translate3d(0,0,0);
-moz-transform: translate3d(0,0,0);
-ms-transform: translate3d(0,0,0);
-o-transform: translate3d(0,0,0);
transform: translate3d(0,0,0);
}
The CSS for the flipx part:
article .teleprompter.flipx
{
-webkit-transform: rotateY(180deg);
-moz-transform: rotateY(180deg);
-o-transform: rotateY(180deg);
-ms-transform: rotateY(180deg);
z-index: 1;
pointer-events: none;
padding: 300px 50px 1000px 100px !important;
}
JS I Think should work:
<script>
function flipTXT(color)
{
if (parent_window && !parent_window.closed) {
parent_window.document.getElementById("teleprompter").style['-webkit-transform'] = rotateY(180deg);
}
}
</script>
I think one of the two solutions seen in the code at Bin below may work for you:
http://jsbin.com/buqexusamuda/1/
HTML
<p>Card: Flip</p>
<div class="card" href="#">Hello</div>
<p>Card 2: Mirror</p>
<div class="card card2" href="#">Hello</div>
CSS
.card, .card2 {
position: relative;
animation: all 2.5s;
perspective: 1000;
transition: 0.6s;
transform-style: preserve-3d;
width: 90px;
height: 32px;
text-align: center;
line-height: 32px;
z-index: 1;
background-color: #ccc;
color: #666;
}
.card2 { transform-origin: right center; }
.card.flip { transform: rotateY(180deg); }
SCRIPT
jQuery(".card").click(function(){
$(this).toggleClass("flip");
});
The simplest solution would be to use jQuery to add/remove the classes. If you can include jQuery, then you can do something along these lines:
<script>
$(document).ready(function(){
//Since the text is on the parent, you need to access it.
var parentWindow = window.opener;
//This gets the parent's DOM so you can grab the text from the parent window.
var parentDom = parentWindow.document;
//This grabs the text you want to transform.
var targetText = parentDom.getElementsByClassName("teleprompter");
//This toggles the class
$(".button").on('click', function(){
$(targetText).toggleClass("flipx");
});
});
</script>
I used a combination of jQuery and regular javascript so you don't have to roll your own code to add/remove and check for classes.
Here's the code to include jQuery in your page in case you don't have it handy:
This one will work with older non-HTML 5 compliant browsers and modern browsers.
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
This one will only work with more modern browsers:
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Obviously one can't actually comment out the code, but, how, from JavaScript, do I make the following piece of CSS seems as if it were commented out? How do I uncomment it after?
.box:hover div.innercontent {
-webkit-transform: perspective(3000) translateZ(200px);
-moz-transform: scale(1.1);
-moz-perspective: 3000px;
transform: perspective(3000) translateZ(200px) ;
z-index: 90;
box-shadow:0 0 35px 5px black;
}
.box:hover div.innerlabel {
-webkit-transform: perspective(500) rotateX(5deg) translateZ(60px);
-moz-transform: rotateX(5deg) scale(1.1);
-moz-perspective: 500px;
transform: perspective(500) rotateX(5deg) translateZ(60px);
box-shadow:0 0 20px 8px white;
z-index: 100;
}
.box:hover div.labelwrapper {
z-index: 100;
}
Thanks
Remove the css class from the elements.
You can either use jQuery or this other stackoverflow question to accomplish this.
If the CSS makes up the entirity of a CSS file, you can set the disabled attribute on the <link/> element to disable all the styles defined in it. This is probably the easiest way, especially when dealing with :hover styles.
I'll show you how to do one and you can use the same technique for the others:
$(".innercontent")
.addClass('.innercontent-dummy')
.removeClass('.innercontent');
Then to restore
$(".innercontent-dummy")
.addClass('.innercontent')
.removeClass('.innercontent-dummy');
The 'dummy' class doesn't have to have any formatting; you just need it as a placeholder to find the element if you want to restore the original class.
I use a modifier class, like "active," to toggle the on-off state of elements. Bootstrap does this with menus and other elements as well.
For example:
CSS:
.box.active:hover div.innercontent {
-webkit-transform: perspective(3000) translateZ(200px);
-moz-transform: scale(1.1);
-moz-perspective: 3000px;
transform: perspective(3000) translateZ(200px) ;
z-index: 90;
box-shadow:0 0 35px 5px black;
}
.box.active:hover div.innerlabel {
-webkit-transform: perspective(500) rotateX(5deg) translateZ(60px);
-moz-transform: rotateX(5deg) scale(1.1);
-moz-perspective: 500px;
transform: perspective(500) rotateX(5deg) translateZ(60px);
box-shadow:0 0 20px 8px white;
z-index: 100;
}
.box.active:hover div.labelwrapper {
z-index: 100;
}
JavaScript:
$('.box').toggleClass('active');