Dynamiczna zmiana strony favicon

347

Mam aplikację internetową oznaczoną marką według aktualnie zalogowanego użytkownika. Chciałbym zmienić favicon strony na logo prywatnej marki, ale nie mogę znaleźć żadnego kodu ani żadnych przykładów tego, jak zrobić to. Czy ktoś wcześniej to zrobił?

Wyobrażam sobie, że mam tuzin ikon w folderze, a odniesienie do pliku favicon.ico, którego należy użyć, jest generowane dynamicznie wraz ze stroną HTML. Myśli?

SqlRyan
źródło
41
W favicon jest gra zręcznościowa .
Corey Trager,
Pamiętaj, że dynamiczna implementacja favicon Chrome jest wadliwa i zużywa zbyt dużo procesora. Zobacz code.google.com/p/chromium/issues/detail?id=121333
przeglądanie
6
Link do gry zręcznościowej został zmieniony. To jest poprawne.
Basil
Zobacz stackoverflow.com/questions/6296574/…, jak dynamicznie aktualizować favicon, rysując na obrazie szablonu szablon z płótnem.
obsłużyć
1
Mały błąd w przykładzie kodu podanym w zaakceptowanej odpowiedzi. Nie mam wystarczającej oceny reputacji, aby komentować odpowiedzi, dlatego piszę tutaj. W ostatnim wierszu zamieniono nawiasy:} ()); należy przeczytać}) (); Byłoby miło, gdyby przykład kodu został zaktualizowany, ponieważ najprawdopodobniej jest on kopiowany i wklejany przez innych.
Goran W

Odpowiedzi:

396

Dlaczego nie?

(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 powinien być z tym fajny.

edytowane w celu poprawnego zastąpienia istniejących ikon

keparo
źródło
2
Myślę, że jest to bliskie temu, czego szukam, ale jak uzyskać odpowiedni HREF z bazy danych. Przypuszczam, że będę musiał przeprowadzić wyszukiwanie serwera z javascript, ale nie chcę, żeby to się skomplikowało. Dzięki za wskazówkę.
SqlRyan
34
Ponieważ i tak to nie działa w IE, możesz usunąć shortcutz relatrybutu. shortcutjest niepoprawną powiązaną z IE relacją łącza!
Mathias Bynens,
8
Możesz równie łatwo poszukać istniejącego linku favicon i zaktualizować go lub zastąpić.
keparo
5
Google może dać ci ulubioną
kirb
5
Czy wpisanie tego w konsoli Javascript w Chrome powinno działać? Nie mogę zmusić go do zmiany ulubionych na różnych stronach w ten sposób.
powerj1984
88

Oto kod, który działa w Firefox, Opera i Chrome (w przeciwieństwie do wszystkich innych odpowiedzi tutaj zamieszczonych). Oto inna wersja kodu, która działa również w IE11 . Poniższy przykład może nie działać w przeglądarce Safari lub 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);
}

Następnie użyjesz go w następujący sposób:

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

Odsuń się lub obejrzyj wersję demo .

Mathias Bynens
źródło
Bug Chrome została ustalona w Chrome 6 (wydany 10 września), więc hack Chrome nie jest już naprawdę konieczne - w rzeczywistości, bym zdecydowanie wskazują nie jest używany, ponieważ łamie przycisk do przodu.
josh3736
Błąd Chrome mógł zostać naprawiony, ale został ponownie uszkodzony w 14.0.835.187.
danorton,
Demo nie działa dla mnie z Chrome 21 / WinXP.
Hugo,
Demo nie działa dla mnie w Chrome 26 / Win7. document.head || document.head = document.getElementsByTagName('head')[0]; Uncaught ReferenceError: Invalid left-hand side in assignment
Patrick,
2
Działa to we wszystkich obecnie obsługiwanych przeglądarkach (IE 11, Edge, FF i Chrome) niezdolnych do testowania z safari
Aaron
46

Jeśli masz następujący fragment kodu HTML:

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

Możesz zmienić ikonę ulubionych za pomocą Javascript, zmieniając element HREF w tym linku, na przykład (zakładając, że używasz JQuery):

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

Możesz także utworzyć element Canvas i ustawić HREF jako ToDataURL () płótna, podobnie jak robi to Favicon Defender .

