scratch animation ok

This commit is contained in:
Jérémy Munsch 2023-12-20 17:03:15 +01:00
parent 3fabe83923
commit 3a7d35f701
No known key found for this signature in database
GPG key ID: 18361AF3BFEC0FEC
8 changed files with 183 additions and 69 deletions

View file

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 149 KiB

View file

@ -6,15 +6,16 @@
font-family: 'Montauk Pro', serif;
text-align: center;
text-transform: uppercase;
@include font-size(3rem);
}
h2,h3,h4,h5,h6 {
display: block;
color: $color-primary;
text-transform: uppercase;
text-decoration: #{$color-tertiary} solid underline;
text-decoration-thickness: 0.2rem;
text-transform: uppercase;
}
hr {

View file

@ -1,6 +1,12 @@
@import "./../partials/spin_wheel";
.won-page {
#scratch-wrapper canvas {
position: absolute;
z-index: 1;
left: 0;
}
#wheel-wrapper {
position: relative;
width: 16rem;

View file

@ -59,6 +59,14 @@ return [
'inCanvas' => true,
'fit' => true,
'format' => 'webp'
],
'scratch_prize' => [
'height' => 300,
'width' => 450,
'resize' => true,
'inCanvas' => true,
'keepRatio' => true,
'format' => 'webp'
]
]
];

View file

