Как раскрутить «Социальную сеть Ковчег», если это фантастическая трилогия

в 11:54, , рубрики: jquery, web-разработка, книги, писательство, Программирование, стартапы, Читальный зал, метки: , , , ,

Три книги с фантастикой и сайт для чтения – это проект который, длится уже 2 года.
И, чёрт возьми, мне это нравится. Сейчас расскажу, как я делал сайт для чтения своих произведений.

Каждый человек, должен иметь хобби, которое не связанно с его профессиональной деятельностью. Для души, для отдыха, для самореализации, развития своих навыков и смены деятельности (которая является лучшим отдыхом). Путём многочисленных экспериментов, я выбрал писательскую деятельность.

image

Написав первую книгу и получив множество хороших отзывов, у меня встал вопрос, как публиковаться и как донести своё произведение до своих будущих и состоявшихся читателей.

Почему не бумажная книга?

Сначала была мысль – отправить свою книгу в 200 издательств страны и ждать ответа. После получения ответа, нужно будет 6 месяцев доводить книгу до ума, при помощи редакторов и потом ещё 6 месяцев ждать 2000 бумажных экземпляров. Которые без рекламы (а её не дают для начинающим писателям) будут продаваться год. Обдумав этот вариант и учитывая, что я не привык получать деньги за своё хобби, я выбрал вариант раскрутки в интернете. Аудитория интернета в данный момент, больше чем читающая книги аудитория, которая не подключена к сети и ходят по книжным магазинам. Вы не подумайте, я не против бумажных книг, но как метод раскрутки начинающего писателя – бумажная книга очень сложный и долгий путь. (Вспомните, как начинал Лукьяненко, с бесплатных текстов в сети, в файлах .txt)

Каким должен быть сайт для чтения?

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

Казалось бы, что сложного в таком сайте? Но на пути этого увлекательного квеста, меня ждало несколько сюрпризов.

Придумывая, каким будет мой сайт, я пытался перевоплотиться в собственного читателя и учесть все свои пожелания:

Пожелания современного читателя к сайту с книгами:
1) Хочу иметь возможность скачать книгу в любом формате с оглавлением, для любой читалки (PDF, fb2, epub, mobi).
2) Хочу иметь возможность комментировать главы в книге и делиться своими впечатлениями.
3) Хочу иметь возможность дать своим знакомым короткую ссылку или поставить Like при помощи любой социальной сети, если книга мне понравится (например продиктовать по телефону адрес сайта "990990.ru").
4) Когда я на работе, я не могу достать читалку, поэтому хочу доступ к чтению на сайте. Этот же пункт действует, если у меня нет читалки.
5) При чтении на сайте, хочу, чтобы сайт запоминал позицию чтения, где я закончил. Чтобы я мог открыть книгу дома и дочитать. И ещё, я ненавижу регистрацию. Хочу авторизовываться через любую свою социальную сеть.
6) Не хочу при чтении видеть рекламу и другие отвлекающие факторы. Хочу иметь возможность выбирать фон для чтения.
7) Не хочу пользоваться скроллом для чтения таких увесистых томов
8) Прервав чтение, не хочу потом искать место, где остановился последний раз.
9) Хочу узнавать о новых книгах и главах недописанных книг автора, если мне понравятся его книги.
10) Книги должны быть интересны и написаны лёгким языком и желательно с буквами «ё».

Учитывая, что мне ещё и писать книги, после того, как сайт будет готов, я учёл требования писателя:

Требования современного писателя к своему сайту:
1) Будет супер, если я смогу писать прямо на сайте. Хочу иметь красивый, удобный, минималистичный редактор, который не отвлекает меня в режиме Fullscreen. Хочу иметь сюда доступ в любой момент, в том числе с iPad.
2) Сайт в два клика должен принимать тексты из моей любимой программы для писателей Scrvener.
3) Редактор должен подсчитывать кол-во слов в создаваемой главе, чтобы главы не получались очень длинными и можно было ставить себе норму на день.
4) Публикация новой главы, должна осуществляться в один клик.
5) Хочу знать отзывы своих читателей.
6) Хочу видеть географическое положение своих читателей и статистику скачиваний и листаний книги.
7) Хочу, чтобы внешний вид читалки, располагал к чтению и не отвлекал моих читателей от сюжета.
8) Хочу иметь короткую ссылку, чтобы раздавать своим знакомым (например 990990.ru или wezel.ru)

Поберегите колёсико или почему книга с листанием страниц,
выигрывает у длинного текста со скроллингом:

