Статьи

Создание простых сравнительных полос с помощью JavaScript и CSS

Несколько месяцев назад я просмотрел отличный сервис SumAll . Одна из самых интересных частей их обслуживания — ежедневная / еженедельная сводка по электронной почте вашей статистики. Вот скриншот из моей электронной почты сегодня утром.

Shot1

Что мне нравится в этом, так это простые полосы между каждым числом. Они дают вам очень быстрый способ увидеть ваш относительный рост / падение от одного дня к следующему. Как и любому хорошему веб-разработчику, мне было любопытно, как они это создали, поэтому я щелкнул правой кнопкой мыши, выбрал Inspect Element и посмотрел код.

Shot2

Итак, во-первых, есть много разметки, чтобы сделать эту работу. Это не потому, что разработчики SumAll отстой, это просто вопрос жизни при работе с электронной почтой HTML. Но базовый механизм не так уж и сложен — простой div с CSS. Очевидно, что вы можете использовать одну из сотен или около того различных библиотек диаграмм JS или Canvas, но зачем делать все это, когда немного CSS — это все, что вам нужно.

Я подумал, что было бы интересно попробовать воспроизвести внешний вид веб-страницы вне электронной почты, где я мог бы использовать JavaScript, чтобы сделать его более динамичным. Я начал с создания простой HTML-страницы для представления определенной метрики — количества просмотров страниц за последнюю неделю и за эту неделю.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
</head>
<body>

<h2>Scores</h2>
<table>
	<tr>
		<th></th>
		<th>Last Week</th>
		<th></th>
		<th>This Week</th>
	</tr>
	<tr>
		<td>Page Views</td>
		<td><span id="pageviews_lw" data-raw="490121">490K</span></td>
		<td><span id="dobar"></span></td>
		<td><span id="pageviews_tw" data-raw="361902">362K</span></td>
	</tr>
</table>

</body>
</html>

В этом макете нет ничего особенного, но обратите внимание, что я использую отформатированное число (490K) против действительного числа (490121). Я хотел, чтобы это было проще для конечного пользователя. Однако я знаю, что мне понадобится реальное число, поэтому я встраиваю его в HTML, используя свойство данных. (Не по теме — но я чертовски люблю атрибуты данных. Так просто, так практично !)

Вы можете просмотреть эту версию страницы здесь: http://www.raymondcamden.com/demos/2015/mar/19/test1.html . Прежде чем идти дальше — пожалуйста, просмотрите эту ссылку. Это не красиво, но угадайте что? Это работает в каждом браузере, известном человечеству. Все, что я делаю отныне, просто улучшит работу с людьми с JavaScript и более современными браузерами. Это то, что мы все должны учитывать при добавлении интерактивности / необычного пользовательского интерфейса / и т. Д. На наши страницы! (И, честно говоря, я тоже виноват в том, что не сделал надлежащего прогрессивного улучшения.)

Итак, давайте создадим следующую версию. Я начал с изменения dobarдиапазона, включив в него таблицу для размещения моих баров Это может не быть необходимым, но я подражал тому, что построил SumAll. Я также включил CSS для каждого бара минус часть, которая определяла высоту и цвет. SumAll использовал черный только для левой стороны, но я решил использовать черный для 100% -го значения и другой цвет для другого. Это просто имело больше смысла для меня. Это новый HTML для span:

<span id="dobar">

	<table><tr style="vertical-align:bottom">
		<td>
			<div style="margin-right:3px!important;width:4px;"> </div>
		</td><td>
			<div style="margin-right:3px!important;width:4px;"> </div>
		</td>
	</tr></table>
</span>

А теперь давайте посмотрим на JavaScript.

var BIG_COLOR = "#000";
var SMALL_COLOR = "#3cb4e7";