@ -1,12 +1,14 @@
import { SCRATCH_TYPE, ScratchCard } from "scratchcard-js";
import grattageUrl from "./../../assets/images/animations/grattage.png";
document.addEventListener("DOMContentLoaded", function () {
if (!document.querySelector("main.won-page")) {
return;
}
const wheelWrapper = document.getElementById("wheel-wrapper"),
spinWheelInner = wheelWrapper?.querySelector(".wheel-inner") as HTMLElement | null | undefined,
spinWheelBtnList = wheelWrapper?.querySelectorAll(".wheel-spin") as NodeListOf<HTMLElement> | undefined,
animationSection = document.getElementById("spin-animation"),
const scratchWrapper = document.getElementById("scratch-wrapper"),
scratchPicture = document.getElementById("scratch-picture") as HTMLPictureElement|null,
animationSection = document.getElementById("scratch-animation"),
prizeSection = document.getElementById("prize-section"),
discountSection = document.getElementById("discount-section"),
winningProofSection = document.getElementById("winning-proof-section");
@ -29,73 +31,34 @@ document.addEventListener("DOMContentLoaded", function () {
};
if (!animationSection) {
throw Error("section#spin-animation missing");
throw Error("section#scratch-animation missing");
}
if (wheelWrapper && spinWheelInner && spinWheelBtnList && spinWheelBtnList.length) {
let clicks: number = 0;
// * Set default degree (360*5) soit 5 tours
const degree: number = (360 * 5),
wheelPartsDeg: number = 360 / spinWheelInner.children.length,
thisWinAngle: number = (Number.parseInt(
String(wheelWrapper.dataset["winChild"])
// On s'aligne sur la tranche on on ajoute entre 10% et 90% d'une part
)) * wheelPartsDeg - 45 + (wheelPartsDeg * (Math.random() * (0.9 - 0.1) + 0.1));
let timeout: NodeJS.Timeout | null = null;
const spinTheWheel = () => {
// * Add 1 every click
/**
* Multiply the degree by number of clicks
* generate random number between 1 - 85,
* then add to the new degree
*/
const newDegree = degree * ++clicks;
const totalDegree = newDegree + thisWinAngle;
/**
* Let's make the spin btn to tilt every
* time the edge of the section hits
* the indicator
*/
spinWheelInner.style["transform"] = `rotate(${totalDegree}deg)`;
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(toggleAnimationPhase, 7000);
};
/** ! Même Algo que sur GGW legacy */
spinWheelBtnList.forEach((spinBtn) => {
spinBtn.addEventListener("click", spinTheWheel);
spinBtn.addEventListener("keydown", (kbdEvt: KeyboardEvent) => {
if (
kbdEvt.key == " " ||
kbdEvt.code == "Space" ||
kbdEvt.keyCode == 32 ||
kbdEvt.key == "Enter" ||
kbdEvt.code == "Enter" ||
kbdEvt.keyCode == 13
) {
spinBtn.classList.add("active");
spinTheWheel();
kbdEvt.preventDefault();
}
if (scratchWrapper && scratchPicture) {
scratchPicture.addEventListener("load", () => {
const sc = new ScratchCard(scratchWrapper, {
scratchType: SCRATCH_TYPE.LINE,
containerWidth: scratchWrapper.offsetWidth,
containerHeight: scratchWrapper.offsetHeight,
imageForwardSrc: grattageUrl,
imageBackgroundSrc: "",
htmlBackground: "",
clearZoneRadius: 50,
nPoints: 30,
pointSize: 8,
percentToFinish: 65,
callback: function () {
toggleAnimationPhase();
},
brushSrc: "",
enabledPercentUpdate: true
});
spinBtn.addEventListener("keyup", (kbdEvt: KeyboardEvent) => {
if (
kbdEvt.key == " " ||
kbdEvt.code == "Space" ||
kbdEvt.keyCode == 32 ||
kbdEvt.key == "Enter" ||
kbdEvt.code == "Enter" ||
kbdEvt.keyCode == 13
) {
spinBtn.classList.remove("active");
kbdEvt.preventDefault();
}
sc.init().catch((e) => {
console.error(e);
toggleAnimationPhase();
});
});
scratchPicture.setAttribute("src", String(scratchPicture.dataset["src"]));
} else {
toggleAnimationPhase();
}

View file

@ -0,0 +1,103 @@
document.addEventListener("DOMContentLoaded", function () {
if (!document.querySelector("main.won-page")) {
return;
}
const wheelWrapper = document.getElementById("wheel-wrapper"),
spinWheelInner = wheelWrapper?.querySelector(".wheel-inner") as HTMLElement | null | undefined,
spinWheelBtnList = wheelWrapper?.querySelectorAll(".wheel-spin") as NodeListOf<HTMLElement> | undefined,
animationSection = document.getElementById("spin-animation"),
prizeSection = document.getElementById("prize-section"),
discountSection = document.getElementById("discount-section"),
winningProofSection = document.getElementById("winning-proof-section");
/** Hide animation and show win sections */
const toggleAnimationPhase = () => {
if (animationSection) {
animationSection.classList.add("d-none");
}
if (prizeSection) {
prizeSection.classList.remove("d-none");
}else if (discountSection) {
discountSection.classList.remove("d-none");
} else {
throw new Error("No section to toggle");
}
if (winningProofSection) {
winningProofSection.classList.remove("d-none");
}
};
if (!animationSection) {
throw Error("section#spin-animation missing");
}
if (wheelWrapper && spinWheelInner && spinWheelBtnList && spinWheelBtnList.length) {
let clicks: number = 0;
// * Set default degree (360*5) soit 5 tours
const degree: number = (360 * 5),
wheelPartsDeg: number = 360 / spinWheelInner.children.length,
thisWinAngle: number = (Number.parseInt(
String(wheelWrapper.dataset["winChild"])
// On s'aligne sur la tranche on on ajoute entre 10% et 90% d'une part
)) * wheelPartsDeg - 45 + (wheelPartsDeg * (Math.random() * (0.9 - 0.1) + 0.1));
let timeout: NodeJS.Timeout | null = null;
const spinTheWheel = () => {
// * Add 1 every click
/**
* Multiply the degree by number of clicks
* generate random number between 1 - 85,
* then add to the new degree
*/
const newDegree = degree * ++clicks;
const totalDegree = newDegree + thisWinAngle;
/**
* Let's make the spin btn to tilt every
* time the edge of the section hits
* the indicator
*/
spinWheelInner.style["transform"] = `rotate(${totalDegree}deg)`;
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(toggleAnimationPhase, 7000);
};
/** ! Même Algo que sur GGW legacy */
spinWheelBtnList.forEach((spinBtn) => {
spinBtn.addEventListener("click", spinTheWheel);
spinBtn.addEventListener("keydown", (kbdEvt: KeyboardEvent) => {
if (
kbdEvt.key == " " ||
kbdEvt.code == "Space" ||
kbdEvt.keyCode == 32 ||
kbdEvt.key == "Enter" ||
kbdEvt.code == "Enter" ||
kbdEvt.keyCode == 13
) {
spinBtn.classList.add("active");
spinTheWheel();
kbdEvt.preventDefault();
}
});
spinBtn.addEventListener("keyup", (kbdEvt: KeyboardEvent) => {
if (
kbdEvt.key == " " ||
kbdEvt.code == "Space" ||
kbdEvt.keyCode == 32 ||
kbdEvt.key == "Enter" ||
kbdEvt.code == "Enter" ||
kbdEvt.keyCode == 13
) {
spinBtn.classList.remove("active");
kbdEvt.preventDefault();
}
});
});
} else {
toggleAnimationPhase();
}
});

View file

@ -0,0 +1,26 @@
<section class="container pb-5 pt-5 text-center" id="{{ $sectionId }}">
<div class="row mb-3 mt-5">
<div class="col">
<h1 class="text-primary text-uppercase fw-bold">{{ __('Lancez la roue et découvrez votre gain') }}</h1>
</div>
</div>
<div class="row mb-5">
<div class="col">
{{-- blade-formatter-enable --}}
<div class="d-inline-block position-relative" id="scratch-wrapper" aria-describedby="scratch-helper">
@if ($winDiscount)
<img class="img-fluid" id="scratch-picture" data-src="{{ asset(resize($objectWon->picture, 'scratch_prize')) }}"
src="#"
title="{{ __('Votre bon de réduction de :value', ['value' => number_format($objectWon->face_value / 100, 2, ',')]) }}"
alt="{{ __('Votre bon de réduction de :value', ['value' => number_format($objectWon->face_value / 100, 2, ',')]) }}">
@else
<img class="img-fluid" id="scratch-picture" data-src="{{ asset(resize($objectWon->picture, 'scratch_prize')) }}"
src="#" title="{{ $objectWon->picture_title }}" alt="{{ $objectWon->picture_alt }}">
@endif
</div>
<div class="mt-4">
<span class="fs-2" id="scratch-helper">{{ __('Grattez la carte pour connaitre votre gain.') }}</span>
</div>
</div>
</div>
</section>

View file

@ -6,12 +6,19 @@
@section('main-class', 'won-page g-0')
@section('content')
{{-- SCRATCH CARD --}}
@include('theme::pages.participation.parts.animation-scratch', [
'sectionId' => 'scratch-animation',
'winDiscount' => !empty($prizeModel) ? false : true,
'objectWon' => $prizeModel ?? ($discount ?? null),
])
{{-- SPIN WHEEL --}}
@include('theme::pages.participation.parts.animation', [
{{-- @include('theme::pages.participation.parts.animation', [
'sectionId' => 'spin-animation',
'winDiscount' => !empty($prizeModel) ? false : true,
'prizeModel' => $prizeModel ?? null,
])
]) --}}
@if (!empty($prizeModel))
{{-- LOT --}}