網站項目經常會遇到一些視頻或者圖片素材的展示功能,那么就需要自己寫一個功能,就是在一些列表頁面你想要是這個數據的詳細內容,彈框在頁面某個位置
例如這是視頻懸浮展示效果,可自定義自動播放等屬性標簽
又例如這是圖片懸浮展示,可控制懸浮展示與不展示
像上面這樣或者一些其他列表做的一些懸浮彈框展示等,都可以自定義完成。
那這樣的插件需要怎么調用呢?
// 插件的調用
// dom 是父元素調用
$(dom).scaleTools({
item: 'li', // 這是子元素,可以為多個 ,元素需定義data-src屬性與值,為彈框展示提供數據
fade: true, // 顯示方式
conCallback(src) { // 這邊是生成的展示內容標簽,默認是img
return '<video autoplay muted loop><source src="'+ src +'"></video>' // 這邊是已視頻為例子
}
})
// 一些其他參數
{
checkbtn: ' ', // 這是提供控制是否彈框的按鈕元素
followScroll: true, // 彈框根據元素位置固定或根據窗口位置固定,默認根據鼠標懸浮元素
fadeTime: 500, // 生成彈框間隔時間,默認鼠標懸浮后500毫秒后展示
oftX: 0, // 水平方向距離懸浮元素間距
oftYPosition: 'center', // 生成彈框與元素垂直方向中心點對齊, 其他參數'top', 'bottom'
}
上面的一些調用參數就是插件全部接受的自定義數據,如果有其他特有的需求可以自己讀懂源碼再去修改,或者給我留言,我去添加,下面就是方法的定義:
;(function($, win) {
const PLUGINNAME = 'scaleTools'; // 定義插件名
let defaultOpts = { // 默認參數
item: '.item',
checkbtn: '',
fade: false,
followScroll: true,
fadeTime: 500,
oftX: 0,
oftYPosition: 'center', // 'top', 'bottom'
conCallback: false
};
class Plugin {
constructor(wrap, opts) {
this.wrap = $(wrap);
this.opts = $.extend(true, {}, defaultOpts, opts); // 合並用戶參數
this.items = this.wrap.children(this.opts.item);
this.isShown = false;
this.timer;
this.checkShow = false;
this.init();
}
init() {
this.getSize() // 獲取窗口大小
this.initEvent() // 初始事件
}
initEvent() {
this.wrap
.on('mouseenter', this.opts.item, this.timeInterval.bind(this)) // 父元素委托鼠標進入事件
.on('mouseleave', this.opts.item, this.unbindScale.bind(this)); // 鼠標離開事件
$(win).on('resize', this.getSize.bind(this)); // 窗口改變重新獲取
$(win).on('scroll', this.changeScrollTop.bind(this)); // 窗口滾動事件
if(!!this.opts.checkbtn) { // 是否存在插件開關
$(this.opts.checkbtn).on('click', (e)=> {
this.checkShowFn(); // 切換彈框是否懸浮展示
})
}
}
getSize() {
this.winH = $(window).height();
this.winW = $(window).width();
}
initTool(e) {
let html = '<div class="scaleTool"><div class="tool-content">{ inner }</div></div>', // 初始彈框容器, 樣式自己在樣式文件寫
str = '',
src = $(e.target).closest(this.opts.item).data('src') || $(e.target).closest(this.opts.item).find('img').attr('src'); // 獲取懸浮元素 需要展示的數據src ,圖片或者視頻, 如果其他可不填
if(!this.opts.conCallback) {
str = '<img src="'+ src +'" />'
}else {
str = this.opts.conCallback(src)
};
if($('.scaleTool').length) { // 存在彈框
this.toolDom = $('.scaleTool'); // 重新賦值
this.toolDom.find('.tool-content').html(str); // 修改內容
} else {
html = html.replace('{ inner }', str); // 填入內容
$('body').append(html); // 加入頁面
this.toolDom = $('.scaleTool'); // 初始聲明
}
}
checkShowFn() { // 是否彈框開關
this.checkShow = !this.checkShow;
if(this.checkShow) {
$(this.opts.checkbtn).addClass('active') // 為開關添加類名自定義樣式
} else {
$(this.opts.checkbtn).removeClass('active');
this.toolDom.remove();
}
}
unbindScale() { // 鼠標離開
clearTimeout(this.timer);
if(this.toolDom && (this.checkShow || !this.opts.checkbtn)) {
this.opts.conCallback && this.toolDom.find('video')[0].pause();
this.toolDom.hide();
this.isShown = false
}
}
// 鼠標進入
timeInterval(event) {
if(this.checkShow || !this.opts.checkbtn) {
this.timer = setTimeout(()=>{
this.showScale(event);
}, this.opts.fadeTime)
}
}
showScale(e) {
clearTimeout(this.timer);
if(this.isShown || this.winW < 1200) return; // 頁面窗口小於1200 或者正在顯示彈框 return
this.initTool(e);
let itemW = this.toolDom.width(),
itemH = this.toolDom.height(),
curX, curY,
$curBox = $(e.target).closest(this.opts.item);
// 獲取當前懸浮元素的一些位置信息,對彈框位置的定義
let box = $curBox.get(0).getBoundingClientRect();
if(box.right > this.winW / 2) {
curX = box.left - itemW - this.opts.oftX
} else {
curX = box.right + this.opts.oftX
}
if(this.opts.oftYPosition === 'top') {
if(box.top < itemH) {
if(box.top < 0) {
curY = 0
} else {
curY = box.top
}
} else {
curY = box.top - itemH
}
} else if(this.opts.oftYPosition === 'bottom') {
if(this.winH - box.bottom > itemH) {
curY = box.bottom
} else {
curY = this.winH - itemH
}
} else {
if((box.top + $curBox.outerHeight() / 2) < itemH / 2) {
if(box.top < 0) {
curY = 0
} else {
curY = box.top
}
} else {
if((box.bottom - $curBox.outerHeight() / 2) > (this.winH - itemH / 2)) {
curY = this.winH - itemH
} else {
curY = box.top + $curBox.outerHeight() / 2 - itemH / 2
}
}
}
this.scrollH = $(win).scrollTop();
this.toolDom.css({
left: curX,
top: curY
});
this.toolT = curY;
// 展示方式
if(this.opts.fade) {
this.toolDom.fadeIn()
} else {
this.toolDom.show()
}
this.playVideo()
this.isShown = true
}
changeScrollTop(e) { // 根據滾動高度修改彈框位置
let scrollT = $(e.target).scrollTop(),
reScrollT = this.scrollH,
itemT = this.toolT,
newScrollT;
if(this.opts.followScroll && this.isShown) {
newScrollT = reScrollT - scrollT;
this.toolDom.css({
top: itemT + newScrollT,
});
}
}
playVideo() { // 視頻播放
setTimeout(()=> {
this.opts.conCallback && this.toolDom.find('video').get(0).play()
}, 0)
}
}
$.fn[PLUGINNAME] = function(options) {
this.each(function() {
if (!$.data(this, "plugin_" + PLUGINNAME)) {
$.data(this, "plugin_" + PLUGINNAME, new Plugin(this, options));
}
});
return this;
};
})(jQuery, window);
上面則是全部插件方法定義了,公司項目網站www.macw.com, 這個插件主要用在視頻與素材板塊,即v.macw.com的整站與sc.macw.com的圖庫分類, 如果有興趣可以來網站看一下效果
有很多不足希望能夠指出,學習進步,互相關注,謝謝~