Mengubah favicon situs web secara dinamis

347

Saya memiliki aplikasi web yang bermerek sesuai dengan pengguna yang saat ini masuk. Saya ingin mengubah favicon halaman menjadi logo label pribadi, tetapi saya tidak dapat menemukan kode atau contoh bagaimana untuk melakukan ini. Adakah yang berhasil melakukan ini sebelumnya?

Saya membayangkan memiliki selusin ikon di folder, dan referensi yang menggunakan file favicon.ico baru saja dihasilkan secara dinamis bersama dengan halaman HTML. Pikiran?

SqlRyan
sumber
40
Ada permainan arcade di favicon.
Corey Trager
Perhatikan bahwa implementasi favicon dinamis Chrome buggy dan menggunakan CPU terlalu banyak. Lihat code.google.com/p/chromium/issues/detail?id=121333
brillout
6
Tautan untuk game arcade berubah. Ini yang benar.
Basil
Lihat stackoverflow.com/questions/6296574/… tentang cara memperbarui favicon secara dinamis dengan menggambar di atas gambar templat dengan kanvas.
tangani
1
Bug kecil dalam contoh kode disediakan dalam jawaban yang diterima. Saya tidak memiliki skor reputasi yang cukup untuk mengomentari jawaban, karenanya saya menulis di sini. Baris terakhir diapit tanda kurung:} ()); harus dibaca })(); Alangkah baiknya bahwa contoh kode menjadi diperbarui karena kemungkinan besar disalin dan ditempel oleh orang lain.
Goran W

Jawaban:

396

Kenapa tidak?

(function() {
    var link = document.querySelector("link[rel*='icon']") || document.createElement('link');
    link.type = 'image/x-icon';
    link.rel = 'shortcut icon';
    link.href = 'http://www.stackoverflow.com/favicon.ico';
    document.getElementsByTagName('head')[0].appendChild(link);
})();

Firefox seharusnya keren dengan itu.

diedit untuk menimpa ikon yang ada dengan benar

keparo
sumber
2
Saya pikir ini dekat dengan apa yang saya cari, tetapi bagaimana saya mendapatkan HREF yang sesuai dari database. Saya kira saya harus melakukan pencarian server dari javascript, tapi saya tidak ingin terlalu rumit. Terima kasih atas tipnya.
SqlRyan
34
Karena ini tidak bekerja di IE, Anda dapat menghapus shortcutdari relatribut. shortcutadalah hubungan tautan IE-proprietary yang tidak valid!
Mathias Bynens
8
Anda bisa dengan mudah mencari tautan favicon yang ada dan memperbarui atau menggantinya.
keparo
5
Google dapat memberi Anda favicon situs dengan menggunakan url ini, menggantikan stackoverflow.com dengan domain yang Anda inginkan: s2.googleusercontent.com/s2/favicons?domain=stackoverflow.com
kirb
5
Haruskah memasukkan ini di konsol Javascript di Chrome work? Saya tidak bisa mengubah favicon di berbagai situs dengan cara itu.
powerj1984
88

Berikut beberapa kode yang berfungsi di Firefox, Opera, dan Chrome (tidak seperti setiap jawaban lain yang diposting di sini). Berikut adalah demo kode yang berbeda yang juga berfungsi di IE11 . Contoh berikut mungkin tidak berfungsi di Safari atau Internet Explorer.

/*!
 * Dynamically changing favicons with JavaScript
 * Works in all A-grade browsers except Safari and Internet Explorer
 * Demo: http://mathiasbynens.be/demo/dynamic-favicons
 */

// HTML5™, baby! http://mathiasbynens.be/notes/document-head
document.head = document.head || document.getElementsByTagName('head')[0];

function changeFavicon(src) {
 var link = document.createElement('link'),
     oldLink = document.getElementById('dynamic-favicon');
 link.id = 'dynamic-favicon';
 link.rel = 'shortcut icon';
 link.href = src;
 if (oldLink) {
  document.head.removeChild(oldLink);
 }
 document.head.appendChild(link);
}

