Creating a basic Islamic ornament (star shape)
In this tutorial, we will learn how to create a basic Islamic ornament using Paper.js. Paper.js is a JavaScript library that allows us to create vector graphics in the browser. It is based on the HTML5 Canvas element and provides a clean and simple API for drawing and manipulating graphics.
Let's start creating a star shape. This is a basic step for creating a more complex ornament.
Creating a star shape with 6 folds
To get started, we need to create a hexagon. We use hexagon as a guide while we are building our 6-fold star shape. We put the hexagon centered at (200,160) with the radius of 120 pixels.
Draw a basic hexagon
project.currentStyle = {
strokeColor: 'black',
strokeWidth: 0.5,
};
var r = 4;
var center = new Point(200, 160);
var sides = 6;
var radius = 120;
var hexagon = new Path.RegularPolygon(center, sides, radius);
hexagon.rotate(30)
var c = new Path.Circle({center: center, radius: r, fillColor: 'red'})
var text = new PointText({
point: center + [0, 18],
content: 'center=(200,160)',
fontFamily: 'Courier New',
justification: 'center',
fontSize: 12
});
Starting from the middle of the each edge (shown in red), we draw a line to the center of the edge that are 2 next of the edge we are on (shown in blue). We then draw a line from the center of the hexagon to the opposite edge.
Connect two mid-edge points
project.currentStyle = {
strokeColor: 'black',
strokeWidth: 0.5,
};
var r = 4;
var center = new Point(200, 160);
// var c = new Path.Circle({center: center, radius: r, fillColor: 'red'})
var sides = 6;
var radius = 120;
var hexagon = new Path.RegularPolygon(center, sides, radius);
hexagon.rotate(30)
function angledBeam(point, towards, angle){
var vec = (towards - point).normalize(radius * 2.75) + point;
var line1 = new Path.Line({from: point, to:vec}).rotate(angle, point);
var line2 = new Path.Line({from: point, to:vec}).rotate(-angle, point);
return [line1, line2];
}
function mark(point){
new Path.Circle({center: point, radius: 5, fillColor: 'red'});
}
project.currentStyle.strokeWidth = 2;
var len = hexagon.segments.length;
for(var i=0; i<len; i++)
{
var mid = (hexagon.segments[i].point + hexagon.segments[(i+1)%len].point)/2
if(i==0)
{
angledBeam(mid, center, 30)
var c = new Path.Circle({center: mid, radius: r, fillColor: 'red'})
}
if(i==2 || i==4)
var c = new Path.Circle({center: mid, radius: r, fillColor: 'blue'})
}
We stop when we hit the edge we ended that blue points. We repeat this process for all the edges. We will end up with a star shape with 6 folds.
Repeat the process with other edges
project.currentStyle = {
strokeColor: 'black',
strokeWidth: 0.5,
};
var r = 4;
var center = new Point(200, 160);
// var c = new Path.Circle({center: center, radius: r, fillColor: 'red'})
var sides = 6;
var radius = 120;
var hexagon = new Path.RegularPolygon(center, sides, radius);
hexagon.rotate(30)
function angledBeam(point, towards, angle){
var vec = (towards - point).normalize(radius * 0.75) + point;
var line1 = new Path.Line({from: point, to:vec}).rotate(angle, point);
var line2 = new Path.Line({from: point, to:vec}).rotate(-angle, point);
return [line1, line2];
}
function mark(point){
new Path.Circle({center: point, radius: 5, fillColor: 'red'});
}
project.currentStyle.strokeWidth = 2;
var len = hexagon.segments.length;
for(var i=0; i<len; i++)
{
var mid = (hexagon.segments[i].point + hexagon.segments[(i+1)%len].point)/2
angledBeam(mid, center, 30)
// var c = new Path.Circle({center: mid, radius: r, fillColor: 'red'})
}
This is the basic shape we will use to create our ornament. Here actually we are creating a 6-fold star shape. In this star the angle between each fold is 60 degrees. We can prove that by drawing a line from the center of the hexagon to the center of the star, but it might a topic of another tutorial or you can do it yourself.
The point here is that we can create little bit of different 6-fold star shape by only changing the angle between each fold. We will use the same process to create more complex shapes. But I will leave that for another tutorial. The image below might give you an idea of what I am talking about.
Repeat the same process with smaller angle than 60 degrees
project.currentStyle = {
strokeColor: 'black',
strokeWidth: 0.5,
};
var r = 4;
var center = new Point(200, 160);
// var c = new Path.Circle({center: center, radius: r, fillColor: 'red'})
var sides = 6;
var radius = 120;
var hexagon = new Path.RegularPolygon(center, sides, radius);
hexagon.rotate(30)
function angledBeam(point, towards, angle){
var vec = (towards - point).normalize(radius * 0.76) + point;
var line1 = new Path.Line({from: point, to:vec}).rotate(angle, point);
var line2 = new Path.Line({from: point, to:vec}).rotate(-angle, point);
return [line1, line2];
}
function mark(point){
new Path.Circle({center: point, radius: 5, fillColor: 'red'});
}
project.currentStyle.strokeWidth = 2;
var len = hexagon.segments.length;
for(var i=0; i<len; i++)
{
var mid = (hexagon.segments[i].point + hexagon.segments[(i+1)%len].point)/2
angledBeam(mid, center, 24)
// var c = new Path.Circle({center: mid, radius: r, fillColor: 'red'})
}