fserb
źródło
1
Myślałem, że zanim uruchomi się JS, przeglądarka już zobaczy link i spróbuje załadować favicon.png. Może to wymagać wykonania po stronie serwera.
cHao
Jeśli nie korzystasz z JQuery, możesz zmienić hrefatrybut #faviconużywania. document.getElementById('favicon').setAttribute('href','favicon2.png') Może możesz dodać go do swojego posta @fserb?
johannchopin
37

Wersja jQuery:

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

lub nawet lepiej:

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

Wersja Vanilla JS:

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

document.querySelector("link[rel*='icon']").href = "favicon.ico";
Vorillaz
źródło
@pkExec Połączenie tego i powyższej odpowiedzi Keparo (wybrana odpowiedź) sprawiło, że działała zarówno dla FF, jak i dla Chrome.
MrShmee,
17

Bardziej nowoczesne podejście:

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)
  }
}

Następnie możesz użyć go w następujący sposób:

changeFavicon("http://www.stackoverflow.com/favicon.ico")
Michał Perłakowski
źródło
11

Favicon jest zadeklarowany w tagu head za pomocą czegoś takiego:

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

Powinieneś być w stanie przekazać nazwę ikony, którą chcesz wraz z danymi widoku i wrzucić ją do tagu head.

Jeff Sheldon
źródło
1
IIRC jednak niektóre przeglądarki (patrzę w twoją stronę, IE) tak naprawdę czasem tego nie szanują.
Matthew Schinckel
(Stwierdziłem, że uzyskałem lepsze wyniki po prostu umieszczając plik ikony we właściwej lokalizacji, a nie wyraźny link).
Matthew Schinckel,
9

Oto kod, którego używam, aby dodać obsługę dynamicznego favicon do Opera, Firefox i Chrome. Nie mogłem jednak uruchomić IE ani Safari. Zasadniczo Chrome zezwala na dynamiczne ikony ulubionych, ale aktualizuje je tylko wtedy, gdy położenie strony (lub iframeitp. W nim) zmienia się, o ile wiem:

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]}

Aby zmienić ulubione, po prostu favicon.change("ICON URL")skorzystaj z powyższego.

(podziękowania dla http://softwareas.com/dynamic-favicons za kod, na którym ja bazowałem.)

krio
źródło
Bug Chrome została ustalona w Chrome 6 (wydany 10 września), więc hack Chrome nie jest już naprawdę konieczne - w rzeczywistości, bym zdecydowanie wskazują nie jest używany, ponieważ łamie przycisk do przodu.
josh3736
Chrome nadal ma ten sam błąd, choć w nieco innych okolicznościach niż określony błąd. code.google.com/p/chromium/issues/detail?id=99549
danorton
4

Chciałbym użyć podejścia Grega i stworzyć niestandardowy moduł obsługi dla favicon.ico Oto (uproszczony) moduł obsługi, który działa:

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;
    }
    }
}

Następnie możesz użyć tego modułu obsługi w sekcji httpHandlers konfiguracji sieci w IIS6 lub użyć funkcji „Mapowania modułu obsługi” w IIS7.

Dan
źródło
1
właściwie jestem ciekawy, dlaczego to zostało odrzucone? jest to właściwie najlepsza odpowiedź, biorąc pod uwagę, że inni polegają na skryptach, które mogą być niedostępne.
eteryczny
1
@ethermal Ponieważ wygląda na dynamiczny po stronie serwera. OP prosiło o dynamizm po stronie klienta.
Alexis Wilke,
3

Jedynym sposobem, aby ta funkcja działała w przeglądarce IE, jest ustawienie serwera WWW do obsługi żądań * .ico w celu wywołania języka skryptowego po stronie serwera (PHP, .NET itp.). Skonfiguruj również * .ico, aby przekierować do jednego skryptu i aby ten skrypt dostarczył poprawny plik favicon. Jestem pewien, że nadal będą jakieś interesujące problemy z pamięcią podręczną, jeśli chcesz mieć możliwość odbijania się w tej samej przeglądarce między różnymi ikonami ulubionych.

Greg
źródło
3

Jest jedno rozwiązanie dla tych, którzy korzystają z jQuery:

