Предполагам доста от вас вече са се уверили в могъщите способности на CSS3. Въпреки рехавата поддържка, новият стандарт усилено се налага в ежедневието на разработчиците и съответно потребителите, като за последните в повечето случаи е трудно да усетят някаква разлика. Не това е важното обаче. Ние от FridayCode осъзнаваме колко ценен е CSS3 и как може да удължи живота ви с няколко бири повече. Това е и благородната причина, поради която споделяме този урок с вас.
Любопитната тема, на която сме се спряли днес има вероятност да ви повлече към отворилата се носталгична яма. Защо намесвам спомените ли? Както вече сте разбрали ще говорим за графики, диаграми и пр. Интересното е, че докато правих урока, в главата ми се въртяха добрите стари Excel-ски чартове. През 90-те години те си бяха сериозна гъзария и дори да не им се намираше голямо приложение сред дечурлигата, самият факт че можеш да ги правиш ти вдигаше health-a с 50 единици.
Сега, за жалост, олдскул ръбатите графики са заменени от супер-дупер красиви, мазни и ефектни диаграми, които обикновено са дело на Flash. Ние обаче за момент ще игнорираме тази технология и ще си поговорим за чартовете само с CSS3.
| View DemoDownload |
Примера в демото е един от многото, които могат да се получат като краен вариант. Реално нямаме ограничение откъм форми на диаграмите - квадратни, кръгли, елипси и дори по-сложни геометрии. Всичко зависи от вас, вашите възможности и времето, което бихте отделили. Предполагам сте видяли, че съм добавил и малко анимация, така че максимално да се доближим до Flash конкуренцията. За да видите ефекта ще е необходимо да прегледате демото под последните версии (препоръчително е) на Chrome и Safari, както и на бетата на Firefox 4. Под Opera също може да се насладите на ефекта, но има дребен визуален бъг, който се надявам да отстранят скоро. IE-тата не поддържат 99% от ефектите, които ползваме тук и за тях в този урок изобщо няма да говорим. Накрая, за ваше удобство съм поставил и инпути, в които може да въвеждате различни стойности, за да усетите ефекта по-добре.
За финал на моя псевдо-увод ще ви препоръчам да прочетете предишната статия за CSS3 - анимирани табове с CSS3, в която са обяснени доста неща. Приемам че сте го направили и продължаваме напред.
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Диаграми с CSS3</title> <link rel="stylesheet" href="css/style.css" type="text/css" /> <script type="text/javascript" src="js/jquery-1.4.2.min.js"/></script> <script type="text/javascript" src="js/charts.js"/></script> </head> <body> <div id="chart"> <ul> <li> <span class="top"></span> <a href="#"><span></span></a> <strong>0</strong> <input type="text" value="0"/> </li> <li> <span class="top"></span> <a href="#"><span></span></a> <strong>20</strong> <input type="text" value="20"/> </li> <li> <span class="top"></span> <a href="#"><span></span></a> <strong>40</strong> <input type="text" value="40"/> </li> <li> <span class="top"></span> <a href="#"><span></span></a> <strong>60</strong> <input type="text" value="60"/> </li> <li> <span class="top"></span> <a href="#"><span></span></a> <strong>80</strong> <input type="text" value="80"/> </li> <li> <span class="top"></span> <a href="#"><span></span></a> <strong>100</strong> <input type="text" value="100"/> </li> </ul> <a href="#" class="submit">Презареди</a> </div> </body> </html>
Както виждате, в случая съм избрал да използвам ul li стил за диаграмата, но разбира се това не е задължително. Вие може да решите да изграждате всичко с div-ове например и няма да има проблем - всичко е въпрос на вкус. "Контейнерите" на колоните са самите li-та. Цветът им е светлосив, за да установите зрително някакви размери. В тях имаме span с клас top, който представлява горната част на тези контейнери. Слага се, за да се придобие някакъв 3D ефект. Самият пълнеж на колоните е изграден от <a> със <span> в него. Линкът, като елемент съм го подбрал за подсказка, тъй като при hover може да се изписва информация или да се случва нещо ефектно. В него стои празен span, който служи за "затапване" на въпросния пълнеж. В li-тата се вижда, че има още елементи - strong и input, които са тук само за примера и не играят съществена роля.
CSS
body {
margin: 0;
padding: 0;
font-size: 14px;
font-family: Arial, Tahoma, Verdana, sans-serif;
line-height: 22px;
background: #f2f2f2;
color: #666;
}
ul { margin: 0; padding: 0; list-style: none; }
a, a:link, a:visited { outline: none; text-decoration: none; color: #666; }
a:hover { text-decoration: none; }
#chart {
position: relative;
width: 320px;
margin: 100px auto 0;
}
#chart ul {
height: 120px;
}
#chart ul li {
position: relative;
z-index: 1;
float: left;
width: 50px;
height: 120px;
margin: 0 4px 0 0;
background: rgba(0, 0, 0, 0.1);
-moz-border-radius: 100px / 40px; /* Firefox */
-webkit-border-radius: 100px 40px; /* Safari & Chrome */
border-radius: 100px / 40px; /* Opera */
}
#chart ul li span.top {
position: absolute;
z-index: 2;
top: 0;
width: 100%;
height: 20px;
display: block;
background: rgba(200, 200, 200, 0.7);
-moz-border-radius: 100px / 40px;
-webkit-border-radius: 100px 40px;
border-radius: 100px / 40px;
}
#chart ul li strong {
position: absolute;
bottom: -26px;
display: block;
width: 48px;
text-align: center;
}
#chart ul li a, #chart ul li a:link, #chart ul li a:visited {
position: absolute;
z-index: 10;
bottom: 0;
width: 100%;
height: 20px;
background: rgba(93, 145, 208, 0.5);
-moz-border-radius: 100px / 40px;
-webkit-border-radius: 100px 40px;
border-radius: 100px / 40px;
/* Анимиране */
-moz-transition: height 0.3s linear; /* Firefox */
-webkit-transition: height 0.3s linear; /* Safari & Chrome */
-o-transition: height 0.3s linear; /* Opera */
}
#chart ul li a span {
height: 20px;
display: block;
background: rgba(59, 113, 179, 0.5);
-moz-border-radius: 100px / 40px;
-webkit-border-radius: 100px 40px;
border-radius: 100px / 40px;
}
#chart input {
position: absolute;
bottom: -60px;
width: 48px;
border: 1px solid #999;
background: #fff;
}
a.submit {
position: absolute;
bottom: -120px;
background: #678FC1;
color: #fff;
text-align: center;
padding: 5px;
left: 50%;
width: 100px;
margin-left: -50px;
}
Ако сте ме послушали в началото и сте прочели статията за анимираните табове с CSS3, то сега едва ли ще имате проблем с CSS-a. Всъщност в конкретния пример ние не правим нищо гениално като код, а по-скоро се възползваме от възможностите на новия стандарт. Имам предвид, че ако се разгледате из кода ще видите, че ползваме border-radius, за да създадем основните ефекти и transition за анимацията. Border-radius обаче има една интересна вариация наречена elliptical borders. Стандартно изписан border-radius за всички браузъри изглежда така:
-moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px;
Когато решите да направите елипса, използвайки въпросните Elliptical Borders, синтаксисът е следния:
-moz-border-radius: 10px / 6px; -webkit-border-radius: 10px 6px; border-radius: 10px / 6px;
Обърнете внимание, че във варианта за WebKit нямаме наклонена черта. Какво представляват тези стойности? Всеки знае, че разстоянието от центъра на една окръжност до периферията й се нарича радиус. Когато той е правилен имаме окръжност, но когато е различен имаме елипса. Всъщност окръжността е един вид елипса, но ми се струва, че това са излишни подробности. В примера горе имаме стойности 10px и 6px. Това са радиусите съответно по оста X и оста Y. Но ако сте били умствено изнасилван в часовете по математика, предполагам бихте предпочели да видите обяснението на картинка, макар и семпла.
Разбира се, оставил съм стойностите в пиксели, за да се ориентирате по-добре. Сега си представете, че на всеки ъгъл от един елемент (div например) имате по една такава елипса, която оформя крайния изглед. В нашия случай този метод се ползва на четири места и е идентичен. С малко експерименти може да получите доста причудливи форми.
jQuery
$(document).ready( function() {
$('#chart ul li:last-child').css('margin', '0'); //Премахваме margin-а на последният елемент от диаграмата.
$('#chart ul li a').each( function(){
var input = $(this).parent().find('input'); //"Търсим" input-ите във всяко li.
$(this).css('height', (parseInt(input.val()) + 20) + 'px'); //Слагаме височина на всяко "a", равна на стойността от придружаващия го input и добавяме 20px.
});
$('a.submit').click(function(e) {
e.preventDefault(); //Изключваме стандартното пренасочване на "a"-то.
$('#chart ul li').each( function() {
var input = $(this).find('input'); //"Търсим" input-ите във всяко li.
$(this).find('a').css('height', (parseInt(input.val()) + 20) + 'px').next().text(input.val()); //Слагаме височина на всяко "a", равна на стойността от придружаващия го input и добавяме 20px. Също така ъпдейтваме стойността под диаграмите.
});
});
});
За финал малко jQuery магия. Мисля, че обясненията срещу редовете говорят сами за себе си, така че няма да се спирам на всичко. Като цяло тук се взима стойността от инпута и се поставя, като височина на пълнежа в диаграмата. Предполагам обаче ви прави впечатление, че на две места добавяме 20px към стойността от инпутите. Това е така, защото ако имаме стойност 0, то въпросния пълнеж не би се показал. Т.е. приемаме, че минималната стойност е 20px. Разбира се, това не е задължително да бъде така - зависи от дизайна ви, но мисля, че е полезно да видите поне едно решение на проблема, ако изникне пред вас.
Заключение
За да отпадне нуждата от всякакви инпути или дори javascript, цялата тази ливада с код може да бъде интегрирана в система, която попълва данните и чисто и просто плюе резултата чрез тези диаграми. Също така може да прави проверки какъв тип данни идват, дали те са позволени, като стойност и т.н. На демото подобни проверки липсват, така че каквото въведете, това ще получите.
Освен липсата на поддръжка в IE, други минуси (или пък плюсове? ха-ха) няма и подобен род графики биха били в пъти по-леки за браузърите и потребителите с по-слаби машини. Също така отпада изискването за Flash, което понякога може да прогони някои клиенти. Предимства могат да се изтъкват часове наред, но не това е целта. Всеки си ползва каквото пожелае, но моят зов е и ще продължи да бъде "Дайте шанс на новото!".





