svg-porr, testkört raphaelJS

Arcs
Arcs

Det är väldigt lätt att man som webbutvecklare ibland fastnar i mönster för hur man bygger och renderar sidor, även om det finns nyare effektivare alternativ, då detta framförallt sparar tid. Tid är ett ständigt återkommande problem som ofta bankar skiten ur ens nyfikenhet och får en att stagnera kunskapsmässigt. Det resulterar i att man får försöka hålla sig uppdaterad när man kan och vill, vilket ofta blir kvällar och liknande =) Ett bibliotek som jag blev tipsad om av en kollega och sen spenderade några kvällar förra veckan med att titta på är RaphaelJS.
Ett bibliotek som hjälper dig rendera SVG med hjälp av javascript 🙂 Möjligheterna är stora och det finns ordentligt dokumenterat, vissa delar fick mitt huvud att värka lite, men det gick att ta sig igenom och jag tycker det var värt besväret.
Ibland vill man visualisera data på olika sätt, vilket jag använt biblioteket till, och då för att skapa lite olika charts/diagram. Ett av de mer intressanta som jag tänkte dela med mig av är arc/bågen som är ett rätt trevligt sätt att visa procentuell data på.

Här har jag gjort ett enkelt plugin som hjälper mig att med jquery rendera objekten i raphael. Storleken på objekten styr jag med css.
[sourcecode language=”css”]
.arc {
width: 100px;
height: 100px;
display: block;
}
[/sourcecode]
Och den enda HTML jag då renderar ut på sidorna är följande:
[sourcecode language=”html”]
<meter id=”arc1″ class=”arc” data-value=”70″ data-color=”#00006b” data-label=”70″></meter>
<meter id=”arc2″ class=”arc” data-value=”35″ data-color=”#00006b” data-label=”35″></meter>
[/sourcecode]
Det gör att man får väldigt clean HTML vilket jag är ett stort fan av =D, samt att man kan isolera procedurerna för renderingen och hålla saker där de ska vara! och hör sen alla som kladdar med script inline ^^

Från min script.js kallar jag sen enkelt på pluginet:
[sourcecode langauge=”javascript”]
$(‘.arc’).arcThis();
[/sourcecode]

Mycket renare än så kan knappast vyn bli och resten fixar vi med hjälp av raphaelJS och lite jquery. När det gäller att rendera bågar/arcs blir det matte på lite tölig nivå men det är egentligen inga knepigheter. Vi tar hjälp av rapahels .path funktion för att tala om start-slut positioner på sträckan samt vilken kurva den ska ha. Sen räknar vi ut positionsmässigt vart vi ska placera den baserat på storleken på objektet, vilket vi bestämt med CSS. Har även satt lite statiska värden i options som man kan overrida när man kallar på funktionen etc. Väldigt enkelt. Hade gjort ett innan som renderade flera bågar i samma med underelement osv men det blev lite rörigt att visa =P