Пусть это и эгоистично, но я выбрал ту форму чтения, которая удобна мне, когда впереди, меня ждёт более 2400 страниц. Я яркий представитель SMS поколения, который любит читать, но которого всё вокруг отвлекает. После звонка друга, я должен иметь возможность, быстро вернуть свои глаза на ту строчку, где они были до того, как отвлеклись.
Скроллинг я не люблю, так как длинная «портянка» текста, может случайно уехать в самое начало и, тогда уж, проще начать читать заново, чем искать место, где остановился. А чтение, это такое ритуальное действо, что не терпит любых отвлечений.
Можно было сделать постраничную «pagination» с номерами страниц внизу, но тогда, читателю придётся изучать этот интерфейс и понимать логику перемотки. Попадать в маленькие цифры внизу, тоже не так легко, когда ты сопереживаешь главным героям, на часах 3 утра и уже спать пора, а хочется дочитать.
Поэтому и по другим неосознанным причинам, было решено заморочиться с постраничным выводом, чтобы всё было похоже на настоящую книгу.

Оглавление трёх книг

В такой книге, нужно сделать оглавление с номерами страниц. Для любителей прочитать конец и испортить себе впечатление, такая функция очень хороша. Тут же можно переключаться между тремя произведениями. В конце главы, маленький жёлтый листочек показывает кол-во комментариев пользователей к этой главе. В него можно кликнуть и добавить то, что тебя задело по прочтению.

Белые ссылки, обычным читателям не видны, с их помощью, я могу открыть главу для редактирования или начать писать новую главу.

Номера страниц, это самое сложное

Книга без номеров страниц, это как прогулка по тёмному подвалу, когда не знаешь, где начало, и когда конец. Оглавление без номеров страниц, это просто набор ссылок.
Проблема одна, как разбить длинную книгу на страницы и при этом иметь возможность обновлять главы (при этом глава может увеличиться и уменьшиться). Bookmate.com — решил этот вопрос тем, что указывает номер страницы внутри главы. Сквозной нумерации по всей книге нет. Это не наш метод. У нас произведение собственное и у нас есть время подготовить книгу к чтению, путём пересчёта номеров страниц.

Простой алгоритм, который долго придумывать:

Как разбивается длинный текст на страницы, я попытаюсь описать простыми словами, потом приведу скрипт.
1. Берём исходный текст книги и вставляем туда «мягкие переносы». Делаем это при помощи трёх строчек кода (и работы Сергея Куракина):

  include 'hypher.php';
  $hy_ru = new phpHypher('hyph_ru_RU.conf');
  $text = $hy_ru->hyphenate($text,'UTF-8');

Без переносов, наш текст будет выглядеть очень разряжённым и некомпактным. В настройках плагина, я установил переносы только очень длинных слов, поэтому текст выглядит опрятным и переносы не «частят». Этот код добавляет внутрь текста символы "& shy;" — которые разрешают браузеру переносить слова в этих местах.

2. Разбиваем длинную книгу по главам и заносим в таблицу 1_book:
1_book таблица
num — это номера глав. book — это номер книги, пока их три штуки. title — название главы

3. Путём использования «долгодумающего» скрипта (работу которого опишу чуть ниже), создаётся простая таблица 1_books_p – в которой указан номер страницы и с какого символа по какой, резать текст этой главы:
1_book_p таблица

Так мы создаём таблицу, в которой всё заранее просчитано. Пользователю не нужно ждать (и тратить ресурсы сервера) на расчёт нумерации страниц книги. Всё посчитано до нас. Этот скрипт запускается только «писателем» после того, как он изменил главу. Если глава исправленна одна, то можно пересчитать только нумерацию этой изменённой главы, а нумерацию следующих страниц уменьшить или увеличить на разницу, между тем, что было и что стало. Работа скрипта просчёта страниц одной главы, занимает 1 секунду.

Вот сам скрипт:

<?
include 'hypher_.php';
include 'pass_of_db.php';

$hy_ru = new phpHypher('hyph_ru_RU.conf');

$book = $HTTP_GET_VARS['book'];
$glava = $HTTP_GET_VARS['glava'];
if ($glava == '') $glava=0;

$db = mysql_connect ($config[mysql_host], $config[mysql_user], $config[mysql_password]);
mysql_query("SET NAMES utf8");
mysql_select_db($config[base_name],$db);   
if (!$db) { echo "Ошибка подключения к SQL :("; exit();}

   	$sqlnews2="SELECT * FROM `1_books` WHERE book=$book AND num=$glava";  
	$result2 = mysql_query($sqlnews2); 
	@$sql2 = mysql_fetch_array($result2);
	$text=$sql2['text']; //вытаскиваем текст из базы
    $text = str_replace("r",'</p><p>',$text); //вставляем параграфы там, где "возрат коретки" в простом тексте