Надявам се да приемете всичко за конструктивна критика, защото е такова ;)
Не мога да разбера, защо като се каже CSS3 това се свежда предимно до border-radius. Не мога. CSS3 (че и 2) е много повече от това.
Примерно, част от контейнерите могат да бъдат заместени с :before / :after селектори и да се постигне същия ефект. Като цяло, :before и :after са силно пренебрегнати елементи.
После този линк, не е наистина нужен, защото click може да се прихване на почти всичко. Говорейки за клик върху линк, поне при мен, демото не работи ;)
Отново за линковете, не е нужно да се пишат всичките варианти, понеже a {} дава стилове на всичките :)
Отново, за селекторите, че няма нужда да са толкова ненужно конкретни. В смисъл #ID UL LI е излишно, при положение, че LI-тата няма как да са в друго.
Радвам ви се, че пишете за CSS, но (според мен) когато напишете нещо малко по-mind-boggling, мотивирате задклавиатурните устройства да мислят повече.
Да се върнем на скрипта, който може да бъде оптимизиран само заради принципа (в смисъл на 500 000 итерации се получават няколко секунди оптимизация). Не знам до колко сте проверявали, но дори и document.querySelectorAll не работи толкова бързо, колкото ни се иска.
В случаи, когато трябва дас е ползва ID в селектора (и трябва да ползвам jQuery), аз предпочитам $("#id").find(), понеже е доказано по-бързо (правят едни RegEx магии, с което оптимизират заявката).
И при положение, че говорим за CSS3, кому е нужен $(":last-child") ?
Та както казах -- това е конструктивна критика и палави идейки как да се затормози задклавиатурното устройство ;)
Благодаря за конструктивната критика. Наистина може някои неща да се пренебрегнат, други да се оптимизират и така нататък, но главната цел е да обясним как да се постигне крайния резултат, след това говорейки за скорост и за оптимизация, мисля че всеки решава кое е най-правилното решение за него самия. Колкото до това което казваш за :last-child :) мисля че щом са намерили място за него в jQuery :) може да се замислим за идейки с него :)
И както обичам да казвам "Винаги Всичко е Според Зависи". Още веднъж благодаря за критиките и се надявам да си активен във Форума и да бистрим политиката както се казва :)
Поздрави!
Привет! :)
Колегата добре го е казал, но въпреки това ми се иска да добавя няколко неща.
В темата за менюто с CSS и jQuery беше ни разкритикувал отново по подобен начин, но както казах няма лошо :). Но май не си ми прочел ответния коментар, в който обяснявам, че това е урок и трябва да бъде максимално разбираеми за начинаещите. Т.е. говорим си за елементарен начин на писане, ако искаш го наречи неоптимизиран. Пълно конкретизиране със селекторите, използване на познати такива и т.н. и т.н. За хората, които малко от малко разбират, визирам теб, това ще се стори като минус, но не е. Няма смисъл във всеки урок да се ползват похвати, които излишно отместват вниманието и са нужни десетки редове да се обяснят.
Освен това, никъде не се казва, че border-radius = CSS3. Говорим за CSS3, защото се ползва border-radius, rgba и transition. Мисля че е предостатъчно, за да се наблегне на новия стандат в заглавието.
За скрипта изобщо не виждам смисъл да коментираме. Урокът не е за jQuery и на поне 5 места повторих, че той няма никаква стойност тук - сложен е само и единствено заради демото.
А като говорим за задклавиатурно устройство и неговия тормоз - ами ето на - успяли сме да разчовъркаме твоето и да получим някакви отзиви, корекции и пр. Макар доста от статиите ни да работят с чист копи/пейст, в 90% от тях се залага и на умествена дейност от страна на читателите. Пак казвам, в случая сме провокирали теб, макар лично аз да не възприемам мнението ти като критика, защото няма нищо общо с главната идея на статията, а представлява съвкупност от дребни забележки за оптимизация, която вече обясних защо на места не се прави. Виждам, че имаш знания и искаш да ги покажеш, но да се хващаш за най-малкото не е правилния начин. Следващият път прочети по-добре статията и се опитай да я разгледаш от няколко гледни точки и съм сигурен, че ще видиш защо пишем повечето неща по този начин :).
Успех и лек ден!
Павел, просто си мисля, че не трябва да се ползва JS, за нещо, което го има в CSS. За съжаление, last-child има много по-малка поддръжка от first-child. Ако стиловете са написани с first-child, дори в IE 7 ще работят. (освен разбира се, ако първия нод не коментар)
Георги, не пиша коментари заради писането. Прочетох статията многократно, преди да се реша да пиша коментар; прочетох и ответния коментар. Аз съм просто устроен човек. Принципен.. в известен смисъл. Буквален в друг смисъл.
И точно защото заглавието е "Диаграми с CSS3" смятам, че трябва да се наблегне на CSS частта. Това е една идеална възможност за изява на :before и :after в малко по-сериозна светлина. Или както сте направили с анимацията.
В смисъл, не може всичко да е вечно за начинаещи. Една таква хитринка (визирам цялото писание) може да отваря безброй много вратички. Примерно веднъж говорите за self clearing и всеки следвъщ път просто се ползва, без грам обяснение. Точно както си направил референция с анимираните табове, но правиш референцията само веднъж.
Нещо като висша 3 -- никой не спира да ти обяснява защо интеграла се решава ТОЧНО по този начин -- просто казва "решава се така и се получава това".
Transition-ите не съм ги видял, моя грешка. Предполагам при скролирането просто съм ги игнорирал, а в 3.6.6 просто отсъстват *засрам*.
Пък за форума ... трябва да си правя още една регистрация... Има ли OpenID? Но щом е за политка, вероятно ще се запиша.
Нека не спорим излишно :) Всеки има право на мнение и на различни подходи за постигането на един или друг резултат в зависимост от ситуацията :) ще се радваме ако се регистрираш във форума и поставиш въпроси над които може да разискваме на дълго и на широко :)
Господин Калайджиев имам една конструктивна критика. Вземи лимитирай стойностите до 100, че като напиша нещо от сорта на 1023 и не се получава много готино :)) Иначе браво ... готин Chart :))
Господин Игнев, в заключението е писано "Също така може да прави проверки какъв тип данни идват, дали те са позволени, като стойност и т.н. На демото подобни проверки липсват, така че каквото въведете, това ще получите.".
Та, идеята беше да не се изпада в прекалено много излишни обяснения. Урокът е за CSS и JS-a е предимно за демото. Това си говорихме и по-нагоре.
Малко късно се присъединявам, но който когато ... :)
@Иван: li-тата, освен в ul, могат и да са в ol, така че смятам че селекторите са си нужни.
@FridayTeam: много добри уроци, продължавайте в същия дух ;)
[...] Диаграми със CSS3 [...]