$(document).ready(function() {
	
	//get our numbers
	var pv_lw = $("#pageviews_lw").data("raw");
	var pv_tw = $("#pageviews_tw").data("raw");
	
	var biggest = Math.max(pv_lw, pv_tw);
	var smallest = Math.min(pv_lw, pv_tw);
	//so what perc of biggest is smallest?
	
	var perc = Math.floor((smallest / biggest)*100);
	//so biggest uses 30, perc determines other
	var smallerBar = Math.floor((perc/100)*30);
	
	//do left side
	var css_lw, css_nw;
	if(pv_lw == biggest) {
		css_lw = "30px solid "+BIG_COLOR;
		css_nw = smallerBar+"px solid "+SMALL_COLOR;
	} else {
		css_nw = "30px solid "+BIG_COLOR;
		css_lw = smallerBar+"px solid "+SMALL_COLOR;		
	}

	$("span#dobar td:first-child div").css("border-top", css_lw);
	$("span#dobar td:last-child div").css("border-top", css_nw);

});

Так что на самом деле — все сводится к математике. Определите наибольшее значение, а затем процентную разницу для другого значения. Я использовал «30» для обозначения самого высокого столбца, поэтому другой столбец представляет собой процент от этого. Тогда это просто вопрос обновления CSS. Позвольте мне быстро поблагодарить Иана Девлина за его помощь в поиске ошибки новичка, которую я сделал, используя jQuery.css. Я включил точку с запятой в значение CSS, которое полностью сломало обновление. Я уверен, что никогда больше не совершу эту ошибку.

Вот скриншот результата:

shot3

Вы можете увидеть эту версию во всей красе здесь: http://www.raymondcamden.com/demos/2015/mar/19/test2.html

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

<p>
Last Week: 0 <input type="range" min="0" max="200" value="99" id="leftRange"> 200<br/>
This Week: 0 <input type="range" min="0" max="200" value="32" id="rightRange"> 200<br/>
</p>

Я был немного удивлен тем, насколько хорошо они поддерживаются сейчас ( данные CanIUse ), но так как эта версия просто для удовольствия, мне все равно, что происходит в старых браузерах. Затем я написал простой приемник событий для их изменения и попросил их обновить данные при их использовании.

var BIG_COLOR = "#000";
var SMALL_COLOR = "#3cb4e7";

function renderBar() {
	//get our numbers
	var pv_lw = $("#pageviews_lw").data("raw");
	var pv_tw = $("#pageviews_tw").data("raw");

	var biggest = Math.max(pv_lw, pv_tw);
	var smallest = Math.min(pv_lw, pv_tw);
	//so what perc of biggest is smallest?
	
	var perc = Math.floor((smallest / biggest)*100);
	//so biggest uses 30, perc determines other
	var smallerBar = Math.floor((perc/100)*30);
	
	var css_lw, css_nw;
	if(pv_lw == biggest) {
		css_lw = "30px solid "+BIG_COLOR;
		css_nw = smallerBar+"px solid "+SMALL_COLOR;
	} else {
		css_nw = "30px solid "+BIG_COLOR;
		css_lw = smallerBar+"px solid "+SMALL_COLOR;		
	}
	
	$("span#dobar td:first-child div").css("border-top", css_lw);
	$("span#dobar td:last-child div").css("border-top", css_nw);
};

$(document).ready(function() {

	renderBar();

	var $leftRange = $("#leftRange");
	var $rightRange = $("#rightRange");
	var $leftSpan = $("#pageviews_lw");
	var $rightSpan = $("#pageviews_tw");
	
	$("input[type=range]").on("input", function(e) {
		$leftSpan.text($leftRange.val());
		$leftSpan.data("raw", $leftRange.val());
		$rightSpan.text($rightRange.val());
		$rightSpan.data("raw", $rightRange.val());
		renderBar();
	});
	
});

Затем вы можете поэкспериментировать с данными и увидеть, как бары поднимаются и опускаются. Потому что … я не знаю. Это весело.

shot4

Вы можете проверить эту версию здесь: http://www.raymondcamden.com/demos/2015/mar/19/test3.html