$("link[rel*='icon']").prop("href",'https://www.stackoverflow.com/favicon.ico');
Pepelegal
źródło
3

Lub jeśli chcesz 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());

Rekwizyty do https://koddsson.com/posts/emoji-favicon/

max4ever
źródło
2

Zgodnie z WikiPedia , możesz określić, który plik favicon ma zostać załadowany za pomocą linkznacznika w headsekcji, z parametrem rel="icon".

Na przykład:

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

Wyobrażam sobie, że gdybyś chciał napisać dynamiczną treść dla tego połączenia, miałbyś dostęp do plików cookie, aby w ten sposób uzyskać informacje o sesji i przedstawić odpowiednią treść.

Możesz nie zgadzać się z formatami plików (IE podobno obsługuje tylko format .ICO, podczas gdy większość innych obsługuje obrazy PNG i GIF) i możliwe problemy z buforowaniem, zarówno w przeglądarce, jak i przez serwery proxy. Stałoby się tak z powodu pierwotnej uwagi favicon, a konkretnie do oznaczania zakładki mini-logo strony.

staticsan
źródło
o wiele więcej niż to. stackoverflow.com/a/45301651/661584 najczęściej zadawane pytania / informacje na stronie generatora zaskoczą cię - jest wiele w tym temacie.
MemeDeveloper,
3
Sieć bardzo się zmienia w ciągu 9 lat.
staticsan
2

Tak, całkowicie możliwe

  • Użyj kwerendy po favicon.ico (i innych linków do plików - patrz link poniżej)
  • Po prostu upewnij się, że serwer odpowiada na „someUserId” poprawnym plikiem obrazu (mogą to być statyczne reguły routingu lub dynamiczny kod po stronie serwera).

na przykład

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

W takim razie, niezależnie od używanego języka / frameworku po stronie serwera , powinno być łatwo znaleźć plik na podstawie userId i podać go w odpowiedzi na to żądanie .

Ale aby właściwie robić favikony (to naprawdę bardzo złożony temat ), zobacz odpowiedź tutaj https://stackoverflow.com/a/45301651/661584

O wiele łatwiej niż samodzielne wypracowanie wszystkich szczegółów.

Cieszyć się.

MemeDeveloper
źródło
Tak, link jest dobry. Myślę, że głównym powodem, dla którego te odpowiedzi nie działają w IE, jest to, że nie używają tej domyślnej ikony <link>, ale zamiast tego szukają apple-touch-iconinnego wariantu.
Alexis Wilke,
1

Używam favico.js w moich projektach.

Pozwala zmienić favicon do szeregu predefiniowanych kształtów, a także niestandardowych.

Wewnętrznie używa canvasdo renderowania i base64adresu URL danych do kodowania ikon.

Biblioteka ma również ładne funkcje: znaczki ikon i animacje; podobno możesz nawet przesyłać strumieniowo wideo z kamery internetowej do ikony :)

Oscar Nevarez
źródło
Link i biblioteka są bardzo przydatne, proszę opisać, jak to działa, aby stała się również prawidłową odpowiedzią na zadane pytanie.
Dima Tisnek
1
Dzięki @DimaTisnek. Zaktualizowałem swoją odpowiedź.
Oscar Nevarez
0

Korzystam z tej funkcji przez cały czas przy tworzeniu witryn ... dzięki czemu mogę szybko zobaczyć, która karta ma działającą lokalnie, programistę lub prod.

Teraz, gdy Chrome obsługuje ulubione SVG, sprawia, że ​​jest to o wiele łatwiejsze.

Skrypt Tampermonkey

Popatrz na https://gist.github.com/elliz/bb7661d8ed1535c93d03afcd0609360f w celu uzyskania skryptu tampermonkey, który wskazuje na stronę demo, którą podrzuciłem https://elliz.github.io/svg-favicon/

Kod podstawowy

Zaadaptowałem to z innej odpowiedzi ... może być ulepszone, ale wystarczająco dobre dla moich potrzeb.

(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;
    }

})();

Po prostu włóż własny plik SVG (być może wyczyszczony za pomocą SVGOMG Jake'a Archibalda, jeśli używasz narzędzia) w const na górze. Upewnij się, że jest kwadratowy (używając atrybutu viewBox) i możesz już iść.

Ruskin
źródło