[Arjen Markus] (17 february 2018) While working on [my first wapp-lication], I fantasized about the possibility of providing a graphical presentation of the function that the user types in besides simply a table of values. I have not figured out yet how to actually do that, basically my lack of knowledge about JavaScript (though: see the '''note''' below!), but I have figured out how to employ [Plotchart]. What is more: I need to change nothing about Plotchart itself, I merely had to replace the canvas widget I ordinarily use by a TclOO object that has the same if less functional interface.
The result is the program below:
* It defines a few commands that mimick Tk commands
* It defines a class called htmlCanvas that takes care of the canvas subcommands (note: it is rather geared to the use of canvases within Plotchart, so nothing really fancy and certainly not a "drop-in" replacement)
* It draws a simple graph - a parabolic functionHTML
The program writes the JavaScript commands for the plot to standard output, so redirect the output to an HTML file and show it in a browser.
Some remarks:
* I have not tried to cover the complete set of canvas features used by Plotchart. Many canvas features are actually simply ignored.
* I tried to do away with Tk, by defining a dummy package, but I need to do a bit more for this and I am a trifle impatient ;). That is an improvement to come.
* There is a lot of room for improvement, but then I have spent less than a day on this project.
****Note on [wapp]****
Richard Hipp has already solved the problem we were facing, so that will be a second version of this application.
======
# htmlcanvas.tcl --
# Class to emulate a Tk canvas in HTML
#
set auto_path [concat . $auto_path]
package require Plotchart
proc winfo {args} {
foreach {key value} $args {
switch -- $key {
"width" {
return 500
}
"height" {
return 500
}
default {
error "$args"
}
}
}
}
proc CorrectForAnchor {xt yt text anchor} {
switch -- $anchor {
"n" {
set yt [expr {$yt + 10}]
}
"e" {
set length [string length $text]
set xt [expr {$xt - 5 * $length}]
}
}
return [list $xt $yt]
}
::oo::class create htmlCanvas {
variable color
variable htmlcode
variable width
variable height
constructor {name args} {
variable color
variable htmlcode
variable width
variable height
set width 500
set height 500
foreach {key value} $args {
switch -- $key {
"-width" {
set width $value
}
"-height" {
set height $value
}
}
}
append htmlcode "
"
return $htmlcode
}
method create {type args} {
variable htmlcode
switch -- $type {
"text" {
set text ""
set anchor "c"
set rest [lassign $args xt yt]
foreach {key value} $rest {
switch -- $key {
"-text" {
set text $value
}
"-anchor" {
set anchor $value
}
"-fill" {
set fill $value
}
}
}
# Ignore the test string - "M" drawn at (0,0)
if { $xt == 0 && $yt == 0 && $text eq "M" } {
return
}
# Accept any other string
lassign [CorrectForAnchor $xt $yt $text $anchor] xt yt
my color $fill
append htmlcode "\nctx.fillText('$text', $xt, $yt);"
}
"rectangle" {
set rest [lassign $args x1 y1 x2 y2]
set tag ""
foreach {key value} $rest {
switch -- $key {
"-fill" {
my color $value
}
"-tag" {
set tag $value
}
}
}
# Ignore the masking rectangles
if { [string match "*mask*" $tag] ||
[string match "*titleback*" $tag] } {
return
}
# Accept the others
append htmlcode "\nctx.fillRect($x1,$y1,$x2,$y2)"
}
"line" {
set rest [lassign $args x1 y1 x2 y2]
foreach {key value} $rest {
if { $key eq "-fill" } {
my color $value
}
}
append htmlcode "\nctx.beginPath(); ctx.moveTo($x1,$y1); ctx.lineTo($x2,$y2); ctx.stroke();"
}
}
}
}
set c [htmlCanvas create c c]
set c [string trim $c :]
set p [::Plotchart::createXYPlot $c {0 100 20} {0 0.301 0.05}]
$p dataconfig data -color cyan
$p title "A simple parabola" ;# This gives a slight problem ...
$p xtext "X"
$p vtext "Y"
for {set x 0} {$x < 100} {incr x 5} {
$p plot data $x [expr {($x/100.0) * (1.0 - $x/100.0)}]
}
puts [$c emit]
======
<>Category Graphics|Category Internet