388 lines
9.6 KiB
ERB
388 lines
9.6 KiB
ERB
<div class="w-video_data video_data-widget-8" data-subpart-id="{{subpart-id}}">
|
|
<h3 class="widget-title"><span>{{widget-title}}</span></h3>
|
|
|
|
<div class="vw3-carousel">
|
|
<button class="vw3-prev" title="上一組" aria-label="上一組" type="button">
|
|
<i class="fa fa-angle-left" aria-hidden="true"></i>
|
|
</button>
|
|
|
|
<div class="vw3-track-wrap">
|
|
<ul class="video_data_wrap vw3-track" data-list="videos" data-level="0">
|
|
<li class="video_data vw3-slide" data-video-url="{{video_url}}" data-video-webm-url="{{video_webm_url}}" data-type="{{video_type}}">
|
|
<a href="{{video_show_url}}" title="{{video_title_escape}}">
|
|
<div class="video_linkwrapper3">
|
|
<div class="videohover">
|
|
<div class="view_info"><span>{{view_count}}</span></div>
|
|
<div class="Video__Player"><button class="Video__PlayerButton" type="button"></button></div>
|
|
</div>
|
|
<img class="video_snapshot" src="{{snapshot_url}}" alt="{{video_title_escape}}">
|
|
</div>
|
|
</a>
|
|
<div class="video_info">
|
|
<div class="video_title">
|
|
<a class="video_link" href="{{video_show_url}}" title="{{video_title_escape}}"><h4>{{video_title}}</h4></a>
|
|
</div>
|
|
<div class="video_desc">
|
|
<a class="video_link" href="{{video_show_url}}" title="{{video_title_escape}}">{{video_desc}}</a>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<button class="vw3-next" title="下一組" aria-label="下一組" type="button">
|
|
<i class="fa fa-angle-right" aria-hidden="true"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.video_data-widget-8 {
|
|
position: relative;
|
|
|
|
.widget-title { margin-bottom: 1rem; }
|
|
|
|
/* 外層輪播框 */
|
|
.vw3-carousel {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
position: relative;
|
|
}
|
|
|
|
/* 可視區域 */
|
|
.vw3-track-wrap {
|
|
overflow: hidden;
|
|
flex: 1;
|
|
}
|
|
|
|
/* 滑動軌道 */
|
|
.vw3-track {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 1rem;
|
|
list-style: none;
|
|
margin: 0;
|
|
padding: 0;
|
|
transition: transform 0.4s ease;
|
|
}
|
|
|
|
/* 所有 slide 共用 */
|
|
.vw3-slide {
|
|
flex-shrink: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
/* 第一張大卡:40% 相對容器 */
|
|
.vw3-slide:nth-child(1) {
|
|
width: 40%;
|
|
position: relative;
|
|
|
|
.video_linkwrapper3 { margin-bottom: 0; }
|
|
|
|
.video_info {
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
padding: 2rem 1rem 1rem;
|
|
background: linear-gradient(to top, rgba(0,0,0,0.7) 0%, transparent 100%);
|
|
border-radius: 0 0 14px 14px;
|
|
z-index: 10;
|
|
margin: 0;
|
|
}
|
|
|
|
.video_title h4 {
|
|
color: #fff;
|
|
font-size: 1.15rem;
|
|
font-weight: 500;
|
|
margin: 0 0 0.2rem;
|
|
}
|
|
|
|
.video_desc,
|
|
.video_desc a {
|
|
color: rgba(255,255,255,0.85);
|
|
font-size: 0.85rem;
|
|
}
|
|
}
|
|
|
|
/* 後續小卡:各約 20% */
|
|
.vw3-slide:nth-child(n+2) {
|
|
width: calc(20% - 0.75rem);
|
|
|
|
.video_info {
|
|
padding: 0.5rem 0 0;
|
|
margin: 0;
|
|
}
|
|
|
|
.video_title h4 {
|
|
font-size: 0.95rem;
|
|
font-weight: 500;
|
|
color: #1a1a1a;
|
|
margin: 0 0 0.2rem;
|
|
display: -webkit-box;
|
|
-webkit-line-clamp: 2;
|
|
-webkit-box-orient: vertical;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.video_desc,
|
|
.video_desc a {
|
|
font-size: 0.82rem;
|
|
color: #666;
|
|
display: -webkit-box;
|
|
-webkit-line-clamp: 2;
|
|
-webkit-box-orient: vertical;
|
|
overflow: hidden;
|
|
}
|
|
}
|
|
|
|
/* 圖片共用 */
|
|
.video_linkwrapper3 {
|
|
position: relative;
|
|
aspect-ratio: 16 / 9;
|
|
overflow: hidden;
|
|
border-radius: 14px;
|
|
box-shadow: 0 2px 12px rgba(0,0,0,0.1);
|
|
transition: transform 0.22s ease, box-shadow 0.22s ease;
|
|
|
|
&:hover {
|
|
transform: translateY(-4px);
|
|
box-shadow: 0 8px 24px rgba(0,0,0,0.18);
|
|
}
|
|
|
|
img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
display: block;
|
|
}
|
|
}
|
|
|
|
/* 播放按鈕 */
|
|
.Video__Player {
|
|
position: absolute;
|
|
top: 50%;
|
|
left: 50%;
|
|
transform: translate(-50%, -50%);
|
|
z-index: 10;
|
|
}
|
|
|
|
.Video__PlayerButton {
|
|
width: 48px;
|
|
height: 48px;
|
|
border-radius: 50%;
|
|
background: rgba(255,255,255,0.85);
|
|
border: none;
|
|
cursor: pointer;
|
|
position: relative;
|
|
|
|
&::after {
|
|
content: '';
|
|
position: absolute;
|
|
top: 50%;
|
|
left: 54%;
|
|
transform: translate(-50%, -50%);
|
|
width: 0;
|
|
height: 0;
|
|
border-style: solid;
|
|
border-width: 8px 0 8px 16px;
|
|
border-color: transparent transparent transparent #1a1a1a;
|
|
}
|
|
|
|
&:hover { background: #fff; }
|
|
}
|
|
|
|
/* 左右箭頭 */
|
|
.vw3-prev,
|
|
.vw3-next {
|
|
flex-shrink: 0;
|
|
width: 36px;
|
|
height: 36px;
|
|
border-radius: 50%;
|
|
background: rgba(0,0,0,0.15);
|
|
color: #fff;
|
|
border: none;
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 1.2rem;
|
|
transition: background 0.2s;
|
|
z-index: 10;
|
|
|
|
&:hover { background: rgba(0,0,0,0.4); }
|
|
&:focus { outline: 2px solid #2980b9; outline-offset: 2px; }
|
|
&:disabled { opacity: 0.3; cursor: default; }
|
|
}
|
|
|
|
/* view_info */
|
|
.view_info {
|
|
position: absolute;
|
|
top: 10px;
|
|
left: 10px;
|
|
background: rgba(0,0,0,0.75);
|
|
color: #fff;
|
|
font-size: 0.8rem;
|
|
padding: 2px 8px;
|
|
border-radius: 3px;
|
|
z-index: 10;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
}
|
|
|
|
/* RWD */
|
|
@media(max-width: 768px) {
|
|
.vw3-slide:nth-child(1) { width: 100%; }
|
|
.vw3-slide:nth-child(n+2) { width: calc(50% - 0.5rem); }
|
|
}
|
|
|
|
@media(max-width: 480px) {
|
|
.vw3-slide:nth-child(n+2) { width: 100%; }
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
$(document).ready(function() {
|
|
var $widget = $('[data-subpart-id="{{subpart-id}}"]');
|
|
var $trackWrap = $widget.find('.vw3-track-wrap');
|
|
var $track = $widget.find('.vw3-track');
|
|
var $prevBtn = $widget.find('.vw3-prev');
|
|
var $nextBtn = $widget.find('.vw3-next');
|
|
|
|
var originalSlides = $widget.find('.vw3-slide').toArray();
|
|
var total = originalSlides.length;
|
|
if (total === 0) return;
|
|
|
|
var currentIndex = 0; // 目前第一個顯示的 slide index(在 originalSlides 裡)
|
|
|
|
// 重建 track:把所有 slide 克隆三份(前後各補一輪),讓循環無縫
|
|
function buildTrack() {
|
|
$track.empty();
|
|
// 補後一輪(讓往右循環)
|
|
$(originalSlides).each(function() {
|
|
$track.append($(this).clone().addClass('vw3-clone'));
|
|
});
|
|
// 原始
|
|
$(originalSlides).each(function() {
|
|
$track.append($(this).clone());
|
|
});
|
|
// 補前一輪(讓往左循環)
|
|
$(originalSlides).each(function() {
|
|
$track.append($(this).clone().addClass('vw3-clone'));
|
|
});
|
|
}
|
|
|
|
function getVisibleCount() {
|
|
return $(window).width() < 1024 ? 1 : 4;
|
|
}
|
|
|
|
function isMobile() {
|
|
return $(window).width() < 1024;
|
|
}
|
|
|
|
// 更新每個 slide 的寬度
|
|
function updateWidths() {
|
|
var $allSlides = $track.find('.vw3-slide');
|
|
var wrapWidth = $trackWrap.width();
|
|
var gap = 16;
|
|
var visibleCount = getVisibleCount();
|
|
var mobile = isMobile();
|
|
|
|
// 先全部清除大卡樣式
|
|
$allSlides.find('.video_info').css({
|
|
'color' : '',
|
|
'position' : '',
|
|
'bottom' : '',
|
|
'width' : '',
|
|
'padding' : '',
|
|
'background-image' : '',
|
|
'border-radius' : ''
|
|
});
|
|
$allSlides.find('.video_title h4').css({
|
|
'color' : '',
|
|
'font-size' : ''
|
|
});
|
|
|
|
if (mobile) {
|
|
// 手機:一次一則,全寬,不套大卡樣式
|
|
$allSlides.css('width', wrapWidth + 'px');
|
|
} else {
|
|
// 桌機:第一張 40%,其餘平分
|
|
var bigWidth = wrapWidth * 0.4;
|
|
var smallTotal = wrapWidth - bigWidth - gap * (visibleCount - 1);
|
|
var smallWidth = smallTotal / (visibleCount - 1);
|
|
|
|
$allSlides.css('width', smallWidth + 'px');
|
|
|
|
var firstVisibleIdx = total + currentIndex;
|
|
var $firstSlide = $allSlides.eq(firstVisibleIdx);
|
|
|
|
$firstSlide.css('width', bigWidth + 'px');
|
|
|
|
$firstSlide.find('.video_info').css({
|
|
'color' : '#fff',
|
|
'position' : 'absolute',
|
|
'bottom' : '0',
|
|
'width' : '100%',
|
|
'padding' : '2em',
|
|
'background-image' : 'linear-gradient(180deg, transparent 0, #00000066 40%, #000000a3)',
|
|
'border-radius' : '0 0 14px 14px'
|
|
});
|
|
|
|
$firstSlide.find('.video_title h4').css({
|
|
'color' : '#fff',
|
|
'font-size' : '1.5em'
|
|
});
|
|
}
|
|
}
|
|
|
|
// 計算 track 的 translateX,讓第一個顯示的 slide 對齊左邊
|
|
function getOffset(targetIdx) {
|
|
var $allSlides = $track.find('.vw3-slide');
|
|
var offset = 0;
|
|
var gap = 16;
|
|
for (var i = 0; i < targetIdx; i++) {
|
|
offset += parseFloat($allSlides.eq(i).css('width')) + gap;
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
function goTo(newIndex, animate) {
|
|
currentIndex = ((newIndex % total) + total) % total;
|
|
|
|
updateWidths();
|
|
|
|
var targetIdx = total + currentIndex; // 中間那組的 index
|
|
var offset = getOffset(targetIdx);
|
|
|
|
if (animate === false) {
|
|
$track.css('transition', 'none');
|
|
$track.css('transform', 'translateX(-' + offset + 'px)');
|
|
$track[0].offsetHeight; // force reflow
|
|
$track.css('transition', '');
|
|
} else {
|
|
$track.css('transform', 'translateX(-' + offset + 'px)');
|
|
}
|
|
}
|
|
|
|
// 初始化
|
|
buildTrack();
|
|
goTo(0, false);
|
|
|
|
$prevBtn.on('click', function() {
|
|
goTo(currentIndex - 1, true);
|
|
});
|
|
|
|
$nextBtn.on('click', function() {
|
|
goTo(currentIndex + 1, true);
|
|
});
|
|
|
|
$(window).on('resize', function() {
|
|
goTo(currentIndex, false);
|
|
});
|
|
});
|
|
</script>
|