加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

在PowerPoint中实现一个带撤销功能的3D模型旋转效果

(2022-04-01 17:09:53)
分类: 编程
刘瑞祥
  在PowerPoint里插入3D模型对象并且通过VBA控制其旋转的方法,想必大家已经会了吧?我想大家已经写出了设置3D对象绕各个轴正向和反向旋转的程序了。本文介绍一个技巧,来实现旋转的“撤销”功能,也就是说,当你不小心单击了某个旋转按钮后,即使你记不得误触了哪个按钮,也可以通过“撤销”按钮回到上一步,甚至可以多步撤销。类似这种“撤销”的功能在很多软件里都有,我们看如何用VBA来实现吧。
在PowerPoint中实现一个带撤销功能的3D模型旋转效果
  这种功能在其它语言里如何实现?大概需要某种“设计模式”或者堆栈一类的数据结构吧。然而VBA既没有求指针这种操作,也不是真正的面向对象,那我们就没有办法了吗?
  办法当然总是有的,我先说说思路:
  解决问题的关键在于我们要声明一个全局变量,也就是在全部语句之外(仍然是同一个模块里)声明一个字符型变量,用这个变量记录我们曾经按过哪些按钮,然后根据这个字符串实现撤销功能:
Private str_3D As String
  接下来我们分三个部分进行讲解,本文需要的前置知识已经写过了(单击这里)。
一、设置3D模型对象的旋转
  我们先来编写出正常的让3D模型对象旋转的语句,以X+和X-为例,语句如下:
Public Sub rX1()
    ActivePresentation.Slides(1).Shapes(2). Model3D.IncrementRotationX 5
    str_3D=str_3D & "A"
End Sub

Public Sub rX2()
    ActivePresentation.Slides(1).Shapes(2). Model3D.IncrementRotationX -5
    str_3D=str_3D & "B"
End Sub
  (以上用的是Slides(1).Shapes(2),是因为这个3D对象位于幻灯片第1页,序号是2,同页序号1的是幻灯片页面标题)
  对于Y+、Y-、Z+、Z-这些,我们的语句类似,但是有两点不同:
  一是IncrementRotationX要改成IncrementRotationY和IncrementRotationZ;
  二是前面的str_3D=str_3D & "A"及str_3D=str_3D & "B"意思是在原来的str_3D变量后面加一个字母来标志刚刚按过哪个按钮,而在实现Y+、Y-、Z+、Z-对应功能的语句里,str_3D变量后自然不能再加A、B而应该加其它字母(本例依次是C、D、E、F)了。
二、实现撤销功能
Public Sub unDo()
    Dim strR As String
    If str_3D = "" Then Exit Sub
    strR = Right(str_3D, 1)
    With ActivePresentation.Slides(1).Shapes(2).Model3D
        If strR = "A" Then
            .IncrementRotationX -5
        ElseIf strR = "B" Then 
            .IncrementRotationX 5
        ElseIf strR = "C" Then
            .IncrementRotationY -5
        ElseIf strR = "D" Then
            .IncrementRotationY 5
        ElseIf strR = "E" Then
            .IncrementRotationZ -5
        ElseIf strR = "F" Then
            .IncrementRotationZ 5
        End If
    End With
    str_3D = Left(str_3D, Len(str_3D) - 1)
End Sub
  上一段程序首先判断字符串str_3D是否为空,如果是空的就说明已经恢复到幻灯片刚放映时的状态,程序结束。否则,取str_3D的最后一个字符,根据所取的这个字符判断当初是怎么旋转的,然后反过来操作即可。最后要把这个字符串去掉最后一位。
三、如何一步复位,兼谈属性和方法
  细心的朋友已经看到前面的幻灯片页面里有个“初始化”按钮,怎么实现呢?难道需要一步步退回到最初的状态?这样执行起来会很慢的,但是我们可以这样编程:
Public Sub Init()
    With ActivePresentation.Slides(1).Shapes(2).Model3D
        .RotationX=0
        .RotationY=0
        .RotationZ=0
    End With
    str_3D = ""
End Sub
  大家可以看出,这里用到的是RotationX等“属性”,而非前面所用到的IncrementRotationX等“方法”。二者的区别是:属性一般被看作对象的一个值,可以进行设置,也可以进行读取,而方法被看作是对于对象的一个操作。比如某个现实中的学生,对他进行升留级操作是“方法”,而他所属的年级则是这个学生的“属性”;“迁户口”是一个方法,“户籍所在地”是一个属性。也就是说,方法名往往是动词,而属性名则是名词。要给某个属性赋值,可以用“对象名.属性(参数)=值”这样的语句,要把属性值赋给某个变量,则用“变量名=对象名.属性(参数)”这样的语句。而要使用方法,则只能采用"对象名.方法 参数"这样的语句。根据不同的属性和方法,其后的参数是可选的(本例里方法的后面有参数,属性的后面没有参数),但方法中的参数是不带括号的。
  具体到本文的例子,就我个人的体会,IncrementRotationX方法和RotationX属性(对应的还有IncrementRotationY方法和和RotationY属性,以及IncrementRotationZ方法和RotationZ属性)还有两个区别:
  首先,前者的参数是“变化量”,也就是“变化了多少”,后者是“变化到多少”;
  其次,前者的坐标系是固定在3D模型对象上的,随着对象的旋转,坐标轴也在旋转,后者则是不变的。如果用物理上的概念来比喻,前者好像是“质心坐标系”,后者好像是“实验室坐标系”。至于我这么理解对不对,就请读者来检验了。如果大家有更好的解释,也欢迎留言。

PS:下面三个图,左图是该模型对象初始位置的视图,缺口都在右上靠前方,中间的是利用方法来实现的绕三个轴各转30度,右边是利用属性实现绕三个轴各转30度(中图和右图是对相同初始位置的3D对象分别执行后的效果):
在PowerPoint中实现一个带撤销功能的3D模型旋转效果   在PowerPoint中实现一个带撤销功能的3D模型旋转效果
Public Sub r1()    '执行效果如中图
    With ActivePresentation.Slides(1).Shapes(2).Model3D
        .IncrementRotationX 30
        .IncrementRotationY 30
        .IncrementRotationZ 30
    End With
End Sub

Public Sub r2()    '执行效果如右图
    With ActivePresentation.Slides(1).Shapes(2).Model3D
        .RotationX = 30
        .RotationY = 30
        .RotationZ = 30
    End With
End Sub

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有