?>

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>Перенумерация страниц</title>
	<script src="../src/js/jquery.js"></script>
    <script src="../src/js/cookie.js"></script>
    <link rel="stylesheet" href="css/style.css" type="text/css" media="screen"/>
	<script type="text/javascript">

function jsDoFirst()
{
 //считаем сколько глав
 $.ajaxSetup({async: false}); 
 var maxgl;
 $('#load2').load("getinfo.php?book=<? echo $book; ?>&page=2",function()
       {
		maxgl = parseFloat( $('.maxglav').html() );

num=1;
gl=<? echo $glava; ?>;
if (gl==0) 
 {
 gl_start  = 0; 
 gl_finish = maxgl;
 }
else 
 {
 $('#load2').load("getinfo.php?book=<? echo $book; ?>&glava="+(gl-1)+"&lastpage=1");
 num = parseFloat( $('.lastpage').html() );
 if(!num) num=0;
 num = num+1;

 gl_start=gl;
 gl_finish=gl;
 }


for(glava=gl_start;glava<=gl_finish;glava++)
{
 lnk = "getinfo.php?book=<? echo $book; ?>&p="+glava+"&start=0&limit=1200000&num=1&final=5";
 $.getJSON( lnk ,function(text)
	{ 
	i=0;
	first=0;
	for(j=0;j<=20000;j++)
	   {
	   first=i; 
	   step=800;
	   if ((text.length-1-first)<=0) step=0; 
	   for(i=first;i<=text.length-1;i+=2)
	      {
	      if(j==0) pref="<h1>Заголовок</h1>";
	      else pref="";
	      $('#b-load2').html(pref+'<p>'+text.substr(first,i-first));
	      h = $('#b-load2').height();
	      if(h>=590) 
	        {
	        i=i-1;
	        newtext = text.substr(first,i-first);
	        vv=razvedka(text,first,i);
	        i=vv+first;
	        newtext = text.substr(first,vv);
	        next=first+vv;
		    $('#load2').html($('#load2').html()+'<font size=-2em>start='+first+' to='+next+' num='+num+'</font>'+'<hr>'+newtext);
		lnk = "getinfo.php?writepage="+num+"&start="+first+"&to="+next+"&book=<? echo $book; ?>&glava="+glava;
		$('#load3').load(lnk);
		console.log(lnk);
	    num=num+1;
	    	flag=1;
	        break;
	        }
	      }
	    if (flag==0) 
	      { 
	      	next=text.length+1;
			lnk = "getinfo.php?writepage="+num+"&start="+first+"&to="+next+"&book=<? echo $book; ?>&glava="+glava;
			$('#load3').load(lnk);
		    num=num+1;
			console.log('fin='+lnk);
	        break; 
	      }
	    flag=0;
	   }
	   
	   });
}	
if (gl!=0)
  {
   lnk="getinfo.php?book=<? echo $book; ?>&glava="+gl+"&getback=1";
   $('#load2').load(lnk);
   self.close();
  }
	   });
}

function razvedka(text,first,i)
{
/*
правила переноса на следующую страницу:

Ищу ближайший с конца Пробел, или </p>
Предпочитаю </p>, даже если </p> чуть дальше пробела (тогда сл.страницу начинаю с <p>)
Если рядом только пробел, то использую его разделителем и следующую страницу
начинаю с <p2>.
Если нужно выбрать пробел, смотрю сколько слов есть после него, нужно хотя бы два и он не должен быть внутри тега.

*/
newtext = text.substr(first,i-first);

space=newtext.lastIndexOf(" "); addspace=1;
parag=newtext.lastIndexOf("</p>"); addparag=4;

if ((space-parag)<5) {vv=parag; add=addparag; }
			else 	 {vv=space; add=addspace; }

return vv+add;
}	
	
	
	</script>


<script type="text/javascript">
$(document).ready(jsDoFirst); 
</script>    

</head>
<body>

<div class="book_wrapper">
<div class="animate2">	
<div id="b-load2" style="width:365px;padding-top:20px"></div>
</div>
</div>
<div id="load2" style="background-color:white"></div>
<div id="load3"></div>
</body>
</html>		

Я не горжусь своим стилем кодирования PHP и Javascript, поэтому прошу за код палками не бить. Суть моего описания, больше относится к алгоритму определения начального и конечного места разбивания главы, чтобы текста было столько, чтобы он влез на страницу и плавно продолжил предыдущий текст.

