inRm3D: 画板论坛's Archiver

xklppp 发表于 2014-10-14 13:06

几何画板下的编程思考:javascript

这个题目有点大,我没那么深的造诣,只是想说明我的看法:几何画板作为很多算法的形象演练,是个绝妙的工具。
    javascript 比起其他的算法语言 basic,c,c++,java... 以及各式各样的可视化编程语言 vc,vb,c#,F#...来说,使用起来更加轻松随意,其最终效果有过之而无不及。
    尽管 javascript 也有着庞大的支撑系统和繁复的应用环境,但我们将尽可能的避开那些繁文缛节,我们的目的是娱乐,开心就好。
    对于 html+css+javascript 里面的一些细枝末节和扩展,网上俯拾皆是,为了精简,我们这里的讨论将不以语言为中心,程序用到哪我们就讨论到哪。
    我们这就开始吧:(大家学习愉快!!!)
[attach]22555[/attach]
[attach]22556[/attach]

xklppp 发表于 2014-10-14 13:59

[attach]22559[/attach]
[attach]22560[/attach]

mjj_ljh 发表于 2014-10-14 16:54

我的脑细胞已经萎缩了。根本就跟不上大家的节奏,试着跟xklppp老师从头来一次。

xklppp 发表于 2014-10-14 18:04

[attach]22563[/attach]
[attach]22564[/attach]

inRm 发表于 2014-10-14 19:18

大赞。

lnszdzg 发表于 2014-10-14 20:27

但愿能跟上xklppp老师的步伐

lnszdzg 发表于 2014-10-14 20:32

但愿能跟上xklppp老师的步伐

xklppp 发表于 2014-10-14 22:14

[attach]22568[/attach]
[attach]22566[/attach]

xklppp 发表于 2014-10-15 00:01

[attach]22569[/attach]
[attach]22570[/attach]

xklppp 发表于 2014-10-15 01:29

[attach]22571[/attach]
    代码没有任何问题,思维惯性却让我们诧异:20+30 怎会等于 2030 呢?会的,程序的实际过程是:"20"+"30"="2030"。因为在放置 input 元素时,numA、numB 的 type 属性设置为 text,意为文本。为什么不设置为 type=number 呢?可以的,不过只有在 html5 中才行,当然还有其他的一些问题,这里不展开了。
    改写 showMess 函数:

    function showMess()
    {
        var a=numA.value;
        var b=numB.value;
        var c=a-b;
        var d=a*b;
        var e=a/b;
        a=parsInt(numA.value);
        b=parsInt(numB.value);
        var f=a+b;
        messBox.innerText="A-B="+c+"\n"+
                          "A*B="+d+"\n"+
                          "A/B="+e+"\n"+
                          "A+B="+f;
    }

    其中 parseInt 为 javascript 的内置方法(method 实际上就是函数),将文本转换为整型数值,与之相应的是 parseFloat 方法,将文本转换为浮点型数值。
    我们会发现,无论我们在两个输入框中输入什么内容,输出窗口是没有反应的,原因是 showMess 函数只是在浏览器打开网页后运行一次且仅一次。为此,我们需要在右边的窗口中增加一个输入元素:

    <input type=button value=刷新 onclick=showMess()>

    onclick 为单击鼠标时触发的事件。
    编程就是这样,刚解决了一个小问题,却又冒出来一堆的大问题。
[attach]22572[/attach]

changxde 发表于 2014-10-15 10:00

javascript 中的  “-,*,/” 都是按数值进行,“+”  就按字符处理,不可想象。

xklppp 发表于 2014-10-15 13:41

javascript 是一种宽松类型的语言。宽松类型意味着设计者不必显式地定义变量的数据类型。大多数情况下,javascript 将根据需要自动进行转换。例如,如果将一个数值添加到一个字符串,该数值将被系统自动转换为文本。
    在大型的软件开发中,我们最好还是不要享受这种语言的恩赐,原因有很多,主要的有两点:一是它很可能会在不经意间埋下不可预期的 bug;二是这种代码缺乏可移殖性。眼下,我们可以将 showMess 改成:
    function showMess()
    {
        var a=parseInt(numA.value);
        var b=parseInt(numB.value);
        var c=a-b;
        var d=a*b;
        var e=a/b;
        var f=a+b;
        messBox.innerText="A-B="+c+"\n"+
                          "A*B="+d+"\n"+
                          "A/B="+e+"\n"+
                          "A+B="+f;
    }
    尽管如此,showMess 的行为还是很怪异的,在输入框中输入数据时很吃力,我们应该提供一种机制,让用户的操作变得轻松一些。
    在往下走之前,这里有必要讨论一下程序设计的思维模式的问题:
    1.不管是哪一种语言,哪一种软件,解决同一个问题,所使用的语言、软件资源越少越好。
    2.不管遇到什么问题,最好不要往里钻,应该退一步,站得更高一点,看得更远一些。这个不大好理解,比方说:我们被一座金碧辉煌的殿堂所吸引,进到里面后很多人就出不来了,如果我们理智的退出来,站到更高更远的地方,我们将会看到更多的更辉煌的大殿。侠客行里的石破天改成金破天就索然无味了。
    3.程序设计时,不要被语言的规则所束缚,更多的应该遵循人的行为习惯。
    啰嗦了,请大家包容!!!
