Pull to refresh

Comments 72

особенностью этого проета является минималистичность и пустота,

И нечитаемость.

Не нужно было переворачивать текст с левой стороны «вверх ногами». Лучше повернуть на 180 градусов.

Зиму с ёлкой я бы расположил наверху. Все-таки люди привыкли, что на часах все начинается с 00:00, которые вверху

Цвета можно было свести к таким: зима — синий, голубой; весна — зеленые; лето-желтый; осень — красные
UFO just landed and posted this here
Тогда нужно в центре вместо 2014 кружок под дырку предусмотреть.
И сверху стрелку сделать, независимую от календаря — крутишь календарь а она на день указывать будет, а-ля «Колесо фортуны».
Про стрелку думал, но пока что не нашёл способа сделать её промышленным способом надёжно, красиво и дёшево.
Идея хорошая, хотя я предполагал неподвижность календаря. Мне так проще ориентироваться в нём. Но ведь никто не мешает форкнуть.
UFO just landed and posted this here
лучше лето — красное (поспело)
осень — жёлтая (листья)
Спасибо за ответ!

Очень интересный вопрос про расположение Нового Года. У каждого в голове своя модель (не факт, что круглая). НГ может быть сверху (аналогия с часами), снизу (холодное — внизу, горячее — наверху), даже справа или слева. Или вообще непонятно где.

Буду рад, если читатели хабра поделятся своими моделями. Также добавлю опрос.

Про читаемость: пробовал разные варианты. Вариант, который вы предлагаете хорош. Однако, я выбрал другой как более плавный: в нём нет дополнительных стыков на границе полугодий. Сложно объяснить, это интуитивно.
У опрошенных знакомых перевёрнутые названия месяцев затруднений не вызывают.
Тогда уж добавьте опрос, в каком направлении идут месяцы. Например, у меня новый год наверху, слева февраль, март, апрель и далее против часовой стрелки. А у кого-то месяцы могут идти и по часовой. Так же интересно посмотреть на то, какой вариант преобладает.
Действительно, интенерсно. Добавил как новый опрос, чтобы не плодить кучу вариаций.
Или вообще непонятно где.

Тут видимо как раз мой вариант: снизу текущая дата, месяцы идут против часовой стрелки. Касательную к текущей дате можно мысленно представлять как привычную временную ось: слева прошлое, справа — будущее.
Круто! Прекрасная модель, может быть действительно сделать вращающийся календарь.
Спасибо, интересная ссылка и тысяча комментариев по теме.
Еще можно сделать «вечный» круглендарь — в виде спирали, начиная с года рождения и с доклеиванием новых витков снаружи. Для начала можно попробовать такое реализовать в софте, а если еще и интегрировать с социалками, почтой и другими хронологическими инструментами… Только тут важно хорошо оптимизировать его по памяти и подгружать только востребованный контент, иначе получится как с Google Wave.
UFO just landed and posted this here
Хотелось бы увидеть хоть какой-то пример уже заполненного круглендаря за 2013 год, результат, так сказать.
Здесь основная суть не в цикличности, а в каракулепригодности, я так понял.
Может, невнимательно посмотрел, но кажется, что всегда будут присутствовать числа 29-30-31? Даже в феврале?
Да, есть такой там недочет.
Случилось что-то интересное? Лихо дорисовываем круглендарь! К концу года будет любо-дорого смотреть.

Или Вас накроет жестокая депрессия из-за того, что он практически совсем пустой! Так что, не рекомендуется склонным к депрессии и просто тем, у кого мало что случается. :)
Отдаленно похоже на календарь беременности. )
Кстати, выше высказана очень хорошая идея со спиралью.
Да, после беременности и спираль пойдёт. (извините)
Используя такой календарь, для периодических событий можно наловчиться многогранники рисовать.
Всегда воспринимал год в виде синусоиды с минимумом функции в июле и максимумом в январе.
Я, почему-то, представляю течение года против часовой стрелки… В отличии, как видно, от большинства. Почему так, интересно.
Может у вас часы без стрелок?
Может быть, Вы — математик?
image
отличная вешь
может подскажете что в исходнике отвечает за направление? хочу для себя сгенерировать
видимо я из тех 16 % :)
Быстро хорошего решения я не придумаю. Придумаю плохое:

