Создание динамических пользовательских стилей

5 Окт
2011

Каждый день — новый цветВсем привет! Вы, наверное, знаете что такое пользовательские стили. Как правило, создатели наших любимых сайтов не балуют нас разнообразием оформления и богатством красок. Поэтому если привычное оформление сайта надоело, на помощь приходят эти самые пользовательские стили. Обратная сторона медали — выбранная тема тоже быстро приедается. Сейчас я расскажу, как создать динамический пользовательский стиль, который каждый день красит сайт в случайный цвет. Для примера возьму сайт ВКонтакте. Динамический стиль будет состоять всего из одной инструкции:
@import url("http://example.com/dynamic_style.css");
Эта команда импортирует стиль с внешнего сайта. Фишка в том, что этот внешний стиль будет загружаться каждый раз при перезапуске браузера. Как вы уже догадались, этот файл будет динамически генерироваться сервером. Для начала напишем заготовку для стиля. Для экономии ресурсов я разбил стиль на 2 части: статическую и динамическую. Статическая часть содержит полупрозрачные изображения в формате base64(чтобы не нагружать сервер лишними запросами). Она также будет подгружаться инструкцией @import. Динамическую часть будет выдавать скрипт на лету. Скоро сказка сказывается, да не скоро дело делается. С болванками пришлось порядком повозиться. Я не мастер фотошопа, поэтому не буду описывать процесс создания полупрозрачных изображений, наверняка вы справитесь не хуже меня. Вот наконец заготовка динамической части готова. Выглядит она примерно так:

/* Подключаем статическую часть */
@import url("http://s.gmjs.ru/css/imports/chameleon/static.css");

/* ... */

#pageHeader .header_back, #pageHeader .header_left{
  background-color:%main% !important;
}

 #vkontakte .fSub, #vkontakte .activePad{
  background-color:%l2%  !important
}

#vkontakte #profileActions a{
  border-color:%l1% !important;
}

/* ... */
Теперь осталось написать скрипт. Он должен генерировать случайный цвет (в различных градациях), подставлять цвета в код темы и возвращать результат пользователю. В качестве серверной платформы я выбрал Google Apps. При нагрузке до 100 запросов в секунду суточная норма ресурсов расходуется на 10-20%, работает быстро, денег не просит. Гораздо эффективнее было бы сделать статический файл со стилем и периодически его обновлять. Но, к сожалению, в Google App Engine нет доступа на запись к файловой системе. Код скрипта:
import random
import math
import string
import colorsys

from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app


def readFile():  
  fh = open('color.css')
  return fh.read()

def lighten(arr,val):
  ret=[int(math.floor((1-val)*color+val*255)) for color in arr]
  return ret

def colorstr(arr):
  ret=" rgb("+",".join(["%s" % col for col in arr])+") "
  return ret  
  
def colorhex(arr):
  colval=arr[0]*256*256+arr[1]*256+arr[2]  
  return "%s" % hex(colval)[2:] 


def getRandomColorRGB(min=115,max=240):
  svpart = random.randint(min,max)
  return  [int(round(col*255)) for col in colorsys.hsv_to_rgb(random.randint(0,360)/360.0, svpart/255.0, svpart/255.0)]
  
def getCSS(maincolor=getRandomColorRGB()):
  color_main=maincolor
  color_dark=[int(math.floor(val*0.95)) for val in color_main]
  color_l1=lighten(color_main,0.85)
  color_l2=lighten(color_main,0.95)
  color_50=lighten(color_main,0.50)

  cssres=readFile()
  cssres = string.replace(cssres,"%main%",colorstr(color_main))
  cssres = string.replace(cssres,"%dark%",colorstr(color_dark))
  cssres = string.replace(cssres,"%l1%",colorstr(color_l1))
  cssres = string.replace(cssres,"%l2%",colorstr(color_l2))
  cssres = string.replace(cssres,"%l50%",colorstr(color_50))
  cssres = string.replace(cssres,"%hex%",colorhex(color_main))
  return cssres

class CSSChameleonRandom(webapp.RequestHandler):
  def get(self):
    try:
      cssres=getCSS()
      self.response.headers['Content-Type'] = 'text/css'
      self.response.headers['Cache-control'] = 'no-cache'
      self.response.out.write(cssres)
    except (TypeError, ValueError):    
      self.response.out.write("sorry, error =(")
      raise

application = webapp.WSGIApplication([(r'/vk/chameleon/color/[^\/]+.css', CSSChameleonRandom)
                                     ],
                                     debug=True)

run_wsgi_app(application)
Вот и все, осталось только опубликовать готовый стиль на userstyles.org. Тут нас поджидает засада: userstyles.org не принимает стили с конструкцией @import, если она ссылается на внешний url. Но, как известно, на каждую хитрую гайку…
@import /*chrome:// */url(http://p.gmjs.ru/vk/chameleon/color/color.css);
Вот таким несложным способом можно обмануть юзерстайловский фейс-контроль. К сожалению, опера не разрешает импорт стилей с внешних адресов. Поэтому для нее придется установить этот стиль в виде скрипта (который можно загрузить там же на userstyles). Можно придумать и более интересное применение динамическим стилям. Например, менять стиль в зависимости от времени суток, даты, ip-адреса пользователя и т.д.
По материалам Хабрахабр.



загрузка...

Комментарии:

Наверх