[attach]22573[/attach]

xklppp 发表于 2014-10-15 22:30

[attach]22577[/attach]
    javascript 是一种基于对象、事件驱动的编程语言,在输入框输入数据时,系统会触发
onchange 事件,如是,我们便可以编写一个函数,捆绑到这个事件上来,其目的是:当用户输入数据后,立马由该函数对输入的数据进行审核并校正,使输入框内的数据总是在可控的范围内,也就是数据的有效性验证:
    function dataVerify(obj,min,def,max,parseNum)
    {
        var n=parseNum(obj.value);
        if(isNaN(n)||n<min||n>max)n=def;
        obj.value=n;
    }
    这里,我们定义了一个 dataVerify 函数,它接收五个参数:
    obj:接受数据审核的对象
    min:输入框内允许的最小值
    def:通不过审核时设定的默认值
    max:输入框内允许的最大值
    parseNum:将文本转换为数值的系统方法(parseInt 或 parseFloat)
    这意味着我们可以将方法(函数)名作为参数在调用和被调用的函数之间进行传递,这一特性在
编制大型和复杂的程序时非常管用,有点像函数式编程。
    当 n=parseNum(obj.value) 将文本转换为数值出现异常时,isNaN(n)返回逻辑真 true,否则,返回逻辑假 false。
    现在,我们在两个输入框的 html 代码中加入 onchange 事件属性:
A=<input id=numA type=text size=16 value=20
   onchange=dataVerify(this,-1000000,20,1000000,parseInt)><br>
B=<input id=numB type=text size=16 value=30
   onchange=dataVerify(this,-1000000,30,1000000,parseFloat)><br>
    这里的 this 表示对象本身(有点像面向对象编程里的 this);对于 numA 我们传递了将文本转换为整型数值的方法 parseInt,而对于 numB 我们传递了将文本转换为浮点型数值的方法
parseFloat,此举并非程序需要,只是体验一下而已。
    相应的 showMess:
    function showMess()
    {
        var a=parseInt(numA.value);
        var b=parseFloat(numB.value);
        var c=a-b;
        var d=a*b;
        var e=a/b;
        var f=a+b;
        messBox.innerText="A-B="+c+"\n"+
                          "A*B="+d+"\n"+
                          "A/B="+e+"\n"+
                          "A+B="+f;
    }
    这里,留一个问题给大家:如果输入框内允许的最大最小值为 +∞-∞,该如何写代码呢?
[attach]22578[/attach]

xklppp 发表于 2014-10-16 19:07

[attach]22581[/attach]
    就 html 来说,对于 input 元素,我们可以通过 onmousewheel(鼠标滚轮)事件使用 javascript 来提供一种稍为高级一点的数据输入方式:
A=<input id=numA type=text size=16 value=20
  onchange=dataVerify(this,-1000000,20,1000000,parseInt)
  onmousewheel=dataVerify2(event.wheelDelta,10,this,-1000000,20,1000000,parseInt)><br>
B=<input id=numB type=text size=16 value=30
  onchange=dataVerify(this,-1000000,30,1000000,parseFloat)
  onmousewheel=dataVerify2(event.wheelDelta,0.1,this,-1000000,20,1000000,parseFloat)><br>
    系统触发各种鼠标事件后,会建立一个名为 event 的对象记录下鼠标的各种状态,鼠标向前滚动时 event.wheelDelta 大于零,反之小于零。这里的代码设定 numA 的变化幅度为±10,numB 的变化幅度为±0.1。这样,可以将 dataVerify2 写成如下的样子:
    function dataVerify2(d,dn,obj,min,def,max,parseNum)
    {
        var n=parseNum(obj.value)+dn*Math.abs(d)/d;
        if(isNaN(n)||n<min||n>max)n=def;
        obj.value=n;
    }
    这里 Math.abs 是 javascript 的内置对象 Math 的求绝对值的方法,所以,Math.abs(d)/d,将取值 1 或 -1,这样,代码就实现了输入框内的数值随着鼠标的滚动朝相应的方向变化。
[attach]22582[/attach]

xklppp 发表于 2014-10-16 22:08