[sourcecode language=”javascript”]
(function( $ ) {
$.fn.arcThis = function( options ) {
var calcCirclePath = function(value, bar, maxValue) {
var alpha = 360 / maxValue * value;
var a = (90 – alpha) * Math.PI / 180;
var x = bar.xpos + bar.radius * Math.cos(a);
var y = bar.ypos – bar.radius * Math.sin(a);
if(value == maxValue) {
return [[“M”, bar.xpos, bar.ypos – bar.radius], [“A”, bar.radius, bar.radius, 0, 1, 1, (bar.xpos-0.01), bar.ypos – bar.radius]];
} else {
return [[“M”, bar.xpos, bar.ypos – bar.radius], [“A”, bar.radius, bar.radius, 0, +(alpha > 180), 1, x, y]];
}
};

return this.each(function () {
var $this = $(this);
var settings = $.extend( {
maxValue: 100,
contId: $this.attr(‘id’),
contHeight: $this.height(),
contWidth: $this.width(),
strokeWidth: 15
}, options);

$cont = document.getElementById(settings.contId);

var bar = {
value: $(this).attr(‘data-value’),
stroke: $(this).attr(‘data-color’),
title: $(this).attr(‘data-label’)
};

var maxDia;
if ( settings.contHeight > settings.contWidth ) { maxDia = settings.contWidth; }
else { maxDia = settings.contHeight; }

maxDia = maxDia – (settings.strokeWidth * 2);

bar.radius = (maxDia / 2);

bar.xpos = bar.radius + settings.strokeWidth;
bar.ypos = bar.radius + settings.strokeWidth;

var paper = new Raphael(document.getElementById(settings.contId), settings.contWidth, settings.contHeight);

var arc = paper.path(calcCirclePath( 100, bar, settings.maxValue));
arc.attr({ stroke: ‘#dddddd’, ‘stroke-width’: settings.strokeWidth });

var arc = paper.path(calcCirclePath( bar.value, bar, settings.maxValue ));
arc.attr({
stroke: bar.stroke,
‘stroke-width’: settings.strokeWidth,
title: bar.title + ‘%’
});

var text = paper.text(bar.xpos, bar.ypos, bar.title + ‘%’);
});
};
})( jQuery );
[/sourcecode]

Jag tycker det är väldigt lite besvär för en väldigt trevlig funktion, vi får fint renderade svg objekt som skalerar gudomligt, något som även är fascinerande är att det är kompatibelt ända ner till IE7. Texten får sig en liten törn i IE7 men inte så det blir oläsbart. Har även sett vissa kompatibilitetsproblem med mobilversionen av IE9, men det fungerar i övrigt på det mesta som vi provat. (jo iphone verkar ok med). På samma sätt går det väldigt mycket enklare att rendera t.ex. stapeldiagram mm. Biblioteket har även stöd för animering! och event! woop woop. Så ja jag kommer nog leka vidare med detta ^^

Såja. Lycka till att läsa kladdet ovan vilket inte alltid är så lätt när det gäller andras jquery ^^

lek med CSS3 & ikoner

Tro jag hade dåligt tråkigt ikväll eller, skulle spela men så blev det inget, var inge sugen på att jobba med något riktigt så surfade runt lite. Började läsa om former och så i Css, fick se lite grejer folk hade gjort och kände mig inspirerad. Jag har haft mycket Facebook på huvudet idag pga jobbet och fick därför idén att leka med Facebook-ikonen. I övrig notis så bakade jag även scones som resultat av det rubbade kvällsschemat.

En sak som är lite trevlig med css är att det blir webbläsaren som ritar upp det, vilket också gör att det skalerar väldigt bra. dvs du kan zooma och joxxa utan elaka pixelmonster. Här valde jag för demonstrationssyftet att rendera några versioner med hjälp av “zoom:” elementet i css. Eftersom många webbläsare är lite svältfödda på vissa attribut så tog jag även en bild.

fbIcons Css3

Allt är som sagt gjort med hjälp av Css3, användningsområdet är än så länge obestämt. Men om man har några timmar över och vill rita med kod så kör.

Html
[sourcecode language=”html”]
<div class="fbIcon zoom1">
<div class="outerbox">outer</div>
<div class="bottombox">bottom</div>
<div class="boxring">box</div>

<div class="white f1">f1</div>
<div class="white f2">f2</div>
<div class="white f2_2">f2_2</div>

<div class="white f3">f3</div>
</div>
[/sourcecode]

unt der css,
[sourcecode language=”css”]
.fbIcon {
margin: auto;
position: relative;
display: block;
height: 700px;
width: 700px;
text-indent: -9999px;
margin: 5px;
float: left;
}

.fbIcon div {
position: absolute;
display: block;
}

.fbIcon .outerbox {
height: 700px;
width: 700px;
border-radius: 60px;
background: #4370a9;
background: -moz-linear-gradient(-90deg, #164c8b, #4370a9);
background: -o-linear-gradient(#164c8b, #4370a9);
background: -webkit-gradient(linear, 0 top, 0 bottom, from(#164c8b), to(#4370a9));
}

.fbIcon .bottombox {
width: 645px;
height: 160px;
border-radius: 40px;
bottom: 25px;
left: 30px;
background: #6d84b5;
background: -moz-linear-gradient(-90deg, #6d84b5, #83a3d3);
background: -o-linear-gradient( #6d84b5, #83a3d3);
background: -webkit-gradient(linear, 0 top, 0 bottom, from(#6d84b5), to(#83a3d3));
}

.fbIcon .boxring {
height: 670px;
width: 670px;
border-radius: 60px;
background: transparent;
top: 5px;
left: 5px;
border: 10px solid #164C8B;
}

.white { background: #fff; }

.fbIcon .f1 {
width: 125px;
bottom: 25px;
height: 530px;
right: 180px;
}

.fbIcon .f2 {
width: 280px;
bottom: 360px;
height: 100px;
right: 80px;
-webkit-transform: skew(-5deg);
-moz-transform: skew(-5deg);
-o-transform: skew(-5deg);
transform: skew(-5deg);
}
.fbIcon .f2_2 {
height: 100px;
right: 350px;
width: 20px;
bottom: 360px;
}
.fbIcon .f3 {
width: 240px;
height: 100px;
bottom: 555px;
right: 65px;
border-top-left-radius: 100px 100px;
}
[/sourcecode]

css3, pseudo-klasser & validering

Jag hade mig en liten tänkarstund igår tillsammans med min isbjörnsdräkt och några öl, några av tankarna tog mig till internet. Internet är ganska stort och mycket händer på internetet så att säga. Något som jag tycker är framförallt intressant är nyheter med CSS3 och hur mycket kan ersätta jobbig ajax eller jquery galore. Speciellt när det gäller användare och feedback så tycker jag inte det ska behöva ligga så mycket logik bakom visualisering.

En av de saker som ofta dyker upp med web är validering av formulär. Jag har precis avslutat ett ganska stort arbete gällande just detta och en rätt stor del var att ge användaren omedelbar feedback. Detta var för mig speciellt krångel eftersom det kunde finnas multipla formulär på samma sida, vilket ofta får .net att gå bananas med sin omslutande form-tag. Så vi glömmer det problemet och tittar framåt vad som går att göra med CSS3 + html5 och enklare formulär.

I och med HTML5 så kom det ett antal fler attribut för tex “type”, de som finns (button, checkbox, color, date, datetime, datetime-local, email, file, hidden, image, month, number, password, radio, range, reset, search, submit, tel, text, time, url, week) kan tänkas ganska mjeh då de får kontrollen att se lite speciell ut. Fine med det. Det finns lite mer magi för att gör detta användbart i användarsynpunkt. Du kan tex koppla på attributet “required” eller “optional”. Dvs.
[sourcecode language=”html”]
<input type="email" required />
<input type="email" optional />
[/sourcecode]
Detta i sig verkar ju inte så jävla speciellt men det ger dig tillgång till ett par pseudo-klasser i CSS3, så du skulle kunna göra följande.
[sourcecode language=”css”]
input:valid { border: 1px solid lime; }
input:invalid { border: 1px solid crimson; }
[/sourcecode]
Det du får då är automatisk styling beroende på om en “type” validerar sig eller inte & du använder en inbyggd validering för typen. Det är väl så nära en standardvalidering man kan komma kan tyckas? För vissa “types” kan du även sätta “min” och “max”, vilket då också ger dig tillgång till ytterligare pseudo-klasser som “:in-range”, “:out-of-range”, “:read-only”, “:read-write”. Men för mig är detta ungefär samma sak som att det inte validerar, kan vara intressant för att markera fält man inte ska skriva i men jag brukar normalt inte rendera dem som inputs om så är fallet.

[sourcecode language=”html”]
<form action="#" method="get">
<input type="text" required placeholder="Ditt namn" /><span></span><br />
<input type="email" required placeholder="Din Email" /><span></span><br />
<input type="number" min="18" max="30" required placeholder="Din ålder" /><span></span><br />
</form>
[/sourcecode]
Så kan du styla detta för visuell feedback lätt exempelvis med en annan pseudo-selector “after” tillsammans med det fina attributet “content”. På samma sätt hade jag givet här kunnat välja att visa ett element med “display” men det är skoj att variera sig.

[sourcecode language=”css”]
<style>
input:invalid { border: 1px solid crimson; }
input:invalid + span::after {
content: ‘seriously? no validate? u make internetz sad’;
}
input:valid { border: 1px solid lime }

input:focus { border: 2px solid lightblue; }
</style>
[/sourcecode]
har även kastat in min favorit “:focus” här för att enklare visualisera vilket input man är och kladdar i.

Värt att notera är att inget att dessa hindrar ett formulär från att postas, det är endast visuellt men på samma sätt kan man *hint hint* komma åt dessa pseudo-klasser med jquery. en och annan som man använt är tex “:checked”, “:target” osv. Detta är relativt lätt att haka på och se till så att formuläret endast postas om allt är validerat. Givet ersätter inte detta en normal code-behind (eller liknande med häftiga regex uttryck), men det kan hjälpa till vid visuella effekter utan att det ska falla på jquery/ajax och liknande för feedback. Menar hur skönt är det inte att slippa validera email eller “required”.. doh.

Då det är html5 och css3 så fungerar det som vanligt inte i alla webbläsare. Tror safari och chrome klarar av det i senaste versioner iaf.

lightbox med CSS3

Igår var en sådan dag som slutade i att jag var lite milt upprörd, igen, denna gång över vad vissa plugin gör när de kallar på t.ex. en lightbox. Då man vill återanvända inkluderade bibliotek så mycket som möjligt blir det lätt att man krånglar lite extra för att få det att fungera =(
Mitt problem grundade sig i ett nytt valideringsscript jag gjort för en kund (jQuery Validate som grund), som fungerar precis just perfekt efter lite tweeks, tills jag kom till det att ett av formulären skulle ligga i ett modalfönster. De lightboxes/modalscript som jag använt förut och som jag provkörde med var idag nyromodal, lightbox_me, fancybox och tinybox. Av en eller flera anledningar så strulade det med samtliga på lite olika trevliga sätt. Det enda jag ville var att visa något som ligger dolt, i en modalruta. Dvs mörkret ska härska på skärmen och ett stackars objekt ska få all uppmärksamhet i mitten.

Man tycker inte att det ska vara så jäkla svårt så jag satte mig ner för att skriva ett eget, bara för att, men kom på att det säkert skulle bli mer jobb än värt. Började göra lite research istället för att utforska internet och dess hemligheter. Jag hade suttit någon timme och lekt med CSS3PIE.htc för ett annat projekt tidigare under dagen och var lite sugen att titta på vad mer man kunde göra med CSS3 istället.

En intressant pseudo-class som jag sprang på med CSS3 är :target, som fångar upp vad som ligger bakom en hashtag. Dvs du kan t.ex. styra en stil beroende på om du tryckt på vad som genom åren refererats till som ett ankare.
[sourcecode language=”html”] <a href="#lightThisUp">CluckClack</a>[/sourcecode]

Länken kommer vid klick naturligt att styra mig till /#lightThisUp. Med :target får jag tag i detta element och kan manipulera dess egenskaper. Då kan jag alltså styra egenskaper generellt för de objekt som just nu är :target utan att behöva specificera ett id eller klass för detta. Skulle jag definera lite objekt för detta låt säga:
[sourcecode language=”html”]
<a href="#snelDiv">klick klick</a>
<div id="snelDiv">Inte så stor o stark</div>

<a href="#elakDiv">no no</a>
<div id="elakDiv">Stor och stark och elak och dum</div>
[/sourcecode]
Så kan jag styra dessa individuellt beroende på vilken som är vald via #. Här skulle det beroende vilken länk jag trycker på styra bakgrunden:
[sourcecode language=”css”]
div { background: lime; }
div:target { background: crimson; }
[/sourcecode]

Sjukt meningslöst så långt kanske man kan tycka men det går faktiskt att göra en del med det. Säg att jag istället skulle skapa ett lightbox-objekt av det här nu.

[sourcecode language=”html”]
<a href="#rocketsAreAwesome">Öppna</a>

<div class="mylightbox" id="rocketsAreAwesome">

<div class="size1">
<a href="#" class="close">Stäng</a>
<span>Watch this rocket! Its awesome!</span>
<div>Kan inkludera vad som helst här.</div>
<img src="internet" />
</div>

<a class="darkness" href="#">Stäng</a>
</div>
[/sourcecode]

[sourcecode language=”css”]
.mylightbox {
position: fixed;
left: -999em;
}
.mylightbox:target {
bottom: 0; left: 0; right: 0; top: 0;
}
.mylightbox:target a.darkness {
background: rgba(0, 0, 0, 0.50);
bottom: 0; left: 0; right: 0; top: 0;
position: fixed;
z-index: 9000;
display: block;
text-indent: -9999px;
}
.mylightbox:target > div {
position: fixed;
left: 50%;
top: 50%;
z-index: 10000;
}
.mylightbox .close {
background: url("closebox.png") transparent;
display: block;
height: 30px;
right: -15px;
position: absolute;
text-indent: -9999px;
top: -15px;
width: 30px;
}

.size1 {
width: 400px;
margin-left: -200px;
height: 300px;
margin-top: -150px;
}
[/sourcecode]
Det som jag också gjort är satt 2 olika länkar för att kunna stänga lightboxen. Båda pekar på # vilket då blir att vi inte har något target selected = den går tillbaka till att inte visa någon lightbox. En av dessa länkar använder vi som modalbakgrund och gör lika stor som skärmen, vid klick på den så selectar man också # och den försvinner. På samma sätt som jag här lagt modalerna utanför skärmen kan man ju ta display: none och toggla men det gör man väl som man vill.

Har även en klass som talar om storleken innehållet i min lightbox. Detta för att man ska kunna positionera det korrekt. Marginalen blir halva objektets bredd/höjd i offset då vi säger det ska ligga 50% från left/top.

Den här koden skulle alltså fungera på samtliga objekt som du döper till klassen .mylightbox oavsett vad de heter och du gör bara en länk för att peka ut dem. Smidigt? tycker det känns frammåt iaf. Mitt hat för lightboxes har precis stillats lite och med några enkla script kan man få detta att fungera i även äldre mer efterblivna webbläsare som ie7-ie8 etc. Sen har man ju CSS3 transitions om man vill göra det ännu mer intressant =)