Coin flip using js | XM Community
Skip to main content

I want respondents to observe the outcome of a virtual coin flip. For example, I have two images pic_head and pic_tail, and I want the images to flip over a couple of times before it lands on the outcome. The coin flip starts automatically when the page loads and should stop after 2 or 3 secs.

Does anyone have a related js code for this that I could refer to? 

 

Thanks!

This is a unique idea, unfortunately I can’t assist with the css code to do this though.  An alternative might be is if you can create an animated image or video & insert that into the survey instead, have two versions and then randomise which is shown.  This would need you to have an animation of a coin flip, rather than a static image.  You might be able to find something like this online though.


I found a codepen by user Siva that I was able to put into Qualtrics.

To give it a try, first create the Embedded Data fields of "headsCount" and "tailsCount" and put them at the top of the Survey Flow.

Then create a Text/Graphic question and use the Rich Content Editor's HTML/Source view "<>" to update the question text with the below:

<div class="container">
<h2>Flip this coin!</h2>

<div id="coin">
<div id="heads" class="heads">&nbsp;</div>

<div id="tails" class="tails">&nbsp;</div>
</div>
<button id="flip">Flip Coin</button>

<p>Heads: <span id="headsCount">0</span> Tails: <span id="tailsCount">0</span></p>

<p><span id="status">&nbsp;</span></p>
</div>

Next, add the below to the question's JavaScript in the OnReady section:

const coin = document.querySelector('#coin');
const button = document.querySelector('#flip');
const status = document.querySelector('#status');
const heads = document.querySelector('#headsCount');
const tails = document.querySelector('#tailsCount');

let headsCount = 0;
let tailsCount = 0;


function deferFn(callback, ms) {
setTimeout(callback, ms);
}

function processResult(result) {
if (result === 'heads') {
headsCount++;
heads.innerText = headsCount;
Qualtrics.SurveyEngine.setEmbeddedData("headsCount",headsCount);
} else {
tailsCount++;
tails.innerText = tailsCount;
Qualtrics.SurveyEngine.setEmbeddedData("tailsCount",tailsCount);
}
status.innerText = result.toUpperCase();
}

function flipCoin() {
coin.setAttribute('class', '');
const random = Math.random();
const result = random < 0.5 ? 'heads' : 'tails';
deferFn(function() {
coin.setAttribute('class', 'animate-' + result);
deferFn(processResult.bind(null, result), 2900);
}, 100);
}

button.addEventListener('click', flipCoin);

Finally, add the below CSS to the Style section of the Look & Feel, updating the heads/tails image URLs with your own:

h2 {
margin: .25rem;
}

div.container {
margin: auto;
display: flex;
flex-direction: column;
align-items: center;
}

#flip {
padding: 1rem;
background-color: skyblue;
}

#coin {
position: relative;
width: 15rem;
height: 15rem;
margin: 2rem 0rem;
transform-style: preserve-3d;

}

#coin div {
width: 100%;
height: 100%;
border: 2px solid black;
border-radius: 50%;
backface-visibility: hidden;
background-size: contain;
position: absolute;
}

.heads {
background-image: url("https://en.numista.com/catalogue/photos/inde/2311-original.jpg");
}

.animate-heads {
animation: flipHeads 3s;
animation-fill-mode: forwards;
}

@keyframes flipHeads {
from {
transform: rotateY(0deg);
}
to {
transform: rotateY(1800deg);
}
}

.tails {
background-image: url("https://en.numista.com/catalogue/photos/inde/3165-original.jpg");
transform: rotateY(-180deg);
}

.animate-tails {
animation: flipTails 3s;
animation-fill-mode: forwards;
}

@keyframes flipTails {
from {
transform: rotateY(0deg);
}
to {
transform: rotateY(1620deg);
}
}

 


Thanks @ScottG and @Tom_1842 for the super helpful suggestions! 

I tried @Tom_1842’s code and it works perfectly! Thanks for the detailed code. 

 

Thanks again! 


Leave a Reply