比较一下 dataVerify 和 dataVerify2:
    function dataVerify(obj,min,def,max,parseNum)
    {
        var n=parseNum(obj.value);
        if(isNaN(n)||n<min||n>max)n=def;
        obj.value=n;
    }
    function dataVerify2(d,dn,obj,min,def,max,parseNum)
    {
        var n=parseNum(obj.value)+dn*Math.abs(d)/d;
        if(isNaN(n)||n<min||n>max)n=def;
        obj.value=n;
    }
    两个函数可以并作一个:
    function dataVerify(d,dn,obj,min,def,max,parseNum)
    {
        var n=parseNum(obj.value)+dn*Math.abs(d)/d;
        if(isNaN(n)||n<min||n>max)n=def;
        obj.value=n;
    }
    修改一下 numA 和 numB:
A=<input id=numA type=text size=16 value=20
      onchange=dataVerify(1,0,this,-1000000,20,1000000,parseInt)
  onmousewheel=dataVerify(event.wheelDelta,10,this,-1000000,20,1000000,parseInt)><br>
B=<input id=numB type=text size=16 value=30
      onchange=dataVerify(1,0,this,-1000000,30,1000000,parseFloat)
  onmousewheel=dataVerify(event.wheelDelta,0.1,this,-1000000,20,1000000,parseFloat)><br>
    当触发 onchange 事件并执行 dataVerify 时,dn*Math.abs(d)/d 恒等于零。
    至此,我们终于写出了一个颇具价值的 javascript 函数 dataVerify。这可是一劳永逸的业绩,在后面的复分形编程中,有着一大堆的参数,少了这段代码将是很难想像的。当然,我们可以把这个dataVerify 函数写得更复杂一些,功能更强大一些。
[attach]22583[/attach]

xklppp 发表于 2014-10-17 02:03

关于数据的输入,到现在暂且告一段落,接下来讨论作图,也即 html5 的画布 canvas。
    在此之前,我们稍事休息,有两个问题在这里说明一下:
    一、这里的讨论有一个默认的前提,那就是各位朋友应该对编程语言具备一定的知识,这种知识的来源有两个途径,首先,所有的编程语言都有相通的地方;其次,对于 html、css、javascript 这三种语言的细节,应该先作些功课,我手上倒是有些资料,打了个包,260 MB,可我不知道怎么传,如有需要,给个邮箱地址。
    二、解释一下本贴的主题“几何画板下的编程思考”。
    前面提到过,几何画板作为很多算法的形象演练,是个绝妙的工具,比方说,hilbert 曲线的制作,除了原生的字符串重写系统,其他的诸如,迭代、递归、矩阵都可以,但不怎么轻松。然而在几何画板里,通过逆向思维,把 hilbert 曲线的过程倒过来,竟然找到了一种既简单又巧妙的方法。各位老师的画板作品,更是让我心动,虽然弄不明白其中的数学原理,却使我明白了一个道理,我们原来编的程序都是那么生硬,是因为没有在数据可视化上下功夫。
    下面就是受几何画板的启发编写的万花曲线规(须在 ie10 下运行),如果可以继续的话,后面将以它为蓝本进行讨论。
[attach]22584[/attach]
[attach]22585[/attach]

lnszdzg 发表于 2014-10-17 10:13

感谢您的精彩文章,受益匪浅。
想索取您的资料,留个邮箱——[email]1043622345@qq.com[/email]
谢谢!

一线天 发表于 2014-10-17 16:39

赞一个!很有意义的研究,不过几何画板对javascript的支持比较有限吧,如果是在GerGebra上研究javascript会强大的多。

一线天 发表于 2014-10-17 16:51

再看了一遍,发现并不是几何画板支持javascript,而是单纯的javascript语言实现几何画板的部分效果。
而GerGebra是原生支持javascript并可以输出网页文件的,可以说做数学网络课件GerGebra是最佳选择。

myzam 发表于 2014-10-18 08:11

[b] [url=http://www.inrm3d.cn/redirect.php?goto=findpost&pid=44372&ptid=4831]1#[/url] [i]xklppp[/i] [/b]
不错。有意的工作。
不过我也说两点:
第1点:学习js代码最好的地方是网络上的w3cschool(w3c学校),我就是从那里起步的。
第2点:几何画板无法使用编程,这是几何画板的缺陷,同时也是优点,因为编程会让操作抽象化,但编程又可以让画板做更多更细腻的事情,几何画板的作者在这两者间做了选择,他选择了取消编程,采用形象化的操作。GGb可以支持js编程。
最后,对你的工作致敬。

页: [1] 2 3 4 5 6 7 8 9 10

Powered by Discuz! Archiver 7.0.0  © 2001-2009 Comsenz Inc.