Anda kemudian akan menggunakannya sebagai berikut:

var btn = document.getElementsByTagName('button')[0];
btn.onclick = function() {
 changeFavicon('http://www.google.com/favicon.ico');
};

Singkirkan atau lihat demo .

Mathias Bynens
sumber
The Chrome bug tetap di Chrome 6 (dirilis September 10), sehingga hack Chrome sebenarnya tidak penting lagi - pada kenyataannya, saya akan sangat menyarankan tidak menggunakannya karena istirahat tombol maju.
josh3736
Bug Chrome mungkin sudah diperbaiki, tetapi rusak lagi di 14.0.835.187.
danorton
The demo tidak bekerja untuk saya dengan Chrome 21 / WinXP.
Hugo
Demo tidak berfungsi untuk saya di Chrome 26 / Win7. document.head || document.head = document.getElementsByTagName('head')[0]; Uncaught ReferenceError: Invalid left-hand side in assignment
Patrick
2
Ini bekerja di semua browser yang saat ini didukung (IE 11, Edge, FF, dan Chrome) tidak dapat menguji dengan safari
Aaron
46

Jika Anda memiliki cuplikan HTML berikut:

<link id="favicon" rel="shortcut icon" type="image/png" href="favicon.png" />

Anda dapat mengubah favicon menggunakan Javascript dengan mengubah elemen HREF pada tautan ini, misalnya (dengan asumsi Anda menggunakan JQuery):

$("#favicon").attr("href","favicon2.png");

Anda juga dapat membuat elemen Canvas dan mengatur HREF sebagai ToDataURL () kanvas, seperti halnya Favicon Defender .

fserb
sumber
1
Saya pikir pada saat JS berjalan, browser sudah akan melihat tautan dan mencoba memuat favicon.png. Ini mungkin perlu dilakukan sisi server.
cao
Jika Anda tidak menggunakan JQuery, Anda dapat mengubah hrefatribut #faviconmenggunakan document.getElementById('favicon').setAttribute('href','favicon2.png') Mungkin Anda bisa menambahkannya ke posting Anda @ fserb?
johannchopin
37

Versi jQuery:

$("link[rel='shortcut icon']").attr("href", "favicon.ico");

atau bahkan lebih baik:

$("link[rel*='icon']").attr("href", "favicon.ico");

Versi vanilla JS:

document.querySelector("link[rel='shortcut icon']").href = "favicon.ico";

document.querySelector("link[rel*='icon']").href = "favicon.ico";
vorillaz
sumber
@ pkExec Kombinasi dari ini dan jawaban keparo di atas (jawaban yang dipilih) membuatnya bekerja di ff dan chrome untuk saya.
MrShmee
17

Pendekatan yang lebih modern:

const changeFavicon = link => {
  let $favicon = document.querySelector('link[rel="icon"]')
  // If a <link rel="icon"> element already exists,
  // change its href to the given link.
  if ($favicon !== null) {
    $favicon.href = link
  // Otherwise, create a new element and append it to <head>.
  } else {
    $favicon = document.createElement("link")
    $favicon.rel = "icon"
    $favicon.href = link
    document.head.appendChild($favicon)
  }
}

Anda kemudian dapat menggunakannya seperti ini:

changeFavicon("http://www.stackoverflow.com/favicon.ico")
Michał Perłakowski
sumber
11

Favicon dideklarasikan di tag kepala dengan sesuatu seperti:

<link rel="shortcut icon" type="image/ico" href="favicon.ico">

Anda harus bisa hanya memberikan nama ikon yang Anda inginkan di dalam data tampilan dan membuangnya ke tag kepala.

Jeff Sheldon
sumber
1
IIRC, bagaimanapun, beberapa browser (saya melihat ke arah Anda, IE) kadang-kadang tidak menghargai ini.
Matthew Schinckel
(Saya menemukan saya memiliki hasil yang lebih baik hanya memiliki file ikon di lokasi yang tepat, daripada tautan eksplisit).
Matthew Schinckel
9

