Premasagar Rose <http://premasagar.com>
Dharmafly <http://dharmafly.com>
Pablo is a small, open-source JavaScript library for SVG, the web standard for vector graphics.
Pablo is used for vector-based art, games, visualisations, responsive graphics and interfaces.
<line x1="5" y1="195" x2="295" y2="5" stroke="green" stroke-width="10"/>
Pablo.line({
x1: 5,
y1: 195,
x2: 295,
y2: 5,
stroke: 'green',
'stroke-width': 10
});
IE9+, Chrome, Firefox, Safari, Opera, mobile browsers
if (Pablo.isSupported){
/* Pablo code here */
alert('Yes!');
}
else {
/* Fallback content */
alert("Noo");
}
.svg()
Append an <svg>
element to an HTML element
var svg = Pablo('#mycontainer').svg({
width:300,
height:200
});
<div id="mycontainer">
<svg version="1.1" width="300" height="200"><svg>
</div>
Creates the specified element and attributes.
// Pablo.ELEMENT_NAME([attributes])
Pablo.circle({r:50})
// Pablo(elementName, attributes)
Pablo('circle', {r:50})
svg.circle({r:50})
Pablo.symbol()
.text()
.textPath().content('Olá!');
Creates this nested structure
<symbol>
<text>
<textPath>Olá!<textPath>
<text>
<symbol>
<line>
Pablo.line({
x1: 5,
y1: 195,
x2: 295,
y2: 5,
stroke: 'green',
'stroke-width': 10
});
<rect>
Pablo.rect({
x:10, y:10,
width:190, height:190,
fill: '#f6f',
stroke:'#006',
'stroke-width': 20,
'stroke-linejoin': 'round'
});
<circle>
Pablo.circle({
cx: 100,
cy: 100,
r: 90,
fill: '#ff3',
stroke:'#060',
'stroke-width': 20
});
<ellipse>
Pablo.ellipse({
cx: 160,
cy: 100,
rx: 150,
ry: 90,
fill: '#f93',
stroke:'#606',
'stroke-width': 20
});
<polygon>
Pablo.polygon({
points: '100,0 200,50 200,150 100,200 0,150 0,50',
fill: 'green'
});
<polyline>
Pablo.polyline({
points: '10,190 90,90 200,160 340,10',
stroke: '#d21034',
fill: 'none',
'stroke-width': 20
});
<path>
Pablo.path({
d: 'M 10 10 C 0 200, 200 200, 190 10',
fill: '#d21034'
});
☟
<path>
Pablo.path({
d: 'M 10 10 C 0 200, 200 200, 190 10',
fill: 'none',
stroke:'#d21034',
'stroke-width': 20,
'stroke-linecap': 'round'
});
<path>
Pablo.path({
d: 'm3,46l96,0m-48,41l47,46m-47,-46l-44,46m43,-101l0,55m14.5,-69c0,8 -6.5,14.5 -14.5,14.5c-8,0 -14.5,-6.5 -14.5,-14.5c0,-8 6.5,-14.5 14.5,-14.5c8,0 14.5,6.5 14.5,14.5z',
fill: 'none',
stroke:'#d21034',
'stroke-width': 6
});
<path>
<path>
<path>
<pattern>
☟
var bricks = Pablo.defs().pattern({
id: 'bricks',
width:44, height:48,
patternUnits: 'userSpaceOnUse',
fill: 'darkred'
});
bricks.rect({width:20, height:20});
bricks.rect({width:20, height:20, x:24});
bricks.rect({width:40, height:20, y:24});
svg.rect({
width:370,
height: 280,
fill:'url(#bricks)'
});
svg.circle({
r: 125,
cx: 125,
cy: 125,
fill: 'url(#bricks)'
});
<linearGradient>
☟
<linearGradient>
var gr = Pablo.defs().linearGradient({
id: 'mygradient',
x1: '0%',
y1: '100%',
x2: '100%',
y2: '0%'
});
gr.stop({offset:'5%', 'stop-color':'#006'});
gr.stop({offset:'95%','stop-color':'#0c9'});
<linearGradient>
Pablo.circle({
fill:'url(#mygradient)',
cx:80, cy:80, r:80
});
<linearGradient>
Pablo.rect({
fill:'url(#mygradient)',
width:80,
height:80,
x: 240,
y: 10
});
<linearGradient>
Pablo.polygon({
fill:'url(#mygradient)',
points: '100,300 200,0 300,300'
});
<clipPath>
☟
<clipPath>
// Append hexagon to a <clipPath>
svg.clipPath({id:'hex-clip'});
.polygon({points:'108,0 216,63 216,188 108,250 0,188 0,63'});
// Apply clip path to an element
svg.image({
width:631, height:283,
'clip-path':'url(#hex-clip)',
'xlink:href':'guernica.jpg'
});
<filter>
☞ demo
villain = Pablo.g({id:'villain'});
.polygon({id:'hat', points:'...'})
.append([eyes, moustache]);
with querySelectorAll
Pablo('circle.foo')
.attr('fill', 'red');
Inspired by jQuery & Underscore
circles = Pablo('circle.foo');
Pablo([
Pablo.path(),
Pablo.rect(),
Pablo.g()
]);
Pablo.circle()
.add(Pablo.rect());
Slice and dice
// Get the 4th wrapped element
circles.eq(3);
// Get the 4th DOM element
circles[0];
// More
circles.length;
circles.pop();
circles.last();
circles.slice(4,9);
circles.each(fn);
var array = collection.toArray();
each
, map
, every
, some
, reduce
, reduceRight
, filterElements
, indexOf
, lastIndexOf
whities = purplies
.map(function(el){
return Pablo.circle({
cx: Pablo(el).attr('cx'),
r: 8,
fill: 'white'
});
});
whities.after(purplies);
circles.toArray().map(function(el){
return el.getAttribute('cx');
});
// [55, 140, 195, 260]
.parent()
.children()
.prev()
.next()
.siblings()
.find(selector)
var div = Pablo('div.thingy')
.append(something)
.addClass('righteous')
.on('click', function(){
alert('I ❤ DOM');
});
Interaction: drag & drop, clicks, etc
circles.on('click', function(){
alert('Stop it');
});
.clone()
rect = svg.rect({
width:80, height:80,
fill:'red'
});
rect.clone()
.attr('x', 90)
.appendTo(svg);
.duplicate()
rect = svg.rect({
width:80, height:80,
fill:'red'
});
rect.duplicate(3)
.attr('x', [0, 90, 180, 270]);
to iterate changes through a collection
Pablo.circle({cy:30, r:30})
.duplicate(4)
.attr({
cx:[30, 90, 150, 210, 270],
fill: ['red', 'green', 'blue', 'orange', 'purple']
});
Pablo.circle({
cy: '50%',
fill: 'rgba(127, 159, 95, 0.2)',
stroke: '#777'
})
.duplicate(18)
.attr({ // i = element index
cx: function(el,i){return i*4+1+'%'},
r: function(el,i){return i+1+'%'}
});
.css()
.style()
shape.css({
opacity: 0.5,
fill: 'red',
cursor: 'pointer'
});
.transform()
.transformCss()
translate
scale
rotate
skewX
skewY
matrix
<animate>
, <animateTransform>
, <animateMotion>
<animateTransform>
<animateTransform>
train.animateTransform({
attributeName: 'transform',
type: 'translate',
from: 0,
to: 500,
dur: '2s',
fill: 'freeze'
});
<animateTransform>
<animateTransform>
shape.animateTransform({
attributeName: 'transform',
type: 'rotate',
from: 0,
to: 360,
dur: '48s',
repeatCount: 'indefinite'
});
var anim = Pablo.animateTransform({
// [...]
begin: 'indeterminate'
});
button.on('click', function(){
anim[0].beginElement();
});
var anim = Pablo.animateTransform({
// [...]
begin: 'other-anim.end'
});
Pablo.rect({
width: 100,
height: 100,
fill: 'darkblue'
})
.transition('opacity', '1s');
// Transitions whenever the opacity changes
.requestAnimationFrame()
Extend the collections API
Pablo.fn.height = function(){
return this.bbox().height;
};
Collections can use the new method
Pablo('#myelement').height();
<symbol>
& <use>
fishbowl = Pablo.symbol({
id:'fishbowl'
});
fishbowl.append(fish);
fishbowl.append(bowl);
instance = Pablo.use({x:7, y:20, 'xlink:href':'#fishbowl');
Give a namespace to a complex structure
Pablo.template('house', function(/* args */){
/* Code to draw a house */
});
Pablo.house({someOption:'foo'}, [...]);
.requestAnimationFrame()
elem.load('cat.svg', function(cat){
// ...
});
Import from:
On pablojs.com