Динамическое изменение значка веб-сайта

У меня есть веб-приложение, созданное в соответствии с именем пользователя, который в данный момент вошел в систему. Я хотел бы изменить значок страницы на логотип частной марки, но я не могу найти код или примеры того, как сделать это. Кто-нибудь успешно делал это раньше?

Я представляю, как в папке есть дюжина значков, и ссылка на то, какой файл favicon.ico использовать, просто генерируется динамически вместе со страницей HTML. Мысли?

Обратите внимание, что реализация динамического значка в Chrome содержит ошибки и использует слишком много ЦП. См. code.google.com/p/chromium/issues/detail?id=121333

brillout 30.04.2012 21:59

В значке есть аркадная игра.

Corey Trager 04.11.2008 07:16

Изменилась ссылка на аркадную игру. Этот - правильный.

Basil 01.06.2016 16:24

См. stackoverflow.com/questions/6296574/… о том, как динамически обновлять значок, рисуя поверх изображения шаблона с помощью холста.

handle 20.08.2016 12:37

Небольшая ошибка в примере кода, приведенном в принятом ответе. У меня недостаточно очков репутации, чтобы комментировать ответы, поэтому я пишу здесь. В последней строке круглые скобки поменяны местами:} ()); должен прочесть })(); Было бы хорошо, если бы пример кода обновился, поскольку он, скорее всего, скопирован и вставлен другими.

Goran W 21.04.2017 14:27

@CoreyTrager URL изменен: p01.org/defender_of_the_favicon

Clément 05.10.2017 17:37
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
389
6
210 498
16
Перейти к ответу Данный вопрос помечен как решенный

Ответы 16

Значок объявляется в теге заголовка примерно так:

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

Вы должны иметь возможность просто передать имя нужного значка в данных представления и добавить его в тег заголовка.

IIRC, однако, некоторые браузеры (я смотрю в вашу сторону, IE) иногда действительно не уважают это.

Matthew Schinckel 04.11.2008 07:22

(Я обнаружил, что у меня были лучшие результаты, если бы файл значка был в правильном месте, а не явная ссылка).

Matthew Schinckel 04.11.2008 07:23
Ответ принят как подходящий

Почему нет?

var link = document.querySelector("link[rel~='icon']");
if (!link) {
    link = document.createElement('link');
    link.rel = 'icon';
    document.getElementsByTagName('head')[0].appendChild(link);
}
link.href = 'https://stackoverflow.com/favicon.ico';

Я думаю, это близко к тому, что я ищу, но как мне получить соответствующий HREF из базы данных. Полагаю, мне придется выполнить поиск сервера с помощью javascript, но я не хочу, чтобы это становилось слишком сложным. Спасибо за совет.

SqlRyan 04.11.2008 07:57

Конечно, вы всегда можете найти их в базе данных или файловой системе. Если их всего несколько, вы можете просто жестко закодировать массив строк.

keparo 04.11.2008 08:26

Поскольку это в любом случае не работает в IE, вы можете удалить shortcut из атрибута rel. shortcut - это недопустимая ссылка на проприетарную связь IE!

Mathias Bynens 07.06.2010 16:45

Вы можете так же легко найти существующую ссылку на значок и обновить или заменить ее.

keparo 01.04.2011 03:51

Google может предоставить вам значок сайта, используя этот URL-адрес, заменив stackoverflow.com на нужный домен: s2.googleusercontent.com/s2/favicons?domain=stackoverflow.co‌ m

kirb 03.10.2011 08:20

+1 потому что это работает! Но вы должны добавить к нему унарный оператор, например + или - или что-то подобное, +function(){/*CHANGE ICON*/}(), или поместить объект функции между двумя (), например (function(){/*CHANGE ICON*/})(), чтобы он выполнялся ...;)

Cipi 12.10.2011 13:57

Следует ли вводить это в консоль Javascript в Chrome? Я не могу заставить его таким образом менять значки на разных сайтах.

powerj1984 25.05.2013 05:46

@keparo нет, ты не можешь. По крайней мере, Firefox игнорирует изменение href в теге ссылки, которое не влияет на отображаемый значок.

Andy 05.11.2013 18:42

@ Andy: Это было возможно 4 ноября 2008 года, но это было пять лет и один день назад. Пробег может варьироваться в зависимости от браузера, а также от таких факторов, как заменяете ли вы существующее значение или применяете новый элемент ссылки и т. д.

keparo 06.11.2013 09:15

@Andy Firefox не поддерживает изменение href (он не будет обновляться), но он поддерживает удаление старого узла ссылки и добавление нового. Вы можете cloneNode () старый, изменить href, а затем replaceChild () его, в соответствии с ответом Матиаса Биненса.

jishi 18.11.2013 11:29

Замечание для всех, кто пробует это в Firefox, как и я: вы не можете использовать URL-адрес file: // для значка (изменив его в Grasemonkey). Вероятно, крайний случай для большинства людей и довольно очевидный в ретроспективе (проблемы безопасности), но мне потребовалось время, чтобы понять, что это была моя проблема.

