今天的內容一樣是 Video.js
我們來看看如何替播放器加上浮水印。
這裡的浮水印是添加在播放器上,而不是添加在影片上。所以如果有人寫爬蟲抓走影片片源,影片本身還是不會有水印的。
前端能做的不是改變影片(片源)本身的內容,而是從<vidoe>
和其周遭的 HTML 標籤著手,想辦法把水印圖像疊在播放器介面上。
將播放器添加浮水印圖片不外乎是三種方式:
<img>
圖片疊上去div
和 CSS 的 background-img
搭配疊上去採上面任一種作法後,用CSS 絕對定位 去對齊播放器位置。
我們可以暴力用 JS 添加水印疊在播放器上,也可以用 Videojs plugins 的方式來添加浮水印,關於 plugins ,videojs 的 文件 也有開發說明,不過看完大概還是有點問號不知道該怎麼做。
幸運的是,網路上仍然找的到非官方的 Video.js 浮水印套件,先來看看此套件原本的用法:
下載這個 浮水印套件 到本地端,記得先在 HTML 引入(或者 NPM 安裝後 import ) Video.js 的 JS 和 CSS 檔案。確認 Video.js 本身 CSS 和 JS 有引入後才引入浮水印的 JS 和 CSS
<!-- CSS -->
<link href="路徑/videojs.watermark.css" rel="stylesheet">
<!-- JS -->
<script src='路徑/videojs.watermark.js'></script>
HTML
<video id="my-video" class="video-js"><video>
JS
const player = videojs('my-video',{
sources:[{ src: "http://www.html5videoplayer.net/videos/toystory.mp4"}],
loop:true,
muted:true,
width:"600",
height:"300",
controls:true
});
player.watermark({
file: 'http://literreviewstaffing.com/wp-content/uploads/2015/02/google-1088004_960_720-150x150.png',
xpos: 100,
ypos: 100,
opacity: 0.5,
});
使用videojs()
建立videojs物件後,再用.watermark()
去建立浮水印相關的設定,.watermark()
內可以傳入一個物件,浮水印即會是按照傳入的物件屬性、值做對應的設置。
videojs物件.watermark({
設定屬性:值
});
當然囉,所謂.watermark()
並不是 Videojs 原本定義好的 Method,而是這個 plugins 添加的。
以下是這個 Library 套件.watermark()
可傳入物件屬性、值說明:
屬性 | 值 | 描述 |
---|---|---|
file | 字串 ( URL 路徑 ) | 圖片位置 |
xpos | 數值 | 水印圖在播放器上的位置參數 |
ypos | 數值 | 水印圖在播放器上的位置參數 |
opacity | 數值 ( 0.1 ~ 1 ) | 透明度 |
className | 字串 | CSS的class名稱(添加在水印上) |
url | 字串 ( URL 路徑 ) | 浮水印超連結網址 |
clickable | 布林值 | 設置浮水印超連結是否可點選連結 |
debug | 布林值 | 顯示 console.log() 內容 |
xrepeat | 布林值 | 設置圖片是否重複 |
其中末三項 clickablede、bug、xrepeat 其實沒什麼幫助,之後會解釋。
至此便完成浮水印
雖然完成浮水印功能了,但這個浮水印套件也衍生了一些問題:
首先,這個 xpos 和 ypos 其實不是所謂 X 座標 和 Y 座標
videojs物件.watermark({
file: 'watermarks.png',
xpos: 50,
ypos: 50,
opacity: 0.5,
});
按照這個套件文件寫的內容描述來看
Center: xpos: 50 ypos: 50
Bottom right: xpos: 100 ypos: 100
Top left: xpos: 0 ypos: 0
意思是
xpos | ypos | 位置 |
---|---|---|
0 | 0 | 左上角 |
0 | 50 | 右上角 |
50 | 50 | 中央 |
0 | 100 | 左下角 |
100 | 100 | 右下角 |
但是這種設置參數的方式很容易讓人誤會,當輸入0、50、100以外的數值,水印就會出現在左上角,這是因為這個套件預設水印位置在左上角。
當我們讓浮水印出現在左下角或右下角時
點擊全螢幕的按鈕會沒反應,用開發者工具來檢查
原來是因為圖片蓋到全螢幕按扭了,這是因為
z-index
設置了2000
想解決這問題很簡單,因為圖片在右下角,按照 CSS 的絕對定位來看,我們可以假定套件原始碼是設置了 bottom:0;
和 righr:0;
而 videojs 下方控制條 UI 只有高30px
,只要把 bottom:0;
改成 bottom:30px;
就能解決這問題。
為了解決這兩個問題,檢查這個套件的 JS
從上面這段可以看到,原來可以傳入 .watermark()
物件的屬性和值,是在 defaults 這邊定義的。
在 defaults 下方段落的 extend
和 videojs.plugin
把這個 plugin 綁到 videojs上 (其實是新增到 videojs 的 prototypal 上,關於何謂原型可以參考我 去年的筆記 )
參數 xpos 和 ypos ,其實只是用來在裏頭做 if 判定,並不是真的依數值多少來賦值給絕對定位。既然這個套件的定位 ( 左上、右上、左下、右下、中央 ) 是寫死的,用 xpos 和 ypos 反而容易讓人誤會。
基本上只是和 url 參數在 if 搭配判斷用,但是要判斷是否產生連結用 url 判斷是否空值就好,多比較這個參數沒什麼意義。
只是用來打開 console.log
的內容,其實也沒什麼意義。
這個參數相關程式碼,在 JS 裏頭被註解了,那這參數也沒什麼意義。
以下是我修改過後的版本: ITMAN_watermark
屬性 | 值 | 描述 | 預設 |
---|---|---|---|
file | 字串 ( URL 路徑 ) | 圖片位置 | |
position | 字串 | 水印圖在播放器上的位置 | "bottom-right" |
opacity | 數值 ( 0.1 ~ 1 ) | 透明度 | 1 |
className | 字串 | CSS的class名稱(添加在水印上) | |
url | 字串 ( URL 路徑 ) | 浮水印超連結網址 |
postiion 會決定浮水印圖片的位置, 我以 postiion 取代原本的 xpos、ypos ,其可設置的值為:
值 | 浮水印位置 |
---|---|
"top-left" 或 "left-top" | 左上 |
"bottom-left" 或 "left-bottom" | 左下 |
"top-right" 或 "right-top" | 右上 |
"bottom-right" 或 "right-bottom" | 右下 |
className 的設定為,當使用者傳入自己的 class 樣式名稱,會接續在 ITMAN.watermanmark.css
的樣式後面變成
<div class="itman-watermark 你傳入的樣式名稱">
<img>
</div>
或見 github ITMAN_watermark
JavaScript
(function() {
const defaults = {
file: "",
position: "bottom-right",
opacity: 1,
url: "",
className: "itman-watermark",
};
const extend = function() {
let args, target, i, object, property;
args = Array.prototype.slice.call(arguments);
target = args.shift() || {};
for (i in args) {
object = args[i];
for (property in object) {
if (object.hasOwnProperty(property)) {
if (typeof object[property] === "object") {
target[property] = extend(target[property], object[property]);
} else {
target[property] = object[property];
}
}
}
}
return target;
};
let div;
// 使用 .registerPlugin 和 extend 把自訂內容綁進videojs
// .registerPlugin() 第一個參數名稱會對應之後新建進videojs原形鏈上的方法名稱
videojs.registerPlugin("watermark", function(settings) {
let options, player, video, img, link;
options = extend(defaults, settings);
player = this.el();
video = this.el().getElementsByTagName("video")[0];
// 創建浮水印相關元素的 div
if (!div) {
div = document.createElement("div");
options.className === "vjs-watermark"
? (div.className = options.className)
: (div.className = "vjs-watermark " + options.className);
} else {
// 如果 div 已存在 就清空 div 內容
div.innerHTML = "";
}
// 圖片設定
if (options.file) {
img = document.createElement("img");
div.appendChild(img);
img.src = options.file;
}
// 浮水印位置設定
if (options.position === "top-left" || options.position === "left-top") {
// 左上
div.style.top = "0";
div.style.left = "0";
} else if (
options.position === "top-right" ||
options.position === "right-top"
) {
// 右上
div.style.top = "0";
div.style.right = "0";
} else if (
options.position === "bottom-right" ||
options.position === "right-bottom"
) {
// 右下 ( 30px 是為了避開與導覽列UI重疊 )
div.style.bottom = "30px";
div.style.right = "0";
} else if (
options.position === "bottom-left" ||
options.position === "left-bottom"
) {
// 左下 ( 30px 是為了避開與導覽列UI重疊 )
div.style.bottom = "30px";
div.style.left = "0";
} else if (options.position === "center") {
// Center
div.style.top = this.height() / 2 + "px";
div.style.left = this.width() / 2 + "px";
}
// 透明度設定
div.style.opacity = options.opacity;
// url參數有值(連結) 就替浮水印添加 a 標籤
if (options.url !== "") {
link = document.createElement("a");
link.href = options.url;
link.target = "_blank";
link.appendChild(div);
player.appendChild(link);
} else {
player.appendChild(div);
}
});
})();
CSS
.itman-watermark {
position: absolute;
display: inline-block;
z-index: 1;
width: 20%;
}
.itman-watermark img {
width: 100%;
height: auto;
}
videojs 文件 plugins
videojs 浮水印 Library