Суть скрипта, который выше в том, что он берёт 800 символов из главы и выводит его в div, который в точности повторяет страницу книги на самом сайте. Если высота этого div не превысила 590 пикселей, прибавляется 2 символа к тексту и замеряется его новая высота. Как только мы увеличили текст настолько, что он стал вылезать из 590 пикселей, мы останавливаемся и, при помощи функции Razvedka ищем ближайший пробел или символ конца параграфа. Так мы находим место, где будем разбивать эту главу. «getinfo.php?writepage» — записывает вычисленные значения в базу для «1_books_p».

Получается, что все вычисления номеров страниц, происходят у меня на компьютере в моём браузере. Сделать это на сервере — у меня не получилось. Чтобы предсказать сколько символов нужно разместить на странице, чтобы она корректно отображалась — нужно знать ширину символов, сделать переносы, учесть отступ между абзацами. Алгоритм не постижим для моего любительского мозга.

Как сделать анимацию перелистывания страницы:

Сначала я думал, что потрачу на эту часть проекта несколько дней, но, чудом, удалось всё реализовать за 30 минут. Оказалось, что перелистывание — это анимация двух сторон одного листа. Один див нужно уменьшить по ширине до нуля, а другой увеличить до ширины листа. До сих пор удивлён простоте решения. За это я обожаю jQuery.

function rotate()
{
  ease = 'easeInQuad'; //easing - неравномерное ускорение
  tim = 700;

  maxpages=parseFloat($('.maxpages').html());  //сколько страниц всего, чтобы не перелистнуть последнюю

  $('.animate3').show(); //приводим нужные div в начальное положение
  $('.animate3').css("left",105).css("width",0);
  
//плавно сдвигаем правый див и увеличиваем его ширину до 413 пикселей
  $('.animate3').stop().animate({"left": "523","width":"413"},tim,ease, function()
     {
     $('.b-load4').html($('.b-load3').html()); //после пролистывания, меняем текст чтобы придти к начальному состоянию
     $('.num4').html($('.num3').html());
     $('.animate3').css("left",105).css("width",0).hide();
     $('.animate3').css("-webkit-box-shadow","");

	if ( $('.b-load3 #end').html() != null ) //если это последняя страница главы, вставляем комменты
	   {
		update_comment();
	  	$('.clip_right').fadeIn(600);
		$('.comments_right').fadeIn(600);
	   }
	 else
	   {
	   	$('.clip_right').fadeOut(50);
		$('.comments_right').fadeOut(50);
	   }

	if ( $('.b-load2 #end').html() != null )
	   {
		update_comment();
	  	$('.clip_left').fadeIn(600);
		$('.comments_left').fadeIn(600);
	   }
	 else
	   {
	  	$('.clip_left').fadeOut(50);
		$('.comments_left').fadeOut(50);
	   }
     
	 afterrotate();
     });

  $('.animate1').css("width",413).show(); //анимируем параллельно ещё один див (уменьшаем его ширину до 0)
  $('.b-load1').show();
  $('.animate1').stop().animate({"width":"0"},tim,ease, function()
     {
     $('.b-load1').html($('.b-load2').html())
     $('.num1').html($('.num2').html())
     
     $('.animate1').show();
     $('.animate1').css("width",413);
     });
}

Вся анимация заключается в одновременном движении двух дивов, один из которых старая страница, а другой — новая. Смотрится красиво, но трудно понять, если не умеешь читать код. Не буду рассказывать как привязать листание на клик по странице или нажатие клавиш стрелок. Это вы можете посмотреть в скрипте на самом сайте.

Как авторизоваться на сайте за одну секунду:

Авторизация для подобного сайта, нужна для одной простой, но нужной вещи. Читатель не должен помнить, какую страницу он открывал в прошлый раз. Закладку на монитор не повесишь, а книги три и нужно помнить позицию в каждой из них. Я использовал замечательный сервис авторизации Loginza.ru

Авторизация при помощи Loginza

Нужная кнопка посередине. Кто хочет, кликнет и попробует, как просто авторизоваться при помощи: vkontakte, odnoklassniki, mail, gmail, facebook и так далее…
Тут же разместились кнопки Like от яндекса для всех социальных сетей. Счётчик LIKE'ов («ссылку на книгу разместили 22 читателя») работает перехватывая клики при помощи javascript.

Тут же можно выбрать фон для чтения, нажав на кнопку «сменить фон». Сдесь же можно выбрать одну из трёх книг и даже кликнуть в ссылку "скачать книгу".

