Clipping polygons paths in html5 canvas
*1* This application uses the canvas context clip() function to build a workshop for any polygon.
I used to make first an inside html buttons on the page.There is some security restrictions for
working from outside the page (vfp),for ex cannot open a new window to save canvas...
Input the spikes number of the polygon(sides).can be from 1 to >10000 and more.
Input the innerRadius fraction parameter (from 0 to 1 even more, can input until 10)
Input the lineWidth parameter and border color for the polygon border.
for inputs:type values and click on canvas to see the effect.
Can generate the PNG image or print it (this fi
All is tested on Windows8.1 only
Click on code to select [then copy] -click outside to deselect
*1* clipping polygons with html5 canvas
Local m.xpict,m.yhelp,m.myvar
m.xpict=Getpict() &&only for starting
m.xpict=Strtran(m.xpict,"\","/")
m.yhelp=yhelp()
TEXT to m.myvar textmerge noshow
<body scroll="no" bgcolor="black" oncontextmenu="window.close();return false;">
<canvas id="ycanvas1" width="<<sysmetric(1)>>" height="<<sysmetric(2)-50>>"></canvas><br>
<center><div>
<input type="text" id ="ospikes" value="7" title="Spikes 0--more 100)" style="width:50;" onchange="ydraw();">
<input type="text" id ="yr" value="0.5" title="innerRadius 0 to 1 to 10)" style="width:50;" onchange="ydraw();">
<input type="button" id ="osave" value="save as PNG" style="background-color:lime;color:red;" onclick="ysave();">
<input type="text" id ="ol" value="5" title="lineWidth 1--20.. )" style="width:50;" onchange="ydraw();">
<input type="button" id ="ocont" value="Rand Contour" style="background-color:lime;color:red;" onclick="ydraw();">
<input type="file" id="ximage" accept="image/x-png, image/gif, image/jpeg" value="<<m.xpict>>" onchange='ydraw();' />
<input type="button" id ="ohelp" value="Help" style="background-color:lime;color:red;" onclick="yhelp();">
<input type="button" id ="oclose" value="Exit" style="background-color:lime;color:red;" onclick="window.close();">
</div></center>
<script>
var canvas = document.getElementById("ycanvas1");
canvas.style.background="black";
var ctx = canvas.getContext("2d");
ydraw();
////////////////////////////////////////////////////////
function ydraw(){
ctx.fillStyle="black";
ctx.clearRect(0,0,canvas.width,canvas.height);
var cx=canvas.width/2;
var cy=canvas.height/2;
var spikes=document.getElementById("ospikes").value; //20;
var outerRadius=300;
var innerRadius=outerRadius*document.getElementById('yr').value;
var col='#'+(0x1000000+(Math.random())*0xffffff).toString(16).substr(1,6);
// Create an image element
var img = document.createElement('IMG');
img.id="img";
// Specify the src to load the image
img.src =document.getElementById("ximage").value; //"<<allt(m.xpict)>>";
//////////////////////////////////////////////////////
img.onload = function () {
// Save the state, so we can undo the clipping
ctx.save();
drawStar(cx, cy, spikes, outerRadius, innerRadius,col)
ctx.clip();
ctx.drawImage(img, 0, 0,canvas.width,canvas.height);
// Undo the clipping
ctx.restore();
}
}
////////////////////////////////////////////////////////
function drawStar(cx, cy, spikes, outerRadius, innerRadius,col) {
var rot = Math.PI / 2 * 3;
var x = cx;
var y = cy;
var step = Math.PI / spikes;
ctx.strokeSyle = "#000";
ctx.save();
ctx.beginPath();
ctx.moveTo(cx, cy - outerRadius)
for (i = 0; i < spikes; i++) {
x = cx + Math.cos(rot) * outerRadius;
y = cy + Math.sin(rot) * outerRadius;
ctx.lineTo(x, y)
rot += step
x = cx + Math.cos(rot) * innerRadius;
y = cy + Math.sin(rot) * innerRadius;
ctx.lineTo(x, y)
rot += step
}
ctx.lineTo(cx, cy - outerRadius)
ctx.closePath();
ctx.lineWidth=document.getElementById("ol").value;
ctx.strokeStyle=col;
ctx.stroke();
}
////////////////////////////////////////////////////////////////
function ysave () {
var c=document.getElementById("ycanvas1");
var d=c.toDataURL("image/png");
var w=window.open('about:blank','image from canvas');
w.document.write('<center><h2 style="background-color:yellow";color:maroon;width:500px">Right click on image to save as PNG (or print)</h2></center><br>'+"<img src='"+d+"' alt='from canvas'/>");
}
//////////////////////////
function yhelp(){
alert(<<m.yhelp>>);
}
</script>
ENDTEXT
Local apie
apie=Newobject("internetexplorer.application")
Set Safe Off
m.lcdest=Addbs(Sys(2023))+"test.html"
Strtofile(m.myvar,m.lcdest)
apie.Navigate(m.lcdest)
Declare Integer BringWindowToTop In user32 Integer
Try
With apie
.menubar=0
.Toolbar=0
.StatusBar=0
.fullscreen=1
BringWindowToTop(.HWnd)
.Visible=.T.
Endwith
Catch
Endtry
_Cliptext=m.myvar
Function yhelp()
TEXT to m.yhelp noshow
Choose an picture(PNG,JPG,Gif) on apie button dialog.
Input the spikes number of the polygon.can be from 1 to >10000 and more.
Input the innerRadious paramete (from 0 to 1 even more)
Input the lineWidth parameter for the polygon border width.
for inputs:type change value and click on canvas to see the effect.
Can generate the PNG image or print it (this fires a new window.Simply Rightclick to
fire the context menu (save,print).
the canvas is fullscreen and the image is stretched to canvas dimensions.
ENDTEXT
x="'*'"
For i=1 To Memlines(m.yhelp)
If !i=Memlines(m.yhelp)
x=x+ '+" '+Mline(m.yhelp,i)+'" +" \n" ' +Chr(13)
Else
x=x+'+" +'+Mline(m.yhelp,i)+'" +" \n" ' +Chr(13)
Endi
Endfor
Return m.x
Endfunc
This code is similar to the first above but uses a top level form (alwaysOnTop) to set all parameters and interact directly with the canvas through the IE fullscreen window.
the same settings are available and the same results also.
click on the green shape to show the form or collapse it.
Click on code to select [then copy] -click outside to deselect
*2*
Publi yform
yform=Newobject("yclip")
yform.Show
Read Events
return
*
Define Class yclip As Form
BorderStyle = 0
Top = 0
Left = 5
Height = 207
Width = 193
ShowWindow = 2
ShowTips=.T.
Caption = "yClip"
MaxButton = .F.
AlwaysOnTop = .T.
BackColor = Rgb(112,112,112)
ycl = 0
Name = "Form1"
Add Object command1 As CommandButton With ;
Top = 163, ;
Left = 25, ;
Height = 37, ;
Width = 97, ;
FontBold = .T., ;
FontSize = 11, ;
Caption = "Draw", ;
ForeColor = Rgb(0,0,255), ;
BackColor = Rgb(255,128,0), ;
Name = "Command1"
Add Object yhelp As Label With ;
AutoSize = .T., ;
FontBold = .T., ;
FontSize = 16, ;
BackStyle = 0, ;
Caption = "?", ;
Left = 5, ;
Top = 175, ;
ForeColor = Rgb(0,255,0), ;
mousepointer=15,;
Name = "yhelp"
Add Object shape1 As Shape With ;
Top = -1, ;
Left = 167, ;
Height = 205, ;
Width = 25, ;
BorderStyle = 0, ;
MousePointer = 15, ;
BackColor = Rgb(0,255,0), ;
Name = "Shape1"
Add Object spinner1 As Spinner With ;
Height = 25, ;
KeyboardHighValue = 5000, ;
KeyboardLowValue = 0, ;
Left = 82, ;
SpinnerHighValue = 5000.00, ;
SpinnerLowValue = 0.00, ;
Top = 9, ;
Width = 81, ;
Value = 5, ;
Name = "Spinner1"
Add Object label1 As Label With ;
AutoSize = .T., ;
FontBold = .T., ;
FontSize = 9, ;
BackStyle = 0, ;
Caption = "Spikes 0-5000", ;
Height = 16, ;
Left = 0, ;
Top = 12, ;
Width = 77, ;
ForeColor = Rgb(255,0,0), ;
Name = "Label1"
Add Object spinner2 As Spinner With ;
Height = 25, ;
Increment = 0.05, ;
InputMask = "99.999", ;
KeyboardHighValue = 10, ;
KeyboardLowValue = 0, ;
Left = 82, ;
SpinnerHighValue = 10.00, ;
SpinnerLowValue = 0.00, ;
Top = 50, ;
Width = 81, ;
Format = "R", ;
Value = 0.70, ;
Name = "Spinner2"
Add Object label2 As Label With ;
AutoSize = .T., ;
FontBold = .T., ;
FontSize = 9, ;
BackStyle = 0, ;
Caption = "InnerRadius", ;
Height = 16, ;
Left = 2, ;
Top = 53, ;
Width = 68, ;
ForeColor = Rgb(255,0,0), ;
Name = "Label2"
Add Object command2 As CommandButton With ;
Top = 84, ;
Left = 12, ;
Height = 25, ;
Width = 109, ;
FontBold = .T., ;
FontSize = 10, ;
Caption = "Picture", ;
MousePointer = 15, ;
BackColor = Rgb(0,255,0), ;
Name = "Command2"
Add Object command3 As CommandButton With ;
Top = 123, ;
Left = 1, ;
Height = 25, ;
Width = 109, ;
FontBold = .T., ;
FontSize = 10, ;
Caption = "Contour Color", ;
MousePointer = 15, ;
BackColor = Rgb(0,255,0), ;
Name = "Command3"
Add Object spinner3 As Spinner With ;
Height = 25, ;
KeyboardHighValue = 100, ;
KeyboardLowValue = 1, ;
Left = 112, ;
SpinnerHighValue = 100.00, ;
SpinnerLowValue = 1.00, ;
Top = 123, ;
Width = 50, ;
Value = 5, ;
tooltiptext="lineWidth",;
Name = "Spinner3"
Procedure ybuild
If !Vartype(apie)="O"
apie=Newobject("internetexplorer.application")
Endi
TEXT to m.myvar textmerge noshow
<body topmargin=0 leftmargin=0 bgcolor="black" scroll="no" onContextmenu="return false;" onload="ydraw();" >
<div>
<canvas id="ycanvas1" width="<<sysmetric(1)>>" height="<<sysmetric(2)-27>>" </canvas><br>
</div>
<center><div>
<input type="button" id ="osave" value="save as PNG" style="background-color:lime;color:red;" onclick="ysave();">
</div></center>
<script>
var canvas = document.getElementById("ycanvas1");
canvas.style.background="black";
var ctx = canvas.getContext("2d");
////////////////////////////////////////////////////////
function ydraw(){
ctx.fillStyle="black";
ctx.clearRect(0,0,canvas.width,canvas.height);
var cx=canvas.width/2;
var cy=canvas.height/2;
var spikes=<<_screen.spikes>>
var outerRadius=300;
var innerRadius=<<_screen.innerRadius>>*outerRadius;
var col="<<_screen.col>>";
// Create an image element
var img = document.createElement('IMG');
// Specify the src to load the image
img.src ="<<_screen.xpict>>"; //or "http://.....
//////////////////////////////////////////////////////
img.onload = function () {
// Save the state, so we can undo the clipping
ctx.save();
drawStar(cx, cy, spikes, outerRadius, innerRadius,col);
ctx.clip();
ctx.drawImage(img, 0, 0,canvas.width,canvas.height);
// Undo the clipping
ctx.restore();
}
}
////////////////////////////////////////////////////////
function drawStar(cx, cy, spikes, outerRadius, innerRadius,col) {
var rot = Math.PI / 2 * 3;
var x = cx;
var y = cy;
var step = Math.PI / spikes;
ctx.strokeSyle = "#000";
ctx.save();
ctx.beginPath();
ctx.moveTo(cx, cy - outerRadius)
for (i = 0; i < spikes; i++) {
x = cx + Math.cos(rot) * outerRadius;
y = cy + Math.sin(rot) * outerRadius;
ctx.lineTo(x, y)
rot += step
x = cx + Math.cos(rot) * innerRadius;
y = cy + Math.sin(rot) * innerRadius;
ctx.lineTo(x, y)
rot += step
}
ctx.lineTo(cx, cy - outerRadius)
ctx.closePath();
ctx.lineWidth=<<_screen.lineWidth>>
ctx.strokeStyle=col;
ctx.stroke();
}
////////////////////////////////////////////////////////////////
function ysave () {
//var c=document.getElementById("ycanvas1");
var d=canvas.toDataURL("image/png");
alert(d);
var w=window.open('about:blank','image from canvas');
w.document.write("<img src='"+d+"' alt='from canvas'/>");
//w.document.body.style.background="black";
}
</script>
ENDTEXT
Set Safe Off
m.lcdest=Addbs(Sys(2023))+"test.html"
Strtofile(m.myvar,m.lcdest)
apie.Navigate(m.lcdest)
Declare Integer BringWindowToTop In user32 Integer
Try
With apie
.menubar=0
.Toolbar=0
.StatusBar=0
.fullscreen=1
BringWindowToTop(.HWnd)
.Visible=.T.
Endwith
Catch
Endtry
_Cliptext=m.myvar
Endproc
Procedure Destroy
Try
apie.Quit
Release apie
Catch
Endtry
Endproc
Procedure Init
With _Screen
.AddProperty("spikes",5)
.AddProperty("innerRadius",0.8)
.AddProperty("xpict","")
.AddProperty("col","rgb(255,0,0)")
.AddProperty("lineWidth",5)
Endwith
_Screen.xpict=Strtran(_Screen.xpict,"\","/")
With Thisform
.MaxButton=.F.
.MinButton=.F.
Endwith
Publi apie
Endproc
Procedure command1.Click
Thisform.shape1.Click()
Thisform.ybuild()
Endproc
Procedure shape1.MouseLeave
Lparameters nButton, nShift, nXCoord, nYCoord
Endproc
Procedure shape1.MouseEnter
Lparameters nButton, nShift, nXCoord, nYCoord
Endproc
Procedure shape1.Click
Thisform.ycl=Iif(Thisform.ycl=0,1,0)
If Thisform.ycl=1
Thisform.Left=-0.9*Thisform.Width
Else
Thisform.Left=0
Endi
DoEvents
Endproc
Procedure spinner1.InteractiveChange
_Screen.spikes=This.Value
* thisform.command1.click
Endproc
Procedure spinner2.InteractiveChange
_Screen.innerRadius=This.Value
* thisform.command1.click
Endproc
Procedure spinner3.InteractiveChange
_Screen.lineWidth=This.Value
* thisform.command1.click
Endproc
Procedure command2.Click
m.xpict=Getpict()
_Screen.xpict=Strtran(m.xpict,"\","/")
Thisform.command1.Click
Endproc
Procedure command3.Click
m.xcolor=Getcol()
If Empty(m.xcolor)
m.xcolor=Rgb(255,0,0)
Endi
_Screen.Col="#"+Chrtran("123456","563412",Right(Trans[m.xcolor ,"@0" ],6))
Thisform.command1.Click
Endproc
Procedure yhelp.Click
TEXT to m.myvar noshow
this.code asks to a picture and draw it on canvas.this picture is stretched
to the canvas dimension
it asks for a polygon with parameters as follow:
-polygon spikes 0-5000 (and more)
-InnerRadius(outerRadius fraction) from 0-1-i limited to 10
-contour color
-contour lineWidth 1-100 and more
it draws the defined polygon on an internetexplorer.application window
-can save as (PNG,BMP) the built image.
-click on the green shape to show the form or collapse it.
ENDTEXT
Messagebox(m.myvar,0+32+4096,"Summary help")
Endproc
Enddefine
*
*-- EndDefine: yclip