Twitterのfaviconはつぶやきがあった場合など赤い点で知らせてくれます。
その方法と、さらにfaviconをパラパラ漫画的にアニメーションさせる事も可能にしたモジュールを試作しました。
faviconを動的に入れ替る
favicon置換するhtmlコードは下記のとおり
<html lang="ja">
<head>
<meta charset="utf-8">
<title>favicon変更</title>
<link rel="shortcut icon" href="favicon.ico" id="favicon">
<script>
function chngFavi(){
var favi = document.getElementById("favicon");
favi.href = "favicon2.ico";
}
</script>
</head>
<body>
<input type="button" value="favicon切り換え" onclick="chngFavi();">
</body>
</html>
favicon入れ替えモジュール
faviconの入れ替えと、ファビコンでパラパラ漫画が出来るモジュールを作ってみました。
作成したモジュールのコードは下記のとおりです。
'use strict';
/*
* Animate the favicon
* Animation favicon can be changed
* Confirmed to work with Firefox and Chrome
*
* Lisence: MIT
* Author: booskanium
*
*/
export default class Petit_favicon {
constructor(cnf) {
this.default = { //Various settings for turning the favicon
faviId: "favicon", //ID name of the element specified by the favicon.
faviHref: "", //Default value of href attribute of element specified by favicon.
favis: [ //List the png image files to be animated. The base64 format is recommended.
{href: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQMAAABJtOi3AAAAA3NCSVQICAjb4U/gAAAABlBMVEUXFxf9/f17uF6KAAAAPUlEQVR4nGP4DwQM+Il/DAz/GT4zMN5n+HCAnZ/hQ/0/nIQ8w9////dDtH34D+TiU8zP8LGBsR9kfD1OywEU9GGHRxCX/AAAAABJRU5ErkJggg=="},
{href: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQMAAABJtOi3AAAAA3NCSVQICAjb4U/gAAAABlBMVEUJCQn////yzuPuAAAAJUlEQVR4nGP4DwQMBAl7IPFHHoX4J49D7H89TNs/LOpwa8NqOQAy6m86rGA4sAAAAABJRU5ErkJggg=="},
{href: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQMAAABJtOi3AAAAA3NCSVQICAjb4U/gAAAABlBMVEUhISH9/f1SulBhAAAAOUlEQVR4nGP4DwQMBAgGhnqGPwyM54EsZn6g2D98RAPjfpCO/wwfDjADifr/eIiPDUCT/4GMx2U5ALW9ZVjTXZbRAAAAAElFTkSuQmCC"},
{href: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQMAAABJtOi3AAAAA3NCSVQICAjb4U/gAAAABlBMVEUjIyP9/f3Pu2qBAAAAOUlEQVR4nGP4DwQM+Il/DAz/Gf4wMM4Hstj4gWL/cBLyQJWM+yE6/jcwyeNVzA9UBzT0DwNDPU7LAQBPYYZTwADdAAAAAElFTkSuQmCC"},
{href: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQMAAABJtOi3AAAAA3NCSVQICAjb4U/gAAAABlBMVEUXFxf///+kBIlKAAAAM0lEQVR4nGP4DwQM+Imf///bMzz4/0eeAPEBRPxmYKxn+MfAANTbwCQPNOAPYeKfPE7LAUDJaMn96+KXAAAAAElFTkSuQmCC"},
{href: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQMAAABJtOi3AAAAA3NCSVQICAjb4U/gAAAABlBMVEULCwv7+/sLx3DPAAAAOUlEQVR4nGP4DwQMBAgGhnqGHwcY7Bl+1AO5P+xxEH9Asv8bgIqBxH2QXnZ8xN92kMn5IMX2OC0HAPYuZ18AwFUvAAAAAElFTkSuQmCC"},
{href: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQMAAABJtOi3AAAAA3NCSVQICAjb4U/gAAAABlBMVEUKCgr7+/tFR+2/AAAAPklEQVR4nGP4DwQMBAgGhnqGnw1A4kc9kPsBTmDjAhX/Z/jTwLAfJMYPJP7xo7D+IYv9ZGA4z/CPgcEep+UAfe9j/4lhW7gAAAAASUVORK5CYII="},
{href: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQMAAABJtOi3AAAAA3NCSVQICAjb4U/gAAAABlBMVEUICAj+/v7TkBV+AAAAMElEQVR4nGP4DwQM+Il/DAz/GT42MPYzfKj/x4+b+PH/vzxc234gARQjivhvj9NyAKTLaRhZinoaAAAAAElFTkSuQmCC"},
{href: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQMAAABJtOi3AAAAA3NCSVQICAjb4U/gAAAABlBMVEUKCgr6+voqmYZfAAAARUlEQVR4nGP4DwQM+Il/DAz/GT43MM9n+PD/nzzDh/p//HAChfv/vzxQJRD9ZGDcD5fFoeP/f36GzwyM9xn+MDDU47QcALkVX5KjF4UGAAAAAElFTkSuQmCC"},
{href: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQMAAABJtOi3AAAAA3NCSVQICAjb4U/gAAAABlBMVEUICAj7+/vYRtdfAAAAPUlEQVR4nGP4DwQMBAgGhnqGjw2M/Qwf6v/zA4l/2Ikf///LgxQDdTQw7AfqBYrhJkBG/WNgOA/SYY/TcgDvoGFjT+QL7gAAAABJRU5ErkJggg=="}
],
fps: 2 //Note that if you make the FPS too large, frames will be dropped.
}
this.config = JSON.parse(JSON.stringify(this.default)); //Dafaultをconfigへdeep copy
this.intervId = null; //Favicon turning interval ID
this.ix = 0; //Favicon turning index
if (cnf) { //Set your own settings
this.change(cnf);
}
if (!!document.getElementById(this.config.faviId)) {
this.default.faviHref = document.getElementById(this.config.faviId).href;
this.config.faviHref = document.getElementById(this.config.faviId).href;
}
}
change(cnf) { //Change the animation favicon
if (this.intervalId) {
window.clearInterval(this.intervalId);
}
if (cnf) {
if ('faviID' in cnf) this.config.faviId = cnf.favId;
if ('faviHref' in cnf) this.config.faviHref = cnf.favHref;
if ('favis' in cnf) this.config.favis = cnf.favis;
if ('fps' in cnf) this.config.fps = cnf.fps;
} else {
this.config = JSON.parse(JSON.stringify(this.default)); //Deep copy Default to config
}
}
start() { //Start Favicon animation
if (this.intervalId) {
window.clearInterval(this.intervalId);
}
let fpsRate = 1000 / this.config.fps;
this.ix = 0;
document.getElementById(this.config.faviId).href = this.config.favis[this.ix].href;
if (this.config.favis.length > 1) {
this.intervalId = setInterval(()=>{
if (this.ix >= this.config.favis.length - 1) {
this.ix = 0;
} else {
this.ix++;
}
document.getElementById(this.config.faviId).href = this.config.favis[this.ix].href;
}, fpsRate);
}
}
stop() { //Stop the Favicon animation and replace it with the default Favicon
if (this.intervalId) {
window.clearInterval(this.intervalId);
}
document.getElementById(this.config.faviId).href = this.config.faviHref;
}
}
・モジュールなのでimportする
・newはDOMが有効になった(DOMContentLoaded)後に
・configの設定はnewする時、またはchangeメソッドで
・configでのfavicon指定はコード中のコメントを参照
・faviconイメージはbase64でconfigに配列で設定する
※配列が1つだと単純なファビコン入れ替え
※faviconのURL指定も可だがDDoSもどきなので要注意
※faviconイメージはpng推奨
※faviconでsvg利用はSfariが開国したてで時期尚早
・ぱらぱらfpsが速すぎるとコマ落ちするので程々に
・メソッドは
change configの入れ替え
start faviconのアニメーション開始
stop faviconを既定値に戻す
動くファビコンを利用する場合の注意事項です。
・base64で抱え込まないと自爆DDoSかも
・スマホブラウザでは無意味(無駄に裏で機能している)
・faviconを派手に動かしすぎると多分嫌われる
ということで、ほどほどに!!
上記のモジュールを当ページに組み込んだ「index.js」
import Petit_favicon from "../js/modules/__petit_fav.js";
const favi = new Petit_favicon();
document.getElementById("stop").addEventListener("click", () => {
favi.stop();
});
document.getElementById("start").addEventListener("click", () => {
favi.change({favis: [
{href: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAySURBVEhL7c0hAgAgDIBA9P9/nsVOWuMKkQPDpvu7poFqoBqoBqqBaqAaqAaqgWog4AGhxgE/VKJr9AAAAABJRU5ErkJggg=="},
{href: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAxSURBVEhL7c2hAQAACITA1/131mIn2bhCpGbyqq9vHCAHyAFygBwgB8gBcoAcIAcgWbZaAj6Rffc+AAAAAElFTkSuQmCC"},
{href: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABKSURBVEhLtcexDQAwEAMh77/0p7+aSDTs9lfP9VzP9VzP9VzP9VzP9VzP9VzP9VzP9VzP9VzP9VzP9VzP9VzP9VzP9VzP9VyPbQ8yw/wuEOdxyQAAAABJRU5ErkJggg=="}
],fps:1});
favi.start();
});
document.getElementById("bule").addEventListener("click", () => {
favi.change({favis:[{href: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAySURBVEhL7c0hAgAgDIBA9P9/nsVOWuMKkQPDpvu7poFqoBqoBqqBaqAaqAaqgWog4AGhxgE/VKJr9AAAAABJRU5ErkJggg=="}]});
favi.start();
});
document.getElementById("yellow").addEventListener("click", () => {
favi.change({favis:[{href: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAxSURBVEhL7c2hAQAACITA1/131mIn2bhCpGbyqq9vHCAHyAFygBwgB8gBcoAcIAcgWbZaAj6Rffc+AAAAAElFTkSuQmCC"}]});
favi.start();
});
document.getElementById("red").addEventListener("click", () => {
favi.change({favis:[{href: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABKSURBVEhLtcexDQAwEAMh77/0p7+aSDTs9lfP9VzP9VzP9VzP9VzP9VzP9VzP9VzP9VzP9VzP9VzP9VzP9VzP9VzP9VzP9VyPbQ8yw/wuEOdxyQAAAABJRU5ErkJggg=="}]});
favi.start();
});
document.getElementById("demo").addEventListener("click", () => {
favi.change();
favi.start();
});