Посчитать всех, кто скачал PDF, epub, mobi, fb2:

У меня нет необходимости монетизировать данный проект, поэтому скачка файлов бесплатная.
Выглядит страница так:

Скачать книгу социальную сеть Ковчег

Казалось бы, ничего сложного. Но как сделать счётчик на скачивание, если ссылки должны выглядеть по честному, вот так: «wezel.ru/book/download/kovcheg-1.fb2»?

Ещё по опыту работы с 4pda.ru, я помню, как часто ссылки утаскивают к себе на сайт и ссылки по типу: «download.php?file=kovcheg-1.fb2» очень не любят.

Это решается простым mod_rewrite:

RewriteEngine On
RewriteRule kovcheg-1.(.+..+)$ getfile.php?name=kovcheg-1&ext=$1
RewriteRule kovcheg-2.(.+..+)$ getfile.php?name=kovcheg-2&ext=$1
RewriteRule kovcheg-3.(.+..+)$ getfile.php?name=kovcheg-3&ext=$1

При этом сам скрипт getfile.php тут:

<?
header("Content-type: application/x-gzip");
$name = $HTTP_GET_VARS['name'];
$ext = $HTTP_GET_VARS['ext'];
$filename = $name.'.'.$ext;
include "../pass_of_db.php";
$db = mysql_connect ($config[mysql_host], $config[mysql_user], $config[mysql_password]);
mysql_query("SET NAMES utf8");
mysql_select_db($config[base_name],$db);   
if (!$db) { echo "Ошибка подключения к SQL :("; exit();}

$sqlnews2="INSERT `1_books_log` (`id`, `identity`, `book`, `page`, `date`, `file`) VALUES (NULL, '".$_SERVER['REMOTE_ADDR'].' : '.$HTTP_COOKIE_VARS['identity']."', '-2', '0', NOW(),'".$filename."')";  
$result2 = mysql_query($sqlnews2); 

$fd = fopen ($filename, "r");
$code = fread ($fd, filesize($filename));
fclose ($fd);

switch ($ext) {
case 'fb2' :
echo $code;
break;

case 'epub' :
echo $code;
break;

case 'pdf' :
echo $code;
break;

case 'mobi' :
echo $code;
break;
}
?>

Так можно собрать статистику читателям, которые скачивают файлы, даже если ссылка находится на другом сайте.

Как выглядит моё рабочее место:

Я пишу книги тут:
Редактировать книгу социальную сеть Ковчег
Ничего лишнего и при нажатии F11, можно начинать строить в голове хрустальные замки сюжета. Ничего не отвлекает. Хром проверяет грамотность текста во время ввода, а нанятый мой корректор, после того, как я дописываю каждую книгу. У меня большая беда с запятыми, поэтому без корректора было бы сложнее.
В заголовке закладки браузера, у меня считается кол-во слов в редактируемой главе, это обеспечивает примерно равное кол-во слов в главе (примерно 2000).

В конце повествования, всегда идут комментарии:

Комментарии на книгу социальная сеть Ковчег

Комментарии – это то, что отличает интернет от ТВ, радио, книг, музыки и фильмов.
Делать современную книгу без комментариев, у меня бы рука не поднялась. Дизайн привычный большинству интернет-пользователей, что облегчает чтение чужих и написание своих. Можно плюсовать и минусовать комментарии. Скрипты писал сам, ничего сложного в этом нет.

Про что собственно ваша книга? – спросите вы

Книги три и они разные.
1 книга.Это фантастическая трилогия о том, как главный герой попадает в Москву будущего. Прошло 1500 лет и наступил 36 век. Описывается со всеми подробностями их гаджеты, политика, природа, психология. Начало может показаться кому-то скучноватым, поэтому нетерпеливые, могут начинать с 18 главы. В конце книги, у многих происходит разрыв шаблонов и задумчивость на несколько недель.

2 книга.Рассказывает про Америку нашего времени. Описывается природа различных человеческих зависимостей и методов их использования. Вы посмотрите на мировое устройство, которое нас окружает с неожиданной стороны. По сюжету, мы приходим к новой теории мирового заговора.

3 книга.Главный герой и 200 000 людей, попадает на другую планету. Её населяют необычные белые ангелы, которые видят сны, которые они не помнят. Главный вопрос романа, как две цивилизации уживутся друг с другом.

Лучше меня, про книгу расскажут отзывы читателей.

Приятного чтения

PS: Это мой первый пост на Хабре. Прошу миловать.

Автор: imater

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js