Если долго
# -*- coding: utf-8 -*-
import svgwrite, math, numpy

def frange(x, y, jump):
  while x > y:
    yield x
    x += jump

if __name__ == '__main__':
  # Calendar parameters
  dayAngle = math.pi*2/365
  textAngleShift = -(0.26*math.pi*2/365)-1*dayAngle
  canvasSize = (500,707)
  mid = canvasSize[0]/2.0, canvasSize[1]/2.0
  dayFontFamily = "PT Sans"
  dayFontSize = "1.8pt"
  svgFileName = 'calendar_CCW.svg'

  # we will interpolate rainbow gradient through these points
  rainbowGradient = [[  0,  0,  0,239,255,255,  0,  0],  # Red
             [254,248,246,194,  0,  0,211,254],  # Green
             [255,193,  0,  0,  0,210,255,255]]  # Blue
  rainbowGradientPoints = [math.pi*2/7*0,
               math.pi*2/7*1,
               math.pi*2/7*2,
               math.pi*2/7*3,
               math.pi*2/7*4,
               math.pi*2/7*5,
               math.pi*2/7*6,
               math.pi*2/7*7
              ]

  #=======================================
  # Calendar circle parameters
  #=======================================
  k = 3.0 # multiplication koef.
  delta = 1.9 # first step in progression
  initRad = canvasSize[0]*0.3684 # initial size
  radiusProgression = [initRad]
  for i in range(4):
    nextValue = initRad-delta*pow(k,i)
    radiusProgression += [nextValue]
  R_dates = 1.2*canvasSize[0]*0.312
  R_days_end, \
    R_days_beg, \
    R_weeks_beg, \
    R_mounthes_beg, \
    R_seasons_beg = radiusProgression
  #R_weekend_end = R_days_beg + 20;
  R_weekend_end = R_days_end;
  # Stroke width
  stroke_k = 1.8
  stroke_thinest = 0.15
  dayLineStrokeWidth, \
    weekLineStrokeWidth, \
    mounthLineStrokeWidth, \
    seasonLineStrokeWidth = [0.1*(stroke_k**i) for i in range(4,0,-1)]

  weekendStrokeWidth = 6.7

  #=======================================
  # Filling mounth arrays
  #=======================================
  weekAngle = dayAngle*7
  mounthes = [u'января',\
        u'февраля',\
        u'марта',\
        u'апреля',\
        u'мая',\
        u'июня',\
        u'июля',\
        u'августа',\
        u'сентября',\
        u'октября',\
        u'ноября',\
        u'декабря'\
        ]
  mounthDays = [31,28,31,30,31,30,31,31,30,31,30,31] # days in each mounth
  yearDays = ["%d %s"%(i+1, mounthes[index]) \
            for index, m in enumerate(mounthDays) \
            for i in range(m)]
  # array with marks for yearDays:
  # 1 means first day of mounth
  # 2 means first day of mounth and of season
  allFirstDates = [ 0 if i!=0 else \
            1 if (index+1)%3!=0 else \
            2 \
            for index, m in enumerate(mounthDays) \
            for i in range(m)]
  mounthAngles = [d*dayAngle for d in mounthDays]

  #=======================================
  # Making svg and groups
  #=======================================
  dwg = svgwrite.Drawing(svgFileName, profile='tiny')

  textGroup = dwg.g(font_family=dayFontFamily, \
     font_size=dayFontSize,\
     text_anchor="start" )
  dayLineGroup = dwg.g(stroke_width=dayLineStrokeWidth, fill='none')
  weekLineGroup = dwg.g(stroke_width=weekLineStrokeWidth, fill='none')
  mounthLineGroup = dwg.g(stroke_width=mounthLineStrokeWidth, fill='none')
  seasonLineGroup = dwg.g(stroke_width=seasonLineStrokeWidth, fill='none')
  weekendGroup = dwg.g(stroke_width=weekendStrokeWidth, fill='none')

  #=======================================
  # Drawing in defined groups
  #=======================================
  for index, angle in enumerate(frange(math.pi*2,0,-dayAngle)):
    #angle = -angle
    print angle, index
    # interpolation will help us to find
    # all necessary segments for every segment of circles
    colorTuple = (int(numpy.interp(angle, rainbowGradientPoints, rainbowGradient[0])), \
           int(numpy.interp(angle, rainbowGradientPoints, rainbowGradient[1])), \
           int(numpy.interp(angle, rainbowGradientPoints, rainbowGradient[2])))
    color = "rgb%s"%(str(colorTuple))
    sinus =   math.sin(angle)
    cosinus = math.cos(angle)
    
    # Draw a week segment
    if (index-5)%7 == 0:
      weekLineGroup.add (dwg.line( (mid[0]-R_weeks_beg*sinus, \
         mid[1]+R_weeks_beg*cosinus), \
         (mid[0]-R_days_beg *sinus,mid[1]+R_days_beg *cosinus), \
         stroke=color) )
      # Draw a weekend
      sinus_weekend   = math.sin(angle+dayAngle)
      cosinus_weekend = math.cos(angle+dayAngle)
      weekendGroup.add (dwg.line( (mid[0]-R_days_beg*sinus_weekend, \
         mid[1]+R_days_beg*cosinus_weekend), \
         (mid[0]-R_weekend_end *sinus_weekend,mid[1]+R_weekend_end *cosinus_weekend), \
         stroke=color) )
    #if (index-)
      weekLineGroup.add (dwg.line( (mid[0]-R_weeks_beg*sinus, \
              mid[1]+R_weeks_beg*cosinus), \
         (mid[0]-R_days_beg *sinus,mid[1]+R_days_beg *cosinus), \
         stroke=color) )
    # Draw a mounth+season segments
    if allFirstDates[index]!=0:
      mounthLineGroup.add (dwg.line( (mid[0]-R_mounthes_beg*sinus,mid[1]+R_mounthes_beg*cosinus), \
         (mid[0]-R_weeks_beg *sinus,mid[1]+R_weeks_beg*cosinus), \
         stroke=color) )
      # Draw a season segments
      if allFirstDates[index]==2:
        seasonLineGroup.add (dwg.line( (mid[0]-R_seasons_beg*sinus,mid[1]+R_seasons_beg*cosinus), \
           (mid[0]-R_mounthes_beg *sinus,mid[1]+R_mounthes_beg*cosinus), \
           stroke=color) )
    # Draw a day segments
    dayLineGroup.add (dwg.line( (mid[0]-R_days_beg*sinus,mid[1]+R_days_beg*cosinus), \
       (mid[0]-R_days_end *sinus,mid[1]+R_days_end *cosinus), \
       stroke=color
       ) )

    # Draw a day name
    if (index-4)%7 == 0 or (index-3)%7 == 0:
        fillColor = color #"rgb(255,255,255)"
        #fontWeight = "bold"
        weekendMargin = 2.0
    else:
        fillColor = "rgb(0,0,0)"
        #fontWeight = "normal"
        weekendMargin = 0
    wordGroup = dwg.g(transform="rotate(%f, %f, %f) translate(%f,0)" \
            %( math.degrees(angle+dayAngle+textAngleShift)+90, mid[0], mid[1], +R_dates+weekendMargin ) \
            )
    wordGroup.add( dwg.text( '%s'%(yearDays[index]), \
            insert=mid, fill=fillColor \
            #,style="font-weight: %s;"%(fontWeight)
            ))
    textGroup.add(wordGroup)

    #=======================================
    # Dray a circle segments
    #=======================================
    sinus_end =   math.sin(angle+dayAngle)
    cosinus_end = math.cos(angle+dayAngle)
    dayLineGroup.add( dwg.line( (mid[0]-R_days_beg*sinus,  mid[1]+R_days_beg*cosinus), \
      (mid[0]-R_days_beg*sinus_end,mid[1]+R_days_beg*cosinus_end), \
      stroke=color ) )
    weekLineGroup.add( dwg.line((mid[0]-R_weeks_beg*sinus,    mid[1]+R_weeks_beg*cosinus), \
      (mid[0]-R_weeks_beg*sinus_end,mid[1]+R_weeks_beg*cosinus_end), \
      stroke=color ) )
    mounthLineGroup.add( dwg.line((mid[0]-R_mounthes_beg*sinus,   mid[1]+R_mounthes_beg*cosinus), \
      (mid[0]-R_mounthes_beg*sinus_end,mid[1]+R_mounthes_beg*cosinus_end), \
      stroke=color ) )
    seasonLineGroup.add( dwg.line((mid[0]-R_seasons_beg*sinus,    mid[1]+R_seasons_beg*cosinus), \
      (mid[0]-R_seasons_beg*sinus_end,mid[1]+R_seasons_beg*cosinus_end), \
      stroke=color ) )

  #=======================================
  # Simple circles for quick testing
  #=======================================
  #dayLineGroup.add( dwg.circle(center=mid, r=R_days_end, stroke='black' ) )
  #dayLineGroup.add( dwg.circle(center=mid, r=R_days_beg, stroke='black' ) )
  #weekLineGroup.add( dwg.circle(center=mid, r=R_weeks_beg, stroke='black' ) )
  #mounthLineGroup.add( dwg.circle(center=mid, r=R_mounthes_beg, stroke='black' ) )
  #seasonLineGroup.add( dwg.circle(center=mid, r=R_seasons_beg, stroke='black') )

  dwg.add(dayLineGroup)
  dwg.add(weekLineGroup)
  dwg.add(mounthLineGroup)
  dwg.add(seasonLineGroup)
  dwg.add(weekendGroup)
  dwg.add(textGroup)

  # As I didn't learn how to set document width and height, just draw a rect
  dwg.add(dwg.rect((0, 0), canvasSize, stroke='gray', fill="none"))

  dwg.add(dwg.text("2014", insert=(mid[0],mid[1]+4), text_anchor="middle", font_family="PT Serif", font_size="10pt"))

  #=======================================
  # Finaly, draw it!
  #=======================================
  dwg.save()