Tarka 01.05.2014 23:05

Если у вас есть следующий фрагмент HTML:

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

Вы можете изменить значок с помощью Javascript, например, изменив элемент HREF в этой ссылке (при условии, что вы используете JQuery):

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

Вы также можете создать элемент Canvas и установить HREF как ToDataURL () холста, как это делает Фавикон Защитник.

Я думаю, что к моменту запуска JS браузер уже увидит ссылку и попытается загрузить favicon.png. Возможно, это потребуется сделать на стороне сервера.

cHao 13.07.2012 18:42

Если вы не используете JQuery, вы можете изменить атрибут href для #favicon с помощью document.getElementById('favicon').setAttribute('href','favi‌​con2.png'). Может быть, вы можете добавить его в свой пост @fserb?

johannchopin 22.04.2020 15:53

Согласно Википедия, вы можете указать, какой файл значка загружать, используя тег link в разделе head с параметром rel = "icon".

Например:

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

Я предполагаю, что если бы вы захотели написать какой-то динамический контент для этого вызова, у вас был бы доступ к файлам cookie, чтобы вы могли таким образом извлекать информацию о сеансе и представлять соответствующий контент.

Вы можете столкнуться с проблемами форматов файлов (IE, как сообщается, поддерживает только формат .ICO, в то время как большинство остальных поддерживает изображения PNG и GIF) и, возможно, проблем с кешированием как в браузере, так и через прокси-серверы. Это может быть связано с первоначальным назначением значка, в частности, для пометки закладки мини-логотипом сайта.

гораздо больше, чем это. stackoverflow.com/a/45301651/661584 ответы на часто задаваемые вопросы / информация на сайте генератора вас удивят - на эту тему много всего.

MemeDeveloper 25.07.2017 14:40

Интернет сильно изменился за 9 лет.

staticsan 26.07.2017 02:56

Вот код, который я использую для добавления поддержки динамических значков в Opera, Firefox и Chrome. Однако я не мог заставить работать IE или Safari. В основном Chrome позволяет использовать динамические значки, но он обновляет их только тогда, когда местоположение страницы (или iframe и т. д. В ней) изменяется, насколько я могу судить:

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

Чтобы изменить значки, просто перейдите на favicon.change("ICON URL"), используя указанное выше.

(кредиты http://softwareas.com/dynamic-favicons за код, на котором я основал это.)

Ошибка Chrome был исправлен в Chrome 6 (выпущен 10 сентября), поэтому взлом Chrome больше не нужен - на самом деле, я настоятельно рекомендую не использовать его, поскольку он ломает кнопку вперед.

josh3736 29.04.2011 05:17

В Chrome все еще есть та же ошибка, хотя и при несколько иных обстоятельствах, чем указанная конкретная ошибка. code.google.com/p/chromium/issues/detail?id=99549

danorton 08.10.2011 04:41

Вот код, который работает в Firefox, Opera и Chrome (в отличие от любого другого ответа, опубликованного здесь). Вот и другой демонстрация кода, работающего в IE11. Следующий пример может не работать в Safari или 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);
}

Затем вы использовали бы его следующим образом:

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

Разветвляйся или посмотреть демо.

Ошибка Chrome был исправлен в Chrome 6 (выпущен 10 сентября), поэтому взлом Chrome больше не нужен - на самом деле, я настоятельно рекомендую не использовать его, поскольку он ломает кнопку вперед.

josh3736 29.04.2011 05:17

Ошибка Chrome могла быть исправлена, но она снова сломалась в 14.0.835.187.

danorton 08.10.2011 01:05

демонстрация у меня не работает с Chrome 21 / WinXP.

Hugo 08.09.2012 13:47

Демоверсия у меня не работает в Chrome 26 / Win7. document.head || document.head = document.getElementsByTagName('head')[0];Uncaught ReferenceError: Invalid left-hand side in assignment

Patrick 08.05.2013 00:20

Есть ли причина, по которой это не сработает с использованием строки изображения в кодировке base 64 в качестве источника?

powerj1984 25.05.2013 07:11

@ powerj1984 URL-адреса data не поддерживаются в старом IE. Также обратите внимание, что IE поддерживает только значки .ico.

Mathias Bynens 26.05.2013 19:35

Это работает во всех поддерживаемых в настоящее время браузерах (IE 11, Edge, FF и Chrome), которые невозможно протестировать с помощью Safari.

Aaron 02.02.2016 23:55

@MathiasBynens Можно ли динамически установить значок для PDF-файла, который открывается в новой вкладке?

SE_User 13.03.2017 09:05

Ваша демонстрация не работает, вероятно, из-за http to google вместо https

mplungjan 10.02.2019 09:54

@mplungjan Ого, это старая демка! Зафиксированный.

Mathias Bynens 18.02.2019 19:56

Единственный способ сделать это для IE - настроить ваш веб-сервер на обработку запросов * .ico для вызова вашего серверного языка сценариев (PHP, .NET и т. д.). Также настройте * .ico для перенаправления на один скрипт, чтобы этот скрипт доставил правильный файл значка. Я уверен, что по-прежнему будут возникать некоторые интересные проблемы с кешем, если вы хотите иметь возможность переходить в одном браузере между разными значками.