Berikut beberapa kode yang saya gunakan untuk menambahkan dukungan favicon dinamis ke Opera, Firefox dan Chrome. Saya tidak bisa mengaktifkan IE atau Safari. Pada dasarnya Chrome memungkinkan favicon dinamis, tetapi hanya memperbaruinya ketika lokasi halaman (atau yang iframelain di dalamnya) berubah sejauh yang saya tahu:

var IE = navigator.userAgent.indexOf("MSIE")!=-1
var favicon = {
    change: function(iconURL) {
        if (arguments.length == 2) {
            document.title = optionalDocTitle}
        this.addLink(iconURL, "icon")
        this.addLink(iconURL, "shortcut icon")

        // Google Chrome HACK - whenever an IFrame changes location 
        // (even to about:blank), it updates the favicon for some reason
        // It doesn't work on Safari at all though :-(
        if (!IE) { // Disable the IE "click" sound
            if (!window.__IFrame) {
                __IFrame = document.createElement('iframe')
                var s = __IFrame.style
                s.height = s.width = s.left = s.top = s.border = 0
                s.position = 'absolute'
                s.visibility = 'hidden'
                document.body.appendChild(__IFrame)}
            __IFrame.src = 'about:blank'}},

    addLink: function(iconURL, relValue) {
        var link = document.createElement("link")
        link.type = "image/x-icon"
        link.rel = relValue
        link.href = iconURL
        this.removeLinkIfExists(relValue)
        this.docHead.appendChild(link)},

    removeLinkIfExists: function(relValue) {
        var links = this.docHead.getElementsByTagName("link");
        for (var i=0; i<links.length; i++) {
            var link = links[i]
            if (link.type == "image/x-icon" && link.rel == relValue) {
                this.docHead.removeChild(link)
                return}}}, // Assuming only one match at most.

    docHead: document.getElementsByTagName("head")[0]}

Untuk mengubah favicon, cukup favicon.change("ICON URL")gunakan yang di atas.

(kredit untuk http://softwareas.com/dynamic-favicons untuk kode saya berdasarkan ini.)

cryo
sumber
The Chrome bug tetap di Chrome 6 (dirilis September 10), sehingga hack Chrome sebenarnya tidak penting lagi - pada kenyataannya, saya akan sangat menyarankan tidak menggunakannya karena istirahat tombol maju.
josh3736
Chrome masih memiliki bug yang sama, meskipun dalam keadaan yang sedikit berbeda dari bug spesifik yang dicatat. code.google.com/p/chromium/issues/detail?id=99549
danorton
4

Saya akan menggunakan pendekatan Greg dan membuat handler kustom untuk favicon.ico Ini adalah handler (disederhanakan) yang berfungsi:

using System;
using System.IO;
using System.Web;

namespace FaviconOverrider
{
    public class IcoHandler : IHttpHandler
    {
    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "image/x-icon";
        byte[] imageData = imageToByteArray(context.Server.MapPath("/ear.ico"));
        context.Response.BinaryWrite(imageData);
    }

    public bool IsReusable
    {
        get { return true; }
    }

    public byte[] imageToByteArray(string imagePath)
    {
        byte[] imageByteArray;
        using (FileStream fs = new FileStream(imagePath, FileMode.Open, FileAccess.Read))
        {
        imageByteArray = new byte[fs.Length];
        fs.Read(imageByteArray, 0, imageByteArray.Length);
        }

        return imageByteArray;
    }
    }
}

Kemudian Anda dapat menggunakan penangan itu di bagian httpHandlers dari konfigurasi web di IIS6 atau menggunakan fitur 'Pemetaan Penangan' di IIS7.

