841 lines
36 KiB
PHP
841 lines
36 KiB
PHP
<link rel="stylesheet" href="{{asset('frontend/css/game.css?version=1.5')}}" />
|
|
<div class="row chart_containter">
|
|
<div class="background-left" style="display: none;">
|
|
<img src="{{ asset('frontend/imgs/background_left.png') }}" />
|
|
</div>
|
|
<div class="col-lg-12 col-md-12 ribbon">
|
|
<div class="wrap">
|
|
<span class="ribbon6" id="game_rule" data-toggle="modal" data-target="#ruleModal">Thể lệ tham dự</span>
|
|
</div>
|
|
@if(Session::has('success'))
|
|
<div class="alert alert-success">
|
|
{{ Session::get('success') }}
|
|
@php
|
|
Session::forget('success');
|
|
@endphp
|
|
</div>
|
|
@endif
|
|
@if(Session::has('error'))
|
|
<div class="alert alert-danger">
|
|
{{ Session::get('error') }}
|
|
@php
|
|
Session::forget('error');
|
|
@endphp
|
|
</div>
|
|
@endif
|
|
@if(Session::has('errors'))
|
|
<div class="alert alert-danger">
|
|
{{ 'Có lỗi xảy ra (' . implode(', ', $errors->all(':message')) . ')'}}
|
|
@php
|
|
Session::forget('errors');
|
|
@endphp
|
|
</div>
|
|
@endif
|
|
@if (!$is_login)
|
|
<div class="alert alert-danger text-center" style="width: 100%; margin: auto;">
|
|
Vui lòng <a class="btn btn-danger custom_btn" href="{{ route('login') }}">Nhập thông tin</a> để có thể
|
|
quay số
|
|
trúng giải
|
|
</div>
|
|
@endif
|
|
@if ($spined == 1)
|
|
<div class="alert alert-danger text-center prize_alert">
|
|
Bạn chỉ được phép quay 1 lần,
|
|
giải thưởng gần nhất <b>
|
|
<h2>{{ $lasted_prize_name ?? '' }}</h2>
|
|
</b>
|
|
</div>
|
|
@endif
|
|
<div class="custom_title text-center">VÒNG QUAY MAY MẮN</div>
|
|
<div id="chart"></div>
|
|
</div>
|
|
<div class="col-lg-12 col-md-12" style="display: none;">
|
|
<!-- hien thi giai thuong -->
|
|
<div class="custom_subtitle">DANH SÁCH GIẢI THƯỞNG</div>
|
|
<div class="grid-container">
|
|
@foreach ($game_data as $game_item)
|
|
<div class="grid-item ribbon_item">
|
|
<div class="wrap_item">
|
|
<span class="ribbon_minitem">{{ $game_item['label'] ?? '' }}</span>
|
|
</div>
|
|
<!-- <img src="{{ asset('images/' . $game_item['image']) }}" alt="{{ $game_item['detail'] ?? '' }}"> -->
|
|
<div class="overlay">
|
|
<h3 class="title">{{ $game_item['detail'] ?? '' }}</h3>
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
<!-- ket thuc hien thị giai thuong -->
|
|
</div>
|
|
</div>
|
|
<section class="contact-info-section" style="display: none;">
|
|
|
|
<div class="contact-info-container">
|
|
<div class="contact-item">
|
|
<div class="icon-circle">
|
|
<i class="fas fa-map-marker-alt"></i>
|
|
</div>
|
|
<p>397 Nguyễn Văn Cừ nối dài, P An Bình, Q.Ninh Kiều, TP Cần Thơ</p>
|
|
</div>
|
|
<div class="contact-item">
|
|
<div class="icon-circle">
|
|
<i class="fas fa-calendar-alt"></i>
|
|
</div>
|
|
<p>Thứ 2 - Chủ Nhật: 07h00 - 16h30</p>
|
|
<p>Cấp Cứu & Nội Viện: 24/7</p>
|
|
</div>
|
|
<div class="contact-item">
|
|
<div class="icon-circle">
|
|
<i class="fas fa-phone"></i>
|
|
</div>
|
|
<p class="highlight-text">18001115</p>
|
|
<p>Tổng đài liên hệ</p>
|
|
</div>
|
|
<div class="contact-item">
|
|
<div class="icon-circle">
|
|
<i class="fas fa-envelope"></i>
|
|
</div>
|
|
<p class="highlight-text">cskh@dotquy.vn</p>
|
|
<p>Thanh toán & khiếu nại</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
@include('frontend.game.luckywheel_popup')
|
|
@include('frontend.game.customprize_popup')
|
|
@include('frontend.game.rule')
|
|
<style>
|
|
.custom-navbar {
|
|
background-color: #0000006e;
|
|
}
|
|
|
|
.za-chat .chat-wrapper .box__header {
|
|
padding: 24px;
|
|
background-color: #ff0000;
|
|
}
|
|
|
|
.page_container {
|
|
font-family: sans-serif;
|
|
}
|
|
|
|
.page_container .fas {
|
|
background-color: #695aa6;
|
|
color: #fff;
|
|
padding: 0.3rem;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
.slogan {
|
|
border: none;
|
|
visibility: visible;
|
|
bottom: 54px;
|
|
right: 52px;
|
|
position: fixed;
|
|
width: auto;
|
|
height: auto;
|
|
z-index: 1000;
|
|
font-weight: 800;
|
|
background-color: #ff0000;
|
|
padding: 1rem 4rem 1rem 1rem;
|
|
color: #fff;
|
|
border-radius: 1rem;
|
|
box-shadow: 1px 1px 20px #000;
|
|
/* Áp dụng animation */
|
|
animation-name: blink;
|
|
/* Tên của animation (đã định nghĩa ở trên) */
|
|
animation-duration: 1.5s;
|
|
/* Thời gian hoàn thành một chu kỳ animation (1.5 giây) */
|
|
animation-iteration-count: infinite;
|
|
/* Số lần lặp lại: infinite (vô hạn) */
|
|
animation-timing-function: ease-in-out;
|
|
/* Kiểu tốc độ: bắt đầu và kết thúc chậm, ở giữa nhanh */
|
|
}
|
|
|
|
@keyframes blink {
|
|
0% {
|
|
opacity: 1;
|
|
}
|
|
|
|
/* Bắt đầu: Hoàn toàn hiển thị */
|
|
50% {
|
|
opacity: 0.6;
|
|
}
|
|
|
|
/* Giữa: Hoàn toàn trong suốt (ẩn) */
|
|
100% {
|
|
opacity: 1;
|
|
}
|
|
|
|
/* Kết thúc: Hoàn toàn hiển thị trở lại */
|
|
}
|
|
|
|
.contact-info-section {
|
|
width: 100%;
|
|
background-color: #bd021b;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
|
padding: 1rem;
|
|
margin: 1rem;
|
|
position: absolute;
|
|
bottom: -4rem;
|
|
}
|
|
|
|
.contact-info-container {
|
|
display: flex;
|
|
justify-content: space-around;
|
|
/* Phân bố đều các item */
|
|
align-items: flex-start;
|
|
/* Căn trên các item */
|
|
flex-wrap: wrap;
|
|
/* Cho phép xuống dòng trên màn hình nhỏ */
|
|
gap: 20px;
|
|
/* Khoảng cách giữa các item */
|
|
padding: 0 20px;
|
|
/* Padding hai bên */
|
|
}
|
|
|
|
.contact-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
/* Căn giữa nội dung */
|
|
text-align: center;
|
|
/* Căn giữa chữ */
|
|
flex: 1;
|
|
/* Cho phép các item chiếm không gian bằng nhau */
|
|
min-width: 200px;
|
|
/* Đảm bảo mỗi item có chiều rộng tối thiểu */
|
|
padding: 10px;
|
|
}
|
|
|
|
.icon-circle {
|
|
width: 60px;
|
|
/* Kích thước icon circle */
|
|
height: 60px;
|
|
background-color: #ffffff54;
|
|
/* Màu đỏ cam như trong ảnh */
|
|
border-radius: 50%;
|
|
/* Làm tròn thành hình tròn */
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
margin-bottom: 15px;
|
|
/* Khoảng cách với chữ */
|
|
}
|
|
|
|
.icon-circle i {
|
|
color: #ffffff;
|
|
/* Màu icon trắng */
|
|
font-size: 28px;
|
|
/* Kích thước icon */
|
|
}
|
|
|
|
.contact-item p {
|
|
margin: 3px 0;
|
|
color: #ffffff;
|
|
line-height: 1.4;
|
|
font-size: 1.1rem;
|
|
}
|
|
|
|
.contact-item .highlight-text {
|
|
color: #fff;
|
|
/* Màu đỏ cam cho các text nổi bật */
|
|
font-weight: bold;
|
|
/* In đậm chữ */
|
|
font-size: 16px;
|
|
}
|
|
|
|
/* Responsive adjustments */
|
|
@media (max-width: 768px) {
|
|
.contact-info-container {
|
|
flex-direction: column;
|
|
/* Xếp chồng các item trên màn hình nhỏ */
|
|
align-items: center;
|
|
}
|
|
|
|
.contact-item {
|
|
margin-bottom: 25px;
|
|
/* Khoảng cách giữa các item khi xếp chồng */
|
|
width: 100%;
|
|
/* Chiếm toàn bộ chiều rộng */
|
|
max-width: 300px;
|
|
/* Giới hạn chiều rộng cho item riêng lẻ */
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<script src="{{asset('frontend/js/game.js')}}"></script>
|
|
<script>
|
|
$('#game_rule').on('click', function () {
|
|
$('#gamerule').html('');
|
|
$.ajaxSetup({
|
|
headers: {
|
|
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
|
|
}
|
|
});
|
|
var url = "{{route('game/rule')}}";
|
|
$.ajax({
|
|
// dataType: 'json',
|
|
url: url,
|
|
type: 'GET',
|
|
contentType: false,
|
|
processData: false,
|
|
success: function (result) {
|
|
$('#gamerule').html(result);
|
|
}
|
|
});
|
|
});
|
|
let is_login = "{{ $is_login }}";
|
|
let spined = "{{ $spined }}";
|
|
const screenWidth = window.screen.width;
|
|
if (screenWidth <= 991) {
|
|
var padding = { top: 40, right: 20, bottom: 40, left: 20 },
|
|
w = 350 - padding.left - padding.right,
|
|
h = 350 - padding.top - padding.bottom,
|
|
r = Math.min(w, h) / 2,
|
|
rotation = 0,
|
|
oldrotation = 0,
|
|
picked = 100000,
|
|
oldpick = [],
|
|
color = d3.scale.category20();
|
|
} else {
|
|
var padding = { top: 80, right: 80, bottom: 80, left: 80 },
|
|
w = 600 - padding.left - padding.right,
|
|
h = 600 - padding.top - padding.bottom,
|
|
r = Math.min(w, h) / 2,
|
|
rotation = 0,
|
|
oldrotation = 0,
|
|
picked = 100000,
|
|
oldpick = [],
|
|
color = d3.scale.category20();
|
|
}
|
|
|
|
let game_data = "{{json_encode($game_data)}}";
|
|
var data = JSON.parse(game_data.replace(/"/g, '"'));
|
|
var svg = d3.select('#chart')
|
|
.append("svg")
|
|
.data([data])
|
|
.attr("width", w + padding.left + padding.right)
|
|
.attr("height", h + padding.top + padding.bottom);
|
|
|
|
var container = svg.append("g")
|
|
.attr("class", "chartholder")
|
|
.attr("transform", "translate(" + (w / 2 + padding.left) + "," + (h / 2 + padding.top) + ")");
|
|
|
|
const mainCircleRadius = Math.min(w, h) / 2 - 48; // Bán kính của đường tròn chính
|
|
const dotRadius = 10;
|
|
const numberOfDots = 20;
|
|
const dotDistanceFromCenterFactor = 1.6; // Tăng hệ số để đẩy xa hơn
|
|
const defaultColor = "white"; // Màu mặc định khi đứng yên
|
|
|
|
// Bán kính để định vị các chấm
|
|
const dotPositionRadius = mainCircleRadius * dotDistanceFromCenterFactor;
|
|
|
|
// Hình tròn chính (chỉ có đường viền)
|
|
let isSpinning = false; // Biến theo dõi trạng thái quay
|
|
const animationDuration = 2; // Điều chỉnh tổng thời gian của một chu kỳ màu
|
|
const colors = ["#ff0000", "#ff0000", "#ff0000", "#ff0000", "#ff0000", "#ff0000"];
|
|
const numberOfColors = colors.length;
|
|
|
|
|
|
|
|
// Tạo các chấm đổi màu dọc theo đường viền và thiết lập animation delay
|
|
if (screenWidth <= 991) {
|
|
const dotPositionRadius = mainCircleRadius * 1.8;
|
|
let numberOfDots_min = numberOfDots;
|
|
container.append("circle")
|
|
.attr("r", mainCircleRadius)
|
|
.style({
|
|
"fill": "none",
|
|
"stroke": "gray",
|
|
"stroke-width": "2rem"
|
|
});
|
|
for (let i = 0; i < numberOfDots_min; i++) {
|
|
const angle = (2 * Math.PI / numberOfDots) * i;
|
|
const x = dotPositionRadius * Math.cos(angle);
|
|
const y = dotPositionRadius * Math.sin(angle);
|
|
const animationDelay = (i / numberOfDots) * (animationDuration / numberOfColors); // Điều chỉnh độ trễ
|
|
|
|
container.append("circle")
|
|
.attr("cx", x)
|
|
.attr("cy", y)
|
|
.attr("r", dotRadius / 2)
|
|
.attr("class", "animated-dot") // Thêm class mặc định
|
|
.style("fill", colors[i % 2])
|
|
.style("animation-delay", `${animationDelay}s`); // Thiết lập animation-delay ngay từ đầu
|
|
}
|
|
} else {
|
|
const dotPositionRadius = mainCircleRadius * dotDistanceFromCenterFactor;
|
|
container.append("circle")
|
|
.attr("r", mainCircleRadius)
|
|
.style({
|
|
"fill": "none",
|
|
"stroke": "gray",
|
|
"stroke-width": "2rem"
|
|
});
|
|
for (let i = 0; i < numberOfDots; i++) {
|
|
const angle = (2 * Math.PI / numberOfDots) * i;
|
|
const x = dotPositionRadius * Math.cos(angle);
|
|
const y = dotPositionRadius * Math.sin(angle);
|
|
const animationDelay = (i / numberOfDots) * (animationDuration / numberOfColors); // Điều chỉnh độ trễ
|
|
|
|
container.append("circle")
|
|
.attr("cx", x)
|
|
.attr("cy", y)
|
|
.attr("r", dotRadius)
|
|
.attr("class", "animated-dot") // Thêm class mặc định
|
|
.style("fill", colors[i % 2])
|
|
.style("animation-delay", `${animationDelay}s`)
|
|
.style("filter", "drop-shadow(0 0 5px #ad031a)"); // Thiết lập animation-delay ngay từ đầu
|
|
}
|
|
}
|
|
|
|
const style = document.createElement('style');
|
|
style.textContent = `
|
|
.animated-dot.spinning { /* Chỉ áp dụng animation khi có class 'spinning' */
|
|
animation: sequential-blink ${animationDuration}s linear infinite; /* Điều chỉnh thời gian */
|
|
filter: drop-shadow(0 0 2px currentColor);
|
|
}
|
|
|
|
@keyframes sequential-blink {
|
|
${Array.from({ length: numberOfColors }, (_, index) => {
|
|
const percentage = (index / (numberOfColors - 1)) * 100;
|
|
return ` ${percentage}% { fill: ${colors[index]}; }`;
|
|
}).join('\n')}
|
|
100% { fill: ${colors[0]}; }
|
|
}
|
|
`;
|
|
document.head.appendChild(style);
|
|
// Thêm hình tròn làm border bên ngoài
|
|
if (screenWidth <= 991) {
|
|
svg.insert("circle", ":first-child")
|
|
.attr("cx", w / 2 + padding.left) // Tâm X của hình tròn
|
|
.attr("cy", h / 2 + padding.top) // Tâm Y của hình tròn
|
|
.attr("r", r + 3) // Bán kính của hình tròn (lớn hơn r một chút để làm border)
|
|
.style("fill", "none") // Không tô màu nền
|
|
.style("stroke", "#ff9800") // Màu của border hình tròn
|
|
.style("stroke-width", "1rem").style("filter", "drop-shadow(0 0 5px rgba(0, 0, 0, 0.5))");
|
|
svg.insert("circle", ":first-child")
|
|
.attr("cx", w / 2 + padding.left) // Tâm X của hình tròn
|
|
.attr("cy", h / 2 + padding.top) // Tâm Y của hình tròn
|
|
.attr("r", r + 1) // Bán kính của hình tròn (lớn hơn r một chút để làm border)
|
|
.style("fill", "none") // Không tô màu nền
|
|
.style("stroke", "red") // Màu của border hình tròn
|
|
.style("stroke-width", "3rem");
|
|
svg.insert("circle", ":first-child")
|
|
.attr("cx", w / 2 + padding.left) // Tâm X của hình tròn
|
|
.attr("cy", h / 2 + padding.top) // Tâm Y của hình tròn
|
|
.attr("r", r + 2) // Bán kính của hình tròn (lớn hơn r một chút để làm border)
|
|
.style("fill", "none") // Không tô màu nền
|
|
.style("stroke", "#ff9800") // Màu của border hình tròn
|
|
.style("stroke-width", "4rem").style("filter", "drop-shadow(0 0 3px rgba(30, 30, 30, 0.5))");
|
|
} else {
|
|
svg.insert("circle", ":first-child")
|
|
.attr("cx", w / 2 + padding.left) // Tâm X của hình tròn
|
|
.attr("cy", h / 2 + padding.top) // Tâm Y của hình tròn
|
|
.attr("r", r + 20) // Bán kính của hình tròn (lớn hơn r một chút để làm border)
|
|
.style("fill", "none") // Không tô màu nền
|
|
.style("stroke", "#ff9800") // Màu của border hình tròn
|
|
// .style("stroke", "#000")
|
|
.style("stroke-width", "1rem").style("filter", "drop-shadow(0 0 5px rgba(0, 0, 0, 0.5))");
|
|
svg.insert("circle", ":first-child")
|
|
.attr("cx", w / 2 + padding.left) // Tâm X của hình tròn
|
|
.attr("cy", h / 2 + padding.top) // Tâm Y của hình tròn
|
|
.attr("r", r - 18) // Bán kính của hình tròn (lớn hơn r một chút để làm border)
|
|
.style("fill", "none") // Không tô màu nền
|
|
.style("stroke", "red") // Màu của border hình tròn
|
|
.style("stroke-width", "7rem");
|
|
svg.insert("circle", ":first-child")
|
|
.attr("cx", w / 2 + padding.left) // Tâm X của hình tròn
|
|
.attr("cy", h / 2 + padding.top) // Tâm Y của hình tròn
|
|
.attr("r", r + 12) // Bán kính của hình tròn (lớn hơn r một chút để làm border)
|
|
.style("fill", "none") // Không tô màu nền
|
|
// .style("stroke", "#ff9800") // Màu của border hình tròn // Không tô màu nền
|
|
.style("stroke", "#ffeb3b")
|
|
.style("stroke-width", "8rem").style("filter", "drop-shadow(0 0 5px rgb(0, 0, 0))");
|
|
}
|
|
|
|
var vis = container
|
|
.append("g");
|
|
|
|
var pie = d3.layout.pie().sort(null).value(function (d) { return 1; });
|
|
// declare an arc generator function
|
|
var arc = d3.svg.arc().outerRadius(r + 30);
|
|
// select paths, use arc generator to draw
|
|
var arcs = vis.selectAll("g.slice")
|
|
.data(pie)
|
|
.enter()
|
|
.append("g")
|
|
.attr("class", "slice");
|
|
|
|
if (!is_login || spined == 1) {
|
|
var color = d3.scale.ordinal().range(['#eb9c13', '#a5af09', '#0ba97e', '#79c323', '#926c6c', '#c1341a', '#e12603', '#9d4e0a', '#eb9c13', '#a5af09', '#0ba97e', '#73e3a3']);
|
|
} else {
|
|
var color = d3.scale.ordinal().range(['#eb9c13', '#a5af09', '#0ba97e', '#79c323', '#926c6c', '#c1341a', '#e12603', '#9d4e0a', '#eb9c13', '#a5af09', '#0ba97e', '#73e3a3']);
|
|
}
|
|
|
|
arcs.append("path")
|
|
.attr('stroke', '#eb0a0a')
|
|
.attr('stroke-width', '5')
|
|
.attr("fill", function (d, i) { return color(i); })
|
|
.attr("d", function (d) { return arc(d); });
|
|
|
|
// Thêm một nhóm 'g' mới vào mỗi lát cắt để chứa cả ảnh và văn bản.
|
|
// Nhóm này sẽ được dịch chuyển đến tâm của lát cắt.
|
|
arcs.append("g")
|
|
.attr("class", "label-group")
|
|
.attr("transform", function (d) {
|
|
// arc.centroid(d) trả về tọa độ [x, y] của tâm (centroid) của lát cắt.
|
|
// Đây là vị trí lý tưởng để đặt nhãn.
|
|
d.innerRadius = 0;
|
|
d.outerRadius = r;
|
|
d.angle = (d.startAngle + d.endAngle) / 2;
|
|
return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")translate(" + (d.outerRadius - 50) + ")";
|
|
});
|
|
|
|
// Chọn tất cả các nhóm 'label-group' vừa tạo và thêm phần tử 'image' vào
|
|
if (screenWidth <= 991) {
|
|
d3.selectAll(".label-group")
|
|
.append("image")
|
|
.attr("xlink:href", function (d, i) {
|
|
// Lấy đường dẫn ảnh từ dữ liệu gốc của bạn.
|
|
// d.data thường chứa đối tượng dữ liệu gốc khi sử dụng d3.pie() hoặc d3.layout.pie().
|
|
return "{{ asset('images') }}/" + data[i].image; // Hoặc d.data.image nếu bạn đã cấu hình pie generator để lấy data
|
|
})
|
|
.attr("transform", "rotate(90)")
|
|
.attr("width", 50) // Đặt chiều rộng của ảnh (điều chỉnh theo nhu cầu)
|
|
.attr("height", 50) // Đặt chiều cao của ảnh (điều chỉnh theo nhu cầu)
|
|
.attr("x", -25) // Điều chỉnh vị trí x để căn giữa ảnh (nếu width là 40, thì x là -20)
|
|
.attr("y", -50); // Điều chỉnh vị trí y để đặt ảnh phía trên văn bản
|
|
// Chọn tất cả các nhóm 'label-group' và thêm phần tử 'text' vào
|
|
d3.selectAll(".label-group")
|
|
.append("text")
|
|
.attr("dy", "-3rem") // Điều chỉnh vị trí y của văn bản để nó nằm dưới ảnh
|
|
.attr("dx", "0rem") // Điều chỉnh vị trí y của văn bản để nó nằm dưới ảnh
|
|
.attr("text-anchor", "middle")
|
|
.attr("transform", "rotate(90)") // Căn giữa văn bản theo chiều ngang
|
|
.text(function (d, i) {
|
|
// Lấy nhãn từ dữ liệu gốc của bạn
|
|
return data[i].label; // Hoặc d.data.label
|
|
})
|
|
.style("fill", function (d, i) {
|
|
// Lấy màu của lát cắt hiện tại từ bảng màu của bạn
|
|
const sliceColor = color(i);
|
|
// Logic để chọn màu chữ tương phản với màu nền của lát cắt
|
|
// Bạn có thể cần điều chỉnh các giá trị màu hex cụ thể để phù hợp hơn
|
|
return '#fff';
|
|
})
|
|
.style("font-size", "1.2rem") // Điều chỉnh kích thước font để phù hợp với ảnh
|
|
.style("font-family", "Baloo Paaji");
|
|
} else {
|
|
d3.selectAll(".label-group")
|
|
.append("image")
|
|
.attr("xlink:href", function (d, i) {
|
|
// Lấy đường dẫn ảnh từ dữ liệu gốc của bạn.
|
|
// d.data thường chứa đối tượng dữ liệu gốc khi sử dụng d3.pie() hoặc d3.layout.pie().
|
|
return "{{ asset('images') }}/" + data[i].image; // Hoặc d.data.image nếu bạn đã cấu hình pie generator để lấy data
|
|
})
|
|
.attr("transform", "rotate(90)")
|
|
.attr("width", 80) // Đặt chiều rộng của ảnh (điều chỉnh theo nhu cầu)
|
|
.attr("height", 80) // Đặt chiều cao của ảnh (điều chỉnh theo nhu cầu)
|
|
.attr("x", -40) // Điều chỉnh vị trí x để căn giữa ảnh (nếu width là 40, thì x là -20)
|
|
.attr("y", -40); // Điều chỉnh vị trí y để đặt ảnh phía trên văn bản
|
|
// Chọn tất cả các nhóm 'label-group' và thêm phần tử 'text' vào
|
|
d3.selectAll(".label-group")
|
|
.append("text")
|
|
.attr("dy", "-3rem") // Điều chỉnh vị trí y của văn bản để nó nằm dưới ảnh
|
|
.attr("dx", "0rem") // Điều chỉnh vị trí y của văn bản để nó nằm dưới ảnh
|
|
.attr("text-anchor", "middle")
|
|
.attr("transform", "rotate(90)") // Căn giữa văn bản theo chiều ngang
|
|
.text(function (d, i) {
|
|
// Lấy nhãn từ dữ liệu gốc của bạn
|
|
return data[i].detail; // Hoặc d.data.label
|
|
})
|
|
.style("fill", function (d, i) {
|
|
// Lấy màu của lát cắt hiện tại từ bảng màu của bạn
|
|
const sliceColor = color(i);
|
|
// Logic để chọn màu chữ tương phản với màu nền của lát cắt
|
|
// Bạn có thể cần điều chỉnh các giá trị màu hex cụ thể để phù hợp hơn
|
|
return '#fff';
|
|
})
|
|
.style("font-size", "1.2rem") // Điều chỉnh kích thước font để phù hợp với ảnh
|
|
.style("font-family", "Baloo Paaji");
|
|
}
|
|
|
|
// container.on("click", spin);
|
|
function spin(d) {
|
|
// check lại 1 lần nữa xem đã từng quay hay chưa
|
|
$.ajaxSetup({
|
|
headers: {
|
|
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
|
|
}
|
|
});
|
|
var url = "{{route('checkspined')}}";
|
|
$.ajax({
|
|
// dataType: 'json',
|
|
url: url,
|
|
type: 'GET',
|
|
contentType: false,
|
|
processData: false,
|
|
success: function (result) {
|
|
if (result.error) {
|
|
alert(result.message);
|
|
return;
|
|
} else if (result.success) {
|
|
if (result.spined == 1) {
|
|
alert('Mỗi người dùng chỉ được quay 1 lần');
|
|
return;
|
|
}
|
|
if (isSpinning) return; // Ngăn chặn nhiều lần quay đồng thời
|
|
isSpinning = true;
|
|
container.selectAll(".animated-dot").classed("spinning", true);
|
|
container.on("click", null);
|
|
//all slices have been seen, all done
|
|
console.log("OldPick: " + oldpick.length, "Data length: " + data.length);
|
|
if (oldpick.length == data.length) {
|
|
console.log("done");
|
|
container.on("click", null);
|
|
return;
|
|
}
|
|
var ps = 360 / data.length,
|
|
pieslice = Math.round(1440 / data.length),
|
|
rng = Math.floor((Math.random() * 1440 * 3) + 360 * 5);
|
|
// Nhân 1440 với 3 (tối đa 12 vòng quay ngẫu nhiên)
|
|
// Cộng thêm 360 * 5 (thêm 5 vòng quay ban đầu)
|
|
|
|
rotation = (Math.round(rng / ps) * ps);
|
|
|
|
picked = Math.round(data.length - (rotation % 360) / ps);
|
|
picked = picked >= data.length ? (picked % data.length) : picked;
|
|
// if (oldpick.indexOf(picked) !== -1) {
|
|
// container.selectAll(".animated-dot").classed("spinning", false);
|
|
// container.selectAll(".animated-dot").style("fill", defaultColor);
|
|
// isSpinning = false;
|
|
|
|
// container.select("#spinCircle").on("click", spin);
|
|
// alert('Kết quả trùng, quay lại');
|
|
// return;
|
|
// } else {
|
|
// oldpick.push(picked);
|
|
// }
|
|
if (oldpick.indexOf(picked) == -1) {
|
|
oldpick.push(picked);
|
|
}
|
|
rotation += 90 - Math.round(ps / 2);
|
|
vis.transition()
|
|
.duration(5000)
|
|
.ease("easeOutBounce")
|
|
.attrTween("transform", rotTween)
|
|
.each("start", function () {
|
|
container.select("#spinCircle").on("click", null);
|
|
})
|
|
.each("end", function () {
|
|
//mark question as seen
|
|
d3.select(".slice:nth-child(" + (picked + 1) + ") path")
|
|
.attr("fill", "#ff9800");
|
|
//populate question
|
|
d3.select("#question h1")
|
|
.text(data[picked].question);
|
|
// $('#answer_value').html(data[picked].answer);
|
|
oldrotation = rotation;
|
|
|
|
setTimeout(function () {
|
|
update_prize_user(data[picked].id, data[picked].label, data[picked].detail)
|
|
}, 1500); // Chờ 2000 milliseconds (2 giây) trước khi hiển thị modal
|
|
|
|
/* Comment the below line for restrict spin to sngle time */
|
|
container.selectAll(".animated-dot").classed("spinning", false);
|
|
container.selectAll(".animated-dot").style("fill", defaultColor);
|
|
isSpinning = false;
|
|
|
|
container.select("#spinCircle").on("click", spin);
|
|
});
|
|
}
|
|
}
|
|
});
|
|
}
|
|
// container.on("click", spin);
|
|
//make arrow
|
|
svg.append("g")
|
|
.attr("transform", "translate(" + (w + padding.left + padding.right) + "," + ((h / 2) + padding.top) + ")")
|
|
.append("path")
|
|
.attr("d", "M-" + (r * .25) + ",0L0," + (r * .15) + "L0,-" + (r * .15) + "Z")
|
|
.style({
|
|
"fill": "red",
|
|
"stroke": "#ff9800",
|
|
"stroke-width": 5
|
|
});
|
|
//draw spin circle
|
|
var gradientMetal = svg.append("defs")
|
|
.append("radialGradient")
|
|
.attr("id", "metalGradient")
|
|
.attr("cx", "50%")
|
|
.attr("cy", "50%")
|
|
.attr("r", "50%")
|
|
.attr("fx", "50%")
|
|
.attr("fy", "50%");
|
|
|
|
gradientMetal.append("stop")
|
|
.attr("offset", "0%")
|
|
.style("stop-color", "#ff0000");
|
|
|
|
gradientMetal.append("stop")
|
|
.attr("offset", "5%")
|
|
.style("stop-color", "#ff0000");
|
|
|
|
gradientMetal.append("stop")
|
|
.attr("offset", "40%")
|
|
.style("stop-color", "#ff0000");
|
|
|
|
gradientMetal.append("stop")
|
|
.attr("offset", "60%")
|
|
.style("stop-color", "#ff0000");
|
|
|
|
gradientMetal.append("stop")
|
|
.attr("offset", "95%")
|
|
.style("stop-color", "#d30808");
|
|
|
|
gradientMetal.append("stop")
|
|
.attr("offset", "100%")
|
|
.style("stop-color", "#d30808");
|
|
|
|
if (is_login && spined == 0) {
|
|
if (screenWidth <= 991) {
|
|
const spinCircle = container.append("circle")
|
|
.attr("id", "spinCircle")
|
|
.attr("cx", 0)
|
|
.attr("cy", 0)
|
|
.attr("r", 40)
|
|
.style({
|
|
"fill": "#ff9800",
|
|
"cursor": "pointer",
|
|
"filter": "drop-shadow(px 3px 8px red)",
|
|
"transition": "filter 0.3s ease-in-out, stroke 0.3s ease-in-out",
|
|
"stroke": "#fff",
|
|
"stroke-width": 8
|
|
}).on("click", spin)
|
|
.on("mouseover", function () {
|
|
d3.select(this).style("filter", "drop-shadow(4px 4px 10px rgba(0, 0, 0, 0.7))").style("stroke", "#aaa");
|
|
})
|
|
.on("mouseout", function () {
|
|
d3.select(this).style("filter", "drop-shadow(3px 3px 8px rgba(0, 0, 0, 0.5))").style("stroke", "#777");
|
|
}).on("click", spin);
|
|
|
|
container.append("text")
|
|
.attr("x", 0)
|
|
.attr("y", 10)
|
|
.attr("text-anchor", "middle")
|
|
.text("QUAY")
|
|
.style({
|
|
"font-weight": "800",
|
|
"font-size": "1.3rem",
|
|
"fill": "red",
|
|
"font-family": "sans-serif",
|
|
"cursor": "pointer",
|
|
// "filter": "drop-shadow(2px 2px 4px rgba(0, 0, 0, 0.7))"
|
|
}).on("click", spin);
|
|
} else {
|
|
const spinCircle = container.append("circle")
|
|
.attr("id", "spinCircle")
|
|
.attr("cx", 0)
|
|
.attr("cy", 0)
|
|
.attr("r", 50)
|
|
.style({
|
|
"fill": "#ffd63b",
|
|
"cursor": "pointer",
|
|
"filter": "drop-shadow(px 3px 8px red)",
|
|
"transition": "filter 0.3s ease-in-out, stroke 0.3s ease-in-out",
|
|
"stroke": "#f80000",
|
|
"stroke-width": 5
|
|
}).on("click", spin)
|
|
.on("mouseover", function () {
|
|
d3.select(this).style("filter", "drop-shadow(4px 4px 10px rgba(0, 0, 0, 0.7))").style("stroke", "#aaa");
|
|
})
|
|
.on("mouseout", function () {
|
|
d3.select(this).style("filter", "drop-shadow(3px 3px 8px rgba(0, 0, 0, 0.5))").style("stroke", "#777");
|
|
}).on("click", spin);
|
|
|
|
container.append("text")
|
|
.attr("x", 0)
|
|
.attr("y", 10)
|
|
.attr("text-anchor", "middle")
|
|
.text("QUAY")
|
|
.style({
|
|
"font-weight": "600",
|
|
"font-size": "1.8rem",
|
|
"fill": "#eb0a0a",
|
|
"font-family": "Baloo Paaji",
|
|
"cursor": "pointer",
|
|
// "filter": "drop-shadow(2px 2px 4px rgba(0, 0, 0, 0.7))"
|
|
}).on("click", spin);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
function rotTween(to) {
|
|
var i = d3.interpolate(oldrotation % 360, rotation);
|
|
return function (t) {
|
|
return "rotate(" + i(t) + ")";
|
|
};
|
|
}
|
|
|
|
function getRandomNumbers() {
|
|
var array = new Uint16Array(1000);
|
|
var scale = d3.scale.linear().range([360, 1440]).domain([0, 100000]);
|
|
if (window.hasOwnProperty("crypto") && typeof window.crypto.getRandomValues === "function") {
|
|
window.crypto.getRandomValues(array);
|
|
console.log("works");
|
|
} else {
|
|
//no support for crypto, get crappy random numbers
|
|
for (var i = 0; i < 1000; i++) {
|
|
array[i] = Math.floor(Math.random() * 100000) + 1;
|
|
}
|
|
}
|
|
return array;
|
|
}
|
|
|
|
|
|
|
|
|
|
function update_prize_user(prize_id, prize_label, prize_detail) {
|
|
var csrfToken = $('meta[name="csrf-token"]').attr('content');
|
|
|
|
$.ajax({
|
|
url: "{{ route('updateprizeuser') }}",
|
|
type: 'POST',
|
|
data: {
|
|
prize_id: prize_id,
|
|
_token: csrfToken // Bao gồm CSRF token
|
|
},
|
|
dataType: 'json', // Mong đợi dữ liệu trả về là JSON
|
|
success: function (response) {
|
|
if (response.success) {
|
|
const prizeListItems = document.querySelectorAll('#prize-list li.blinking-bg');
|
|
|
|
prizeListItems.forEach(item => {
|
|
// Cập nhật background color
|
|
item.style.backgroundColor = '#858585 !important'; // Thay 'your-new-background-color' bằng màu bạn muốn
|
|
|
|
// Bỏ animation bằng cách xóa thuộc tính animation trong style
|
|
item.style.animation = '';
|
|
|
|
// Hoặc bạn có thể xóa class 'blinking-bg' nếu không muốn bất kỳ style nào liên quan đến nó nữa
|
|
// item.classList.remove('blinking-bg');
|
|
});
|
|
var winModalID = document.getElementById('winModal');
|
|
var winModal = new bootstrap.Modal(winModalID, {
|
|
backdrop: 'static',
|
|
keyboard: false
|
|
});
|
|
winModal.show();
|
|
$('#prize_label_cloud').html(prize_label + ' - ' + prize_detail);
|
|
} else {
|
|
alert('Có lỗi xảy ra');
|
|
}
|
|
},
|
|
error: function (xhr, status, error) {
|
|
alert('Có lỗi xảy ra');
|
|
}
|
|
});
|
|
}
|
|
</script> |