Я бы использовал подход Грега и сделал бы собственный обработчик для favicon.ico. Вот (упрощенный) обработчик, который работает:

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

Затем вы можете использовать этот обработчик в разделе httpHandlers веб-конфигурации в IIS6 или использовать функцию «Сопоставления обработчиков» в IIS7.

Мне вообще интересно, почему это было отклонено? на самом деле это лучший ответ, учитывая, что все остальные полагаются на скрипты, которые могут быть или не быть доступны.

ethermal 20.02.2015 21:04

@ethermal Потому что это выглядит динамически на стороне сервера. OP просил динамизма на стороне клиента.

Alexis Wilke 25.08.2018 05:27

Версия jQuery:

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

или даже лучше:

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

Версия Vanilla JS:

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

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

@pkExec Комбинация этого и ответа keparo выше (выбранный ответ) заставила меня работать как в ff, так и в chrome.

MrShmee 20.02.2015 19:25

Более современный подход:

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

Затем вы можете использовать его так:

changeFavicon("http://www.stackoverflow.com/favicon.ico")

Да вполне возможно

  • Используйте Строка запроса после favicon.ico (и других ссылок на файлы - см. ссылку для ответа ниже)
  • Просто убедитесь, что сервер отвечает на someUserId с помощью правильный файл изображения (это могут быть правила маршрутизации статический или динамичный серверный код).

например

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

Тогда любой язык / фреймворк на стороне сервера, который вы используете, легко сможет найти файл на основе userId и подать его в ответ на этот запрос.

Но чтобы правильно делать фавиконы (на самом деле это сложная тема В самом деле), пожалуйста, смотрите ответ здесь https://stackoverflow.com/a/45301651/661584

Намного проще, чем проработать все детали самостоятельно.

Наслаждаться.

Да, ссылка хорошая. Я думаю, что основная причина, по которой эти ответы не работают в IE, заключается в том, что они не используют значок <link> по умолчанию, а вместо этого ищут apple-touch-icon или какой-либо другой такой вариант.

Alexis Wilke 25.08.2018 05:32

В своих проектах я использую favico.js.

Это позволяет изменить значок на ряд предопределенных форм, а также на пользовательские.

Внутри он использует canvas для рендеринга и URL данных base64 для кодирования значков.

В библиотеке также есть приятные функции: значки значков и анимация; якобы вы даже можете транслировать видео с веб-камеры на значок :)

Ссылка и библиотека очень полезны, пожалуйста, опишите, как это работает, чтобы это также стало действительным ответом на поставленный вопрос.

Dima Tisnek 26.02.2019 07:55

Спасибо @DimaTisnek. Я обновил свой ответ.

Oscar Nevarez 26.02.2019 18:32

Для тех, кто использует jQuery, есть однострочное решение:

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

Или, если хотите смайлик :)

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

Реквизит к https://koddsson.com/posts/emoji-favicon/

Я использую эту функцию все время при разработке сайтов ... поэтому я могу сразу увидеть, на какой вкладке работают локальные, dev или prod.

Теперь, когда Chrome поддерживает значки SVG, это значительно упрощает задачу.

Скрипт Tampermonkey

Посмотрите на https://gist.github.com/elliz/bb7661d8ed1535c93d03afcd0609360f скрипт tampermonkey, который указывает на демонстрационный сайт, который я забросил на https://elliz.github.io/svg-favicon/

Базовый код

Адаптировал это из другого ответа ... можно улучшить, но достаточно для моих нужд.

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

})();

Просто вставьте свой собственный SVG (возможно, очищенный с помощью SVGOMG Джейка Арчибальда, если вы используете инструмент) в константу вверху. Убедитесь, что он квадратный (используя атрибут viewBox), и все готово.

@flyingsheep, потому что он слишком жадный. Я хочу кодировать только те глифы, которые проблематичны в некоторых браузерах. С указанным выше подмножеством вывод становится более читаемым и редактируемым человеком. Список, приведенный выше, может быть устаревшим, поскольку нам не нужно беспокоиться о более старом IE. В последнее время не тестировал.

Ruskin 24.08.2020 13:21

Вот фрагмент, позволяющий сделать значок смайликом или текстом. Он работает в консоли, когда я нахожусь в stackoverflow.

function changeFavicon(text) {
  const canvas = document.createElement('canvas');
  canvas.height = 64;
  canvas.width = 64;
  const ctx = canvas.getContext('2d');
  ctx.font = '64px serif';
  ctx.fillText(text, 0, 64);

  const link = document.createElement('link');
  const oldLinks = document.querySelectorAll('link[rel = "shortcut icon"]');
  oldLinks.forEach(e => e.parentNode.removeChild(e));
  link.id = 'dynamic-favicon';
  link.rel = 'shortcut icon';
  link.href = canvas.toDataURL();
  document.head.appendChild(link);
}

changeFavicon('❤️');

Другие вопросы по теме