Dan
sumber
1
Saya sebenarnya penasaran mengapa ini diturunkan? ini sebenarnya jawaban terbaik mengingat semua orang lain bergantung pada skrip yang mungkin tersedia atau tidak.
ethermal
1
@ethermal Karena sepertinya dinamis di sisi server. OP meminta dinamisme di sisi klien.
Alexis Wilke
3

Satu-satunya cara untuk membuat ini bekerja untuk IE adalah untuk membuat server web Anda untuk memperlakukan permintaan * .ico untuk memanggil bahasa skrip sisi server Anda (PHP, .NET, dll). Juga siapkan * .ico untuk mengarahkan ulang ke satu skrip dan minta skrip ini mengirimkan file favicon yang benar. Saya yakin masih akan ada beberapa masalah yang menarik dengan cache jika Anda ingin dapat bangkit bolak-balik di browser yang sama antara favicon yang berbeda.

Greg
sumber
3

Ada solusi baris tunggal untuk mereka yang menggunakan jQuery:

$("link[rel*='icon']").prop("href",'https://www.stackoverflow.com/favicon.ico');
Pepelegal
sumber
3

Atau jika Anda menginginkan emotikon :)

var canvas = document.createElement("canvas");
canvas.height = 64;
canvas.width = 64;

var ctx = canvas.getContext("2d");
ctx.font = "64px serif";
ctx.fillText("☠️", 0, 64); 

$("link[rel*='icon']").prop("href", canvas.toDataURL());

Alat Peraga untuk https://koddsson.com/posts/emoji-favicon/

maksimal4ever
sumber
2

Menurut WikiPedia , Anda dapat menentukan file favicon mana yang akan dimuat menggunakan linktag di headbagian ini, dengan parameter rel="icon".

Sebagai contoh:

 <link rel="icon" type="image/png" href="/path/image.png">

Saya membayangkan jika Anda ingin menulis beberapa konten dinamis untuk panggilan itu, Anda akan memiliki akses ke cookie sehingga Anda dapat mengambil informasi sesi Anda seperti itu dan menyajikan konten yang sesuai.

Anda mungkin tidak menyukai format file (IE dilaporkan hanya mendukung format .ICO itu, sementara kebanyakan orang lain mendukung gambar PNG dan GIF) dan mungkin masalah caching, baik pada browser dan melalui proxy. Ini mungkin karena tujuan asli favicon, khususnya, untuk menandai bookmark dengan logo mini situs.

ahli statika
sumber
lebih dari itu. stackoverflow.com/a/45301651/661584 faqs / info di situs generator akan mengejutkan Anda - ada banyak hal dalam hal ini.
MemeDeveloper
3
Web berubah banyak dalam 9 tahun.
Statika
2

Ya, sangat mungkin

  • Gunakan querystring setelah favicon.ico (dan tautan file lainnya - lihat tautan jawaban di bawah)
  • Pastikan server merespons "someUserId" dengan file gambar yang benar (yang bisa berupa aturan perutean statis , atau kode sisi server dinamis ).

misalnya

<link rel="shortcut icon" href="/favicon.ico?userId=someUserId">

Maka bahasa sisi server apa pun / kerangka kerja yang Anda gunakan harus dapat dengan mudah menemukan file berdasarkan userId dan menyajikannya sebagai tanggapan atas permintaan itu .

Tetapi untuk melakukan favicons dengan benar (sebenarnya ini adalah subjek yang sangat kompleks ) silakan lihat jawabannya di sini https://stackoverflow.com/a/45301651/661584

Jauh lebih mudah daripada mengerjakan sendiri semua detailnya.

Nikmati.

Pengembang Meme
sumber
Ya, tautannya bagus. Saya berpikir bahwa alasan utama mengapa jawaban ini tidak berfungsi di IE adalah karena mereka tidak menggunakan ikon default itu <link>, tetapi mencari apple-touch-iconatau beberapa varian lainnya.
Alexis Wilke
1

Saya menggunakan favico.js dalam proyek saya.

Hal ini memungkinkan untuk mengubah favicon ke berbagai bentuk yang telah ditentukan dan juga yang kustom.

Secara internal itu digunakan canvasuntuk rendering dan base64URL data untuk pengkodean ikon.

Perpustakaan juga memiliki fitur-fitur yang bagus: lencana ikon dan animasi; konon, Anda bahkan dapat melakukan streaming video webcam ke ikon :)

Oscar Nevarez
sumber
Tautan dan pustaka sangat berguna, harap berikan deskripsi cara kerjanya sehingga ini juga menjadi jawaban yang valid untuk pertanyaan seperti yang dinyatakan.
Dima Tisnek
1
Terima kasih @DimaTisnek. Saya telah memperbarui jawaban saya.
Oscar Nevarez
0

Saya menggunakan fitur ini setiap saat ketika mengembangkan situs ... jadi saya dapat melihat sekilas tab mana yang memiliki lokal, dev atau prod berjalan di dalamnya.

Sekarang Chrome mendukung favicon SVG itu membuatnya jauh lebih mudah.

Skrip Tampermonkey

Pandang sebentar di https://gist.github.com/elliz/bb7661d8ed1535c93d03afcd0609360f untuk skrip tampermonkey yang menunjuk ke situs demo yang saya buang di https://elliz.github.io/svg-favicon/

Kode dasar

Adaptasi ini dari jawaban lain ... dapat ditingkatkan tetapi cukup baik untuk kebutuhan saya.

(function() {
    'use strict';

    // play with https://codepen.io/elliz/full/ygvgay for getting it right
    // viewBox is required but does not need to be 16x16
    const svg = `
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
      <circle cx="8" cy="8" r="7.2" fill="gold" stroke="#000" stroke-width="1" />
      <circle cx="8" cy="8" r="3.1" fill="#fff" stroke="#000" stroke-width="1" />
    </svg>
    `;

    var favicon_link_html = document.createElement('link');
    favicon_link_html.rel = 'icon';
    favicon_link_html.href = svgToDataUri(svg);
    favicon_link_html.type = 'image/svg+xml';

    try {
        let favicons = document.querySelectorAll('link[rel~="icon"]');
        favicons.forEach(function(favicon) {
            favicon.parentNode.removeChild(favicon);
        });

        const head = document.getElementsByTagName('head')[0];
        head.insertBefore( favicon_link_html, head.firstChild );
    }
    catch(e) { }

    // functions -------------------------------
    function escapeRegExp(str) {
        return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
    }

    function replaceAll(str, find, replace) {
        return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
    }

    function svgToDataUri(svg) {
        // these may not all be needed - used to be for uri-encoded svg in old browsers
        var encoded = svg.replace(/\s+/g, " ")
        encoded = replaceAll(encoded, "%", "%25");
        encoded = replaceAll(encoded, "> <", "><"); // normalise spaces elements
        encoded = replaceAll(encoded, "; }", ";}"); // normalise spaces css
        encoded = replaceAll(encoded, "<", "%3c");
        encoded = replaceAll(encoded, ">", "%3e");
        encoded = replaceAll(encoded, "\"", "'"); // normalise quotes ... possible issues with quotes in <text>
        encoded = replaceAll(encoded, "#", "%23"); // needed for ie and firefox
        encoded = replaceAll(encoded, "{", "%7b");
        encoded = replaceAll(encoded, "}", "%7d");
        encoded = replaceAll(encoded, "|", "%7c");
        encoded = replaceAll(encoded, "^", "%5e");
        encoded = replaceAll(encoded, "`", "%60");
        encoded = replaceAll(encoded, "@", "%40");
        var dataUri = 'data:image/svg+xml;charset=UTF-8,' + encoded.trim();
        return dataUri;
    }

})();

Cukup masukkan SVG Anda sendiri (mungkin dibersihkan dengan SVGOMG Jake Archibald jika Anda menggunakan alat) ke dalam const di bagian atas. Pastikan persegi (menggunakan atribut viewBox) dan Anda siap melakukannya.

Ruskin
sumber