А если коротко:

5c5
<   while x < y:
---
>   while x > y:
11c11,12
<   textAngleShift = -(0.26*math.pi*2/365)
---
>   dayAngle = math.pi*2/365
>   textAngleShift = -(0.26*math.pi*2/365)-1*dayAngle
16c17
<   svgFileName = 'calendar_03.svg'
---
>   svgFileName = 'calendar_CCW.svg'
63d63
<   dayAngle = math.pi*2/365
109c109,111
<   for index, angle in enumerate(frange(0,math.pi*2,dayAngle)):
---
>   for index, angle in enumerate(frange(math.pi*2,0,-dayAngle)):
>     #angle = -angle
>     print angle, index
126,127c128,129
<       sinus_weekend   = math.sin(angle-dayAngle)
<       cosinus_weekend = math.cos(angle-dayAngle)
---
>       sinus_weekend   = math.sin(angle+dayAngle)
>       cosinus_weekend = math.cos(angle+dayAngle)
запустил, все работет, против часовой
спасибо добрый человек
Как вы представляете себе год?

Овал, текущая дата снизу.
Овал вертиальный или горизонтальный?
Очевидно зависит от текущей даты. :)
Вообще, вытянут от зимы к лету, т.е. осень и весна длиннее. Почему так — не знаю.

Кстати, если провести такой же опрос где-нибудь в июле, допускаю, что вариант «лето сверху» может быть намного популярнее, чем сегодня.
У меня, почему-то, календарь всегда ассоциировался с прямоугольником. Причём месяцы идут против часовой стрелки, зима сверху. И ещё — самое странное — верхняя и нижняя стороны (зима и лето) длиннее боковых. Возможно это потому, что весна и осень всегда воспринимаются как некие переходные поры года, а лето и зима как-бы основные — 2 крайности в погоде.
А вот ещё вспомнил. Когда я отсчитываю месяцы, этот прямоугльник в уме воображаю как бы с обратной стороны (может даже объёмная картинка получается), т.е. месяцы идут уже по часовой стрелке. А если просто воображать год (календарь), то прямоугольник будто на плоскости и выглядит как описано выше.
А у меня наоборот в эллипсе весна и осень длиннее. У всех свои тараканы в голове командуют. :)
Ну хоть кто-то! Я тоже представляю год как прямоугольник. Правда, месяцы идут по часовой стрелке и зима снизу. Весна и осень у меня тоже немного короче зимы и лета. Причем если представляю год абстрактно, то прямоугольник ровный, а если думаю о текущей дате, он как бы искажается, и текущая грань представляется длиннее всех остальных.
Спасибо за идею! Думаю прикрутить шаговый двигатель и повесить на стенку.
Проезжал в обед мимо типографии — распечатал на А1. Вечером разрисую февраль, поделюсь как выглядит
Повесить в туалете лист формата А1 — значит а) иметь большой туалет, б) повесить его на далекую от «думающего» стену, что помешает использовать фломастер в процессе «размышлений». Может, оно и лучше, но для туалета надо бы змейку или еще что-то, что плотнее использует пространство )
А это идея. Провести статистический анализ по интенсивности использования бумаги и выпустить «календарь рулонный, отрывной, 1 неделя февраля, 54 метра». :)
Дошел в рулене до конца очередного «месяца», а этот месяц еще не кончился — «возьми себя в руки, не нарушай установленный тобой самим порядок!»
А у меня представление года в виде квадрата, по часовой, каждая сторона-время года. НГ соответственно где-то внизу(не посередине), весна слева, затем лето наверху и осень справа. А ещё при таком представлении в центре останется больше места для рисовашек =)
Тоже квадрат, только НовыйГод посередине сверху. Весна таки слева (против часовой стрелки)
Хм. С одной стороны — дико нечитаемо, неудобно как сам календарь, очень пусто. С другой — интересная идея. Можно было бы конечно попытаться уместить в формат А2 (у меня просто некуда вешать А1, что поделаешь).

Но вот меня это навело на мысль соеденить такой календарь с чем-то типа
Пример
image

Т.е. В середине Солнце, схематичные изображения Земли и т.д. Ну люблю я космос и астрономию, что поделаешь :)
К слову, более такой «техничный» или «научный» календарь — интересная идея. Можно еще какие-то данные выводить.
Можно развить. Очень интересная визуализация может получиться. На этом варианте я думал показывать фазу луны, но потом отказался от идеи.
Шыдевр!

rainbowGradientPoints = [math.pi*2/7*x for x in xrange(8)]

Будьте снисходительны, я — дизайнер.
А как надо было?
Я ж написал — list comprehension вместо повторения формулы 8 раз. Three or more — use «for».
А меня в детстве бабушка приучила считать количество дней в месяце по костяшкам кулака, от туда, наверное, в голове, год выглядит, как синусоида.
Я тоже по костяшкам массив заполнял. Потом, правда, перепроверил на всяких пожарный.
Ещё один такой же как и я с годом в виде синусоиды)) а у вас минимум функции это зима или лето?
У меня чуть по-другому, максимум, это длинный месяца (31 день), минимум короткие, правда немного нелогичное представление, я это и сам понимаю, июль и август, декабрь и январь, февраль, не укладываются, но ничего не могу с собой поделать.
Эта мнемоника хорошо работает. На переходе декабрь-январь и июль-август — разрывы фазы. Небольшая длина когерентности, в общем ,)
Этот календарь нужен для летописи. На нем очень удобно отмечать события своей жизни, закрытия проектов в офисе и т.п. Как инструмент для слежением за датами этот календарь не подходит. Зато он крут тем, что его можно начать заполнять в любой момент!

Посему: даты размещать нужно по часовой стрелке, но никакой привязки к НГ не стоит делать. Более того, не стоит и писать год для календаря. Его можно начать в любой момент, в отличие от другого типа календарей. Стоит только представить фрустрацию человека, начинающего ежедневник в феврале, например, ууу…

Пишет скромный создатель кругового календаря в 2000 году. В прошлом году я также выпустил в свет вторую версию.

Кстати, я еще пришел к тому, что этот календарь очень легко кастомизируется, на радость тем, кто хочет себе нечто особенное. Вот, мой друг держит свеженапечатанный экземпляр для биофака университета Южной Каролины: instagram.com/p/aN0godruOc/

Крайне рад, что, оказалось, у меня есть однодумцы. Я тут побурчал, но на самом деле клево получилось ;-)
Версия для биофака действительно крутая! И ДНК хорошо обыгралась, и монохромность пошла на пользу. Макет сохранился? Я бы повесил на стенку.
Макет сохранился, но на работе. Как приду — выложу, но, увы, только в ознакомительных целях, ибо он таки custom shop для одного человека в одном экземпляре.
Было бы любопытно сделать такой на D3.js с возможностью кастомизации и печати прямо из браузера.
Ого! Вдохновился, спасибо. Хочу как-нибудь сделать версию календаря по мотивам этого скрипта. Интересно, как проще на питоне сделать физическую симуляцию?
Sign up to leave a comment.

Articles