v-model指令其实是Vue中的一个语法糖,通常用于表单数据的双向绑定,它背后做了两个操作:

1.v-bind 指令绑定一个value属性;

2.v-on 指令给当前DOM绑定input事件。

<input v-model="valueTest" />
/*等同于*/
<input :value="valueTest" @input="valueTest = $event.target.value" />
//input事件动态监听用户的输入,在界面上生成一个事件时,浏览器会生成一个event对象,表示事件的状态,其中就包含了用户输入得到信息。


在自定义组件中使用v-model实现数据双向绑定该如何操作呢?官方文档中有这么一句话:  默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event。  

所以默认情况下应该有额外的两个操作:

1.props  接收一个 value ;

2.this.$emit触发input事件,传入新值。

父组件中调用:

<test-component v-model=valueTest"></test-component>
/*相当于*/
<test-component :value=valueTest" @input="valueTest = arguments[0]"></test-component>

//arguments:Javascrip中每个函数都会有一个Arguments对象实例arguments,它引用着函数的实参,可以用数组下标的方式"[]"引用arguments的元素。arguments.length为函数实参个数,arguments.callee引用函数自身。

子组件:

<template>
<div>
<button @click="testClick">点击</button>
</div>
</template>
<script>
export default {
props: {
value: String //此处接收到的就是valueTest
},
methods: {
testClick() {
this.$emit('input', '传入的新值');
}
}
}
</script>


至此,默认情况下的自定义组件v-model的使用就完成了,那么非默认情况呢?

Vue自2.2.0版本后增加了model属性, 允许一个自定义组件在使用v-model时定制prop和event。

其意义在于,如果业务需要代码明确,区分出自定义事件,那么prop和event可以自定义是最好的选择,示例如下:

父组件中调用:

<test-component v-model=valueTest"></test-component>
/*相当于*/
<test-component :value=valueTest" @input="valueTest = arguments[0]"></test-component>

子组件:

<template>
<div>
<button @click="testClick">点击</button>
</div>
</template>
<script>
export default { props:{ noValue:"此时不需要接收value" }, model:{ prop:'noValue' event:'noInput' },
methods: {
testClick() {
this.$emit('noInput', '传入的新值');
}
}
}
</script>
  •  2021-04-14 16:38:09   125

今天使用Navicat连接Linux服务器(phpstudy面板)MySql失败并且报错如下:

2013- Lost connection to My SQL server at‘waiting for initial communication packet system error: 0“Internal error/check(Not system error)

因为之前一直都是通过phpMyAdmin来管理数据,所以一直没遇到这个问题。

通过百度答案几乎都是在my.cnf或者my.ini文件的[mysqld]下添加skip-name-resolve,我在尝试并且重启后仍然无效。

最后通过SSH通道连接,勾选使用SSH通道,输入服务器的主机ip和用户名和密码(不是mysql的帐号密码,而是服务器的)


最后把常规中的主机改为localhost,且输入MySQL的用户名和密码(此处的主机指向的localhost是服务器的localhost,而非电脑本地)。

  


  •  2020-04-16 12:20:11   620


当今天打开Linux服务器上部署的Laravel项目(逆光导航)时出现了如下报错:

Warning: require(): open_basedir restriction in effect. File(/www/admin/nav.mhbdng.cn_80/wwwroot/vendor/autoload.php) is not within the allowed path(s): (/www/admin/nav.mhbdng.cn_80/wwwroot/public/:/tmp/:/proc/) in /www/admin/nav.mhbdng.cn_80/wwwroot/public/index.php on line 24

Warning: require(/www/admin/nav.mhbdng.cn_80/wwwroot/vendor/autoload.php): failed to open stream: Operation not permitted in /www/admin/nav.mhbdng.cn_80/wwwroot/public/index.php on line 24

Fatal error: require(): Failed opening required '/www/admin/nav.mhbdng.cn_80/wwwroot/public/../vendor/autoload.php' (include_path='.:/usr/local/phpstudy/soft/php/php-7.1.31/lib/php') in /www/admin/nav.mhbdng.cn_80/wwwroot/public/index.php on line 24


报错原因:

重启网站后在根目录生成了.user.ini文件。


解决方案:

1.删除.user.ini文件:

//进入项目public目录
#cd public
//显示所有文件
#ls -a
//linux会默认隐藏 . 开头的文件和文件夹,-a命令使其显示
//此时文件列表里能看到.user.ini文件,将其删除
#rm .user.ini

此方案重启网站后还是会生成.user.ini文件,并且.user.ini文件用于防止脚本跨目录执行  ,如果你使用的是nginx则不推荐删除。

Tips:

.htaccess是伪静态环境配置文件,用于lamp。

.user.ini是lnmp文件,里面放的是你网站的文件夹路径地址。目的是防止跨目录访问和文件跨目录读取.


2.修改.user.ini文件

#cd public
#ls -a
vim .user.ini
//如果.user.ini没有修改权限则是文件被锁定了,先解锁
#chattr -i .user.ini
//显示如下内容
#open_basedir=/www/wwwroot/public/:/tmp/:/proc/
//删除public
#open_basedir=/www/wwwroot/:/tmp/:/proc/
//保存退出vim
# :wq
//最后锁定.user.ini文件让其不能修改
#chattr +i .user.ini


推荐第二种方案。

  •  2020-03-29 14:07:47   539

在使用Laravel框架的时候遇到一个需求,需要在代码中动态的修改.env文件中的邮箱信息。



百度后得到如下代码:

function modifyEnv(array $data) 
{
$envPath = base_path() . DIRECTORY_SEPARATOR . '.env';

$contentArray = collect(file($envPath, FILE_IGNORE_NEW_LINES));

$contentArray->transform(function ($item) use ($data){
foreach ($data as $key => $value){
if(str_contains($item, $key)){
return $key . '=' . $value;
}
}

return $item;
});

$content = implode($contentArray->toArray(), "\n");

\File::put($envPath, $content);
}

来源:脚本之家


但是发现缺少str_contains方法,此处补充str_contains方法如下:

    function str_contains($haystack, $needles)
{
if(is_array($needles))
{
foreach($needles as $needle)
{
if(is_array($needle))
{
if(self::str_contains($haystack, $needle))
{
return true;
}

return false;
}
elseif(preg_match("/\b$needle\b/i", $haystack) !== 0)
{
return true;
}
}
}else{
if(preg_match("/\b$needles\b/i", $haystack) !== 0)
{
return true;
}
}
return false;
}


  •  2020-01-13 11:04:40   646

 首先,我的界面是这样的:


我要做的工作是点击“显示/隐藏图表”按钮将这七个图表进行显示/隐藏。


在按钮上绑定好相应的脚本和函数:



需要让多对象同时显示/隐藏,为了方便,给七个图表相同的Tag,然后用GameObject.FindGameObjectsWithTag()同时控制七个图表显示/隐藏:



由于GameObject.FindGameObjectsWithTag()无法找到隐藏的对象,所以在脚本中我们要将七个图表对象先保存在变量中:

private GameObject[] _Charts;
private void Awake() {
_Charts = GameObject.FindGameObjectsWithTag("Chart");
}


然后在按钮绑定的单击事件(此处是上面图中的ShowHideChart()方法)中写上方法体:

for (int i = 0; i < _Charts.Length; ++i)
{
if (_Charts[i].activeSelf == false)
{
_Charts[i].SetActiveRecursively(true);
}else{
_Charts[i].SetActiveRecursively(false);
}
}


完整代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class ButtonFunction : MonoBehaviour
{
private GameObject[] _Charts;
private void Awake() {
_Charts = GameObject.FindGameObjectsWithTag("Chart");
}

public void ShowHideChart() {
for (int i = 0; i < _Charts.Length; ++i)
{
if (_Charts[i].activeSelf == false)
{
_Charts[i].SetActiveRecursively(true);
}

else
{
_Charts[i].SetActiveRecursively(false);
}
}
}
}


  •  2019-12-27 12:10:14   661

Unity版本:2018.4.11c1


1. 新建Shader-->PBR Graph文件,并双击在Shader Graph中打开;


2. 修改基本颜色:新建color参数并选择基本色,将参数拖到面板上连接至PBR Master上的Albedo属性上:




3. 使用纹理来控制透明度:新建纹理(Texture2D)参数,并选择纹理;由于PBR-->Alpha通道不接收纹理类型的输入,所以将纹理使用sample texture2D节点转换后再连接,并将模型改为透明:


4. 球形不好看效果,可以在右下角的预览面板右键-->Custom Mesh换个模型;


5. 此时的纹理是覆盖在模型上的,如果不需要覆盖在模型上而是需要从上到下相对于我们的视角覆盖在空间上再执行这一步操作:
            A. 新建节点Tiling And Offset,并把此节点的Out连接到刚才创建的sample texture2D面板的UV上;
            B. 将Tiling And Offset的UV脱出连接到新节点Screen Position上;
            C. 新建一个Vector2参数(可以设置x:1,y:3,按需求设置)来控制平铺,并拖入工作区连接到tiling的输入上;
            D. 控制偏移的y值可以制造滚动效果,我们可以设置使它随时间动:新建时间节点Time和乘法节点Multiply,并新建一个vector 1参数来与Time相乘达到控制滚动速度的效果。



6. 此时已经大体有全息的效果了。我们可以通过添加发光部分来增强效果:
            A. 新建color参数,Mode修改为HDR,再选择颜色设置强度,并放置到工作区;
            B. 新建Fresnel effect节点,它可以产生环形渐变的效果;
            C. 新建乘法节点Multiply,将color参数和Fresnel effect节点连接上去相乘;
            D. 将乘法节点的Out连接到PBR Master的Emission上。



7. 如果要给纹理线条也加上发光:sample texture2D面板的RGBA上再拉出一个输出到新建节点One Minus(接收一个纹理并把它的值翻转)上,再将这个One Minus节点的输出拉到新建节点Multiply上,把参数中的基本色拖到工作区中作为Multiply节点的另外一个参数。而Multiply节点的Out也想要链接到PBR Master的Emission上,所以我们先把上一步中和Emission链接的线删除掉,然后创建一个Add节点,将上一步中的乘法节点Multiply和这步的乘法节点Multiply链接到Add节点的输入上,最后将Add节点的输出链接到PBR Master的Emission上。



8. 添加闪烁光。
            A. 新建时间节点,链接到新建节点Random Range:seed(2)上;
            B. Random Range的Out链接到新建节点Comparison(比较)上Comparison属性选择Greater;
            C. Comparison的Out链接到新建节点Branch上;
            D. Branch的Out链接的新建节点Multiply上,将上一步中的Add的Out再拉一条链接到Multiply的另一个输入;
            E. Multiply的Out链接到PBR Master的Emission上。



9.完成,效果如下:


  •  2019-12-25 11:22:11   699
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraFollow : MonoBehaviour
{
public float sMouse = 2f;
public float sBoard = 1.2f;
public float sWheel = 10f;

void Update()
{
//滚轮实现镜头缩进和拉远
if (Input.GetAxis("Mouse ScrollWheel") != 0)
{
this.GetComponent<Camera>().fieldOfView = this.GetComponent<Camera>().fieldOfView - Input.GetAxis("Mouse ScrollWheel") * sWheel;
}
//按着鼠标右键实现视角转动
if (Input.GetMouseButton(1))
{
transform.Rotate(-Input.GetAxis("Mouse Y") * sMouse, Input.GetAxis("Mouse X") * sMouse, 0);
}
//按着鼠标右键实现位置移动
if (Input.GetMouseButton(0))
{
transform.Translate(-Input.GetAxis("Mouse X") * sBoard, -Input.GetAxis("Mouse Y") * sBoard, 0);
}

}
}


  •  2019-12-23 18:11:22   636

一、初始阶段

Awake: 始终在任何启动功能之前以及预制之后调用此功能被实例化。(如果GameObject在启动过程中处于非活动状态,则直到激活它为止,才会调用Awake。)

理解:创建游戏对象后Awake立即执行(早于Start),仅执行一次,用于初始化。


OnEnable : 脚本对象启用时执行。

理解:脚本对象一启用就立马执行,每次启用都会执行。

 

Start: 仅在启用脚本实例的情况下,在第一帧更新之前调用Start。对于添加到场景中的对象,将在Update之前在所有脚本上调用Start函数,以此类推。自然地,在游戏过程中实例化对象时不能强制执行此操作。

理解:创建游戏对象且脚本启用后执行,在Awake后面执行,仅执行一次,用于初始化。




二、逻辑阶段

FixedUpdate: 与Update相比,FixedUpdate通常被更频繁地调用。如果帧速率低,则可以每帧多次调用它;如果帧速率高,则可以在帧之间根本不调用它。所有物理计算和更新都在FixedUpdate之后立即进行。在FixedUpdate中应用运动计算时,不需要将值乘以Time.deltaTime。这是因为在可靠的计时器上调用了FixedUpdate,而与帧速率无关。

理解:每隔固定时间执行一次(时间可以修改,默认为0.02s一次)。适用于对物体做物理操作(移动,旋转......),不受渲染影响。


Update: 每帧调用一次更新。它是帧更新的主要功能。

理解:渲染帧执行,执行时间不固定。适用于处理游戏逻辑。 


LateUpdate: 更新完成后,每帧调用一次LateUpdate。LateUpdate开始时,Update中执行的所有计算都将完成。LateUpdate的常见用法是后续的第三人称相机。如果使角色移动并转到Update内部,则可以在LateUpdate中执行所有摄像机的移动和旋转计算。这将确保角色在摄像机跟踪其位置之前已完全移动。 

理解:在Update函数被调用后执行,适用于跟随逻辑。


三、结束阶段

OnDisable: 当行为变为禁用或不活动状态时,将调用此函数。


OnDestroy: 在对对象存在的最后一帧进行所有帧更新后调用此函数(对象可能会响应Object.Destroy或在场景关闭时被破坏)。

理解:当脚本销毁或者附属的游戏对象被销毁时调用。 


OnApplicationQuit:  在退出应用程序之前,将在所有游戏对象上调用此函数。在编辑器中,当用户停止播放模式时会调用它。


附Unity3D生命周期流程图:


  •  2019-12-16 10:47:55   687
 一.iframe子页面调用父页面函数

1.javascript

只需要写上window.praent就可以了:
//调用changeTab()函数: 
window.parent.changeTab();


子页面取父页面中的标签中的值:
//比如该标签的id为"aa": 
window.parent.document.getElementById("aa").value;


2.jQuery
//格式:$("父页面元素选择器" , parent.document);
$("#cli" , parent.document).click();


二.iframe父页面调用子页面函数

1.javascript 
//调用changeTab()函数:
document.getElementById('ifrtest').contentWindow.changeTab();


 2.jQuery
//调用changeTab()函数:
$("#cli")[0].contentWindow.changeTab();
  •  2019-07-25 10:15:09   878

Laravel在视图中使用{{ }}语法 来显示变量的内容的时候,会自动调用 PHP htmlspecialchars 函数来避免 XSS 攻击。所以,HTML标签就会被转义,造成如下结果:


代码:

<div class="layui-card" style="border-color: #FCF8E3">
<div class="layui-card-header" style="background-color: #FCF8E3">{{ $study->study_title }}</div>
<div class="layui-card-body">
{{ $study->study_content }}
</div>
</div>


渲染后的视图代码:



视图结果:



解决方法:

使用{!! !!}语法来替代{{ }}语法。{!! !!}语法显示未转义的数据。


代码:

<div class="layui-card" style="border-color: #FCF8E3">
<div class="layui-card-header" style="background-color: #FCF8E3">{{ $study->study_title }}</div>
<div class="layui-card-body">
{!! $study->study_content !!}
</div>
</div>


视图结果:


  •  2019-06-06 13:18:19   1277

今天使用Navicat连接Linux服务器(phpstudy面板)MySql失败并且报错如下:

2013- Lost connection to My SQL server at‘waiting for initial communication packet system error: 0“Internal error/check(Not system error)

因为之前一直都是通过phpMyAdmin来管理数据,所以一直没遇到这个问题。

通过百度答案几乎都是在my.cnf或者my.ini文件的[mysqld]下添加skip-name-resolve,我在尝试并且重启后仍然无效。

最后通过SSH通道连接,勾选使用SSH通道,输入服务器的主机ip和用户名和密码(不是mysql的帐号密码,而是服务器的)


最后把常规中的主机改为localhost,且输入MySQL的用户名和密码(此处的主机指向的localhost是服务器的localhost,而非电脑本地)。

  


  •  2020-04-16 12:20:11   620


当今天打开Linux服务器上部署的Laravel项目(逆光导航)时出现了如下报错:

Warning: require(): open_basedir restriction in effect. File(/www/admin/nav.mhbdng.cn_80/wwwroot/vendor/autoload.php) is not within the allowed path(s): (/www/admin/nav.mhbdng.cn_80/wwwroot/public/:/tmp/:/proc/) in /www/admin/nav.mhbdng.cn_80/wwwroot/public/index.php on line 24

Warning: require(/www/admin/nav.mhbdng.cn_80/wwwroot/vendor/autoload.php): failed to open stream: Operation not permitted in /www/admin/nav.mhbdng.cn_80/wwwroot/public/index.php on line 24

Fatal error: require(): Failed opening required '/www/admin/nav.mhbdng.cn_80/wwwroot/public/../vendor/autoload.php' (include_path='.:/usr/local/phpstudy/soft/php/php-7.1.31/lib/php') in /www/admin/nav.mhbdng.cn_80/wwwroot/public/index.php on line 24


报错原因:

重启网站后在根目录生成了.user.ini文件。


解决方案:

1.删除.user.ini文件:

//进入项目public目录
#cd public
//显示所有文件
#ls -a
//linux会默认隐藏 . 开头的文件和文件夹,-a命令使其显示
//此时文件列表里能看到.user.ini文件,将其删除
#rm .user.ini

此方案重启网站后还是会生成.user.ini文件,并且.user.ini文件用于防止脚本跨目录执行  ,如果你使用的是nginx则不推荐删除。

Tips:

.htaccess是伪静态环境配置文件,用于lamp。

.user.ini是lnmp文件,里面放的是你网站的文件夹路径地址。目的是防止跨目录访问和文件跨目录读取.


2.修改.user.ini文件

#cd public
#ls -a
vim .user.ini
//如果.user.ini没有修改权限则是文件被锁定了,先解锁
#chattr -i .user.ini
//显示如下内容
#open_basedir=/www/wwwroot/public/:/tmp/:/proc/
//删除public
#open_basedir=/www/wwwroot/:/tmp/:/proc/
//保存退出vim
# :wq
//最后锁定.user.ini文件让其不能修改
#chattr +i .user.ini


推荐第二种方案。

  •  2020-03-29 14:07:47   539

在使用Laravel框架的时候遇到一个需求,需要在代码中动态的修改.env文件中的邮箱信息。



百度后得到如下代码:

function modifyEnv(array $data) 
{
$envPath = base_path() . DIRECTORY_SEPARATOR . '.env';

$contentArray = collect(file($envPath, FILE_IGNORE_NEW_LINES));

$contentArray->transform(function ($item) use ($data){
foreach ($data as $key => $value){
if(str_contains($item, $key)){
return $key . '=' . $value;
}
}

return $item;
});

$content = implode($contentArray->toArray(), "\n");

\File::put($envPath, $content);
}

来源:脚本之家


但是发现缺少str_contains方法,此处补充str_contains方法如下:

    function str_contains($haystack, $needles)
{
if(is_array($needles))
{
foreach($needles as $needle)
{
if(is_array($needle))
{
if(self::str_contains($haystack, $needle))
{
return true;
}

return false;
}
elseif(preg_match("/\b$needle\b/i", $haystack) !== 0)
{
return true;
}
}
}else{
if(preg_match("/\b$needles\b/i", $haystack) !== 0)
{
return true;
}
}
return false;
}


  •  2020-01-13 11:04:40   646

Laravel在视图中使用{{ }}语法 来显示变量的内容的时候,会自动调用 PHP htmlspecialchars 函数来避免 XSS 攻击。所以,HTML标签就会被转义,造成如下结果:


代码:

<div class="layui-card" style="border-color: #FCF8E3">
<div class="layui-card-header" style="background-color: #FCF8E3">{{ $study->study_title }}</div>
<div class="layui-card-body">
{{ $study->study_content }}
</div>
</div>


渲染后的视图代码:



视图结果:



解决方法:

使用{!! !!}语法来替代{{ }}语法。{!! !!}语法显示未转义的数据。


代码:

<div class="layui-card" style="border-color: #FCF8E3">
<div class="layui-card-header" style="background-color: #FCF8E3">{{ $study->study_title }}</div>
<div class="layui-card-body">
{!! $study->study_content !!}
</div>
</div>


视图结果:


  •  2019-06-06 13:18:19   1277
因为本人毕业设计中需要用到excel表的导入导出,后台使用的ThinkPHP5框架,所以使用PhpSpreadsheet来完成该功能,此处记录导出功能遇到的问题。
先画个重点:PhpSpreadsheet中$writer -> save('php://output');虽然可以不保存直接下载excel文件,但如果我们是使用ajax和后台交互的话,excel文件是不会下载的。

这种时候,我想到的解决方式有三种:

1.不使用ajax。因为我之前的项目必须使用ajax,所以这种方式我就不介绍了,不使用ajax的话百度有大把方案可行;

2.$writer -> save('php://output')改为$writer -> save('filename.xlsx'),即不下载保存在服务器中,然后我们把文件路径返回,在ajax的成功回调函数中拉起下载。这个方法是我一开始的思路,但是想到下载之后还有清除服务器上的文件,好像搞得麻烦很多,所以我也没采用此方案;

3.在一番面向百度编程后,我发现了一个好东西——jquery.fileDownload.js,该js可以让我们使用ajax也能调起excel文件下载,刚好解决了我们的问题。


步骤:

1.页面中导入该js:



2.后台的excel导出功能的封装函数:

<?php
/*
*excel导入导出操作封装类
*/

namespace app\admin\controller;


//使用Spreadsheet类
use PhpOffice\PhpSpreadsheet\Spreadsheet;
//xlsx格式类
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
//可以生成多种格式类
use PhpOffice\PhpSpreadsheet\IOFactory;



class Office
{

/**
* 导出excel表
* $data:要导出excel表的数据,接受一个二维数组
* $name:excel表的表名
* $head:excel表的表头,接受一个一维数组
* $key:$data中对应表头的键的数组,接受一个一维数组
* 备注:此函数缺点是,表头(对应列数)不能超过26;
*循环不够灵活,一个单元格中不方便存放两个数据库字段的值
*/
public function outdata($name='默认表名', $data=[], $head=[], $keys=[])
{
$count = count($head); //计算表头数量

$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();

for ($i = 65; $i < $count + 65; $i++) { //数字转字母从65开始,循环设置表头:
$sheet->setCellValue(strtoupper(chr($i)) . '1', $head[$i - 65]);
}

/*--------------开始从数据库提取信息插入Excel表中------------------*/
foreach ($data as $key => $item) { //循环设置单元格:
//$key+2,因为第一行是表头,所以写到表格时 从第二行开始写
for ($i = 65; $i < $count + 65; $i++) { //数字转字母从65开始:
$sheet->setCellValue(strtoupper(chr($i)) . ($key + 2), $item[$keys[$i - 65]]);
$spreadsheet->getActiveSheet()->getColumnDimension(strtoupper(chr($i)))->setWidth(20); //固定列宽
}

}
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');//告诉浏览器输出07Excel文件
header('Content-Disposition: attachment;filename="' . $name . '.xlsx"');
header('Cache-Control: max-age=0');//禁止缓存
header('Set-Cookie: fileDownload=true; path=/');
$writer = new Xlsx($spreadsheet);
$writer -> save('php://output');

//释放内存,防止内存泄露:
$spreadsheet->disconnectWorksheets();
unset($spreadsheet);
exit;
}
}


3.使用jquery.fileDownload.js传输数据下载excel:

function excelOutputStuList(res) {
    //res为我需要导出到excel表中的数据,因为我是先读取数据在页面上展示,展示页面有导出excel按钮,此变量为该按钮传来的页面上展示的所有数据。
    var index = layer.confirm('确定导出课程学生列表?', {
btn: ['确定','取消']
}, function(){
$.fileDownload('/admin.php/course/outputStuList', {
httpMethod: 'POST', /*我在调试时报错发现后台接收到的数据是[object object],[object object]形式的,无法解析; *所有在这里我用JSON.stringify(res)把传去后台的数据转换为json字符串,后台再使用json_decode($data,TRUE)转换为数组。
*/ data: 'data=' + JSON.stringify(res),
successCallback: function() {
layer.close(index);
},
failCallback: function() {
layer.msg('加载中..');
}
});
});
}


4.course控制器中的outputStuList()方法:

//excel导出课程学生列表
public function outputStuList(){
$data = request()->param('data');//json字符串 /*将json字符串转换为数组需要加第二个参数'TRUE',因为默认json_decode()函数第二个参数为FALSE,会将json字符串转换为对象*/ $res = json_decode($data,TRUE);
$excel = new Office();
//设置表头:
$head = ['学号','英文名','中文姓名','班级','国籍'];
//数据中对应的字段,用于读取相应数据:
$keys = ['stu_id', 'en_name', 'cn_name', 'class', 'nationality']; //调用封装的excel导出方法outdata($name='默认表名', $data=[], $head=[], $keys=[]);

$excel->outdata($data[0]['course_name'].'学生列表', $res, $head, $keys);
}
注:json_encode() 对变量进行JSON编码;json_decode() 对JSON数据进行解码,转换为PHP变量。


至此,excel成功导出!


  •  2019-03-30 22:41:05   1378

  因为本人毕业设计选题是留学生教务管理系统,使用的是TP5框架,而在做的过程中,需要用户(留学生)能够进行多语言的切换,所以详细看了TP5的文档也百度查阅了一些资料,在这记录一下。

  首先,在配置文件中开启多语言模块:

// 默认语言
'default_lang'=> 'zh-cn',

//多语言开启
'lang_switch_on' => true, //语言列表
'lang_list' => ['zh-cn','en-us'],

  在这里,我就要自己写入en-us.php文件,关于此文件位置,文档里是这么说的:


在我的项目中我放在了模块下面:


然后en-us.php语言文件定义采用返回数组方式:

return [
'HomePage' => '网站首页',
'RecruitStudents' => '本科招生',
'Student status' => '学籍管理',
'Exam Manage' => '考试管理',
'Practice Teaching' => '实践教学',
'educational technology' => '教育技术',
'Download Area' => '下载区'
];

在视图文件中用{:lang()}标签渲染关键字:

//语言切换按钮

<div type="button" lang='cn' class='cn_en'>{:lang('Chinese')}</div>
<div type="button" lang='en' class='cn_en'>{:lang('English')}</div>
<nav>
<ul>
<li><a href="{:url('index/index')}">{:lang('HomePage')}</a></li>
<li><a href="#">{:lang('RecruitStudents')}</a></li>
<li><a href="#">{:lang('Student status')}</a></li>
<li><a href="#">{:lang('Exam Manage')}</a></li>
<li><a href="#">{:lang('Practice Teaching')}</a></li>
<li><a href="#">{:lang('Practice Teaching')}</a></li>
<li><a href="#">{:lang('educational technology')}</a></li>
<li><a href="#">{:lang('Download Area')}</a></li>
</ul>
</nav>

在控制器中写入语言切换的方法(如果多页面都要切换建议写入公共父类控制器中,此处我写在了common/Base.php中):

class Base extends Controller
{
public function lang() {
switch ($_GET['lang']) {
case 'cn':
cookie('think_var', 'en-us');
break;
case 'en':
cookie('think_var', 'zh-cn');
break;
//其它语言

default:
cookie('think_var','zh');

}
}
}

然后,当我们点击语言按钮的时候,通过Ajax访问控制器中的lang()方法:

<script>
$('.cn_en').click(function () {
var data = {'lang': $(this).attr('lang')} //Index控制器继承自Base.php $.get("{:url('Index/lang')}", data, function () { //页面刷新 location.reload();
})
})
</script>

到此,我们参照官方手册进行的多语言切换就算完成了,但如果遇到默认语言没有反应,跳转页面之后,也没有检测当前的语言的BUG的话,修改 thinkphp/library/think/Lang.php 里面的detect()自动检测语言方法:

public static function detect()
{
// 自动侦测设置获取语言选择
$langSet = Config::get('default_lang');
if (isset($_GET[self::$langDetectVar])) {
// url中设置了语言变量
$langSet = strtolower($_GET[self::$langDetectVar]);
Cookie::set(self::$langCookieVar, $langSet, 3600);
} elseif (Cookie::get(self::$langCookieVar)) {
// 获取上次用户的选择
$langSet = strtolower(Cookie::get(self::$langCookieVar));
} elseif ($langSet) {
// 获取默认语言
Cookie::set(self::$langCookieVar, $langSet, 3600);
} elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
// 自动侦测浏览器语言
preg_match('/^([a-z\d\-]+)/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches);
$langSet = strtolower($matches[1]);
Cookie::set(self::$langCookieVar, $langSet, 3600);
}
if (empty(self::$allowLangList) || in_array($langSet, self::$allowLangList)) {
// 合法的语言
self::$range = $langSet;
}
return self::$range;
}

效果截图:



  •  2019-01-15 13:53:18   672
  • 在我们完善一个网站的时候,会遇到上传头像、文档、压缩文件等等问题,html中用表单的 input:type="file"来把文件信息传递给后台都是众所周知的。
  • 那么在后台应该怎么处理呢?
  • php在处理交互方面有天然的优势,自然有强大的函数来处理“上传文件”。 


1.服务器端php.ini文件配置:


2.html的form表单:

<form action="doAction.php" method="post" enctype="multipart/form-data">
请选择文件:
<input type="file" name="myFile"><br>
<input type="submit" value="上传文件">
</form>

注意:1)表单必须为post方式提交;

          2)form中必须有 enctype="multipart/form-data" 属性


3.在doAction.php中先打印上传文件信息:

  //$_FILES:文件上传变量

print_r($_FILES);
exit();


网页信息: 

 


其中,myFile是form表单中input="file"的name属性的值。

解释:[name]:上传文件的原文件名;

          [type]:上传文件的属性;

          [tmp_name]:上传文件的临时保存目录及临时保存文件名;

          [error]:上传错误信息;

          [size]:上传文件大小。


[error]错误信息说明:  



4.doAction.php:  

<?php
header("content-type:text/html;charset:utf-8");//头信息
//1.通过$_FILES文件上传变量接收上传文件信息
$fileInfo = $_FILES['myFile'];
$filename = $fileInfo['name'];
$type = $fileInfo['type'];
$tmp_name = $fileInfo['tmp_name'];
$size = $fileInfo['size'];
$error = $fileInfo['error'];
//2.判断错误号,只有为0或者是UPLOAD_ERR_OK,没有错误发生,上传成功
if($error === UPLOAD_ERR_OK){
//上传成功将服务器上的临时文件移动到指定目录下(两种方式)
//move_uploaded_file($tmp_name,$destination):将服务器上的临时文件移动到指定目录下。成功返回true,否则返回false
//copy($src,$dst):将文件拷贝到指定目录,拷贝成功返回true,否则返回false
if(move_uploaded_file($tmp_name,"uploads/".$filename)){
echo "文件".$filename."上传成功";
}else{
echo "文件".$filename."上传失败";
}
}else{
//匹配错误信息
switch($error){
case 1:
echo '上传文件超过了php配置文件中upload_max_filesize选项的值';
break;
case 2:
echo '超过了表单MAX_FILE_SIZE限制的大小';
break;
case 3:
echo '文件部分被上传';
break;
case 4:
echo '没有选择上传文件';
break;
case 6:
echo '没有找到临时目录';
break;
case 7:
case 8:
echo '系统错误';
break;
}
}



转自博主PHP中文网博客 —— 吾生也有涯,而知也无涯
  •  2019-01-01 22:52:19   1021

首先,我们拆分一下验证码的组成: 

1)一个长方形的底图

2)验证码的内容(数字,数字+英文,中文)

3)各色的干扰点

4)长短颜色不一的干扰线段


下面,我们就拆分出来的这四点一一实现:

1.长方形的底图   

  我们所见的验证码一般都是一个100*30px的底图,有的中文验证码底图会大一点(200*60px),而这个底图是如何来的呢?

    在php语言中,有关于图像的处理有专门的函数库--GD库,不了解的先查询手册---php-图像处理和 GD

    了解该库后,我们还要确保自己的php中带有该库且该库开启。一般php都会带有且默认开启。我们可以用phpinfo();函数查看是否有该库存在,如果GD库已有但未开启则需要在php.ini extension=php_gd2.dll前面的分号去掉,重启apache。

    制作验证码所需的该GD库函数如下:

imagecreatetruecolor(int $width , int $height) — 新建一个真彩色图像(网页黑色背景);

imagecolorallocate( resource $image , int $red , int $green , int $blue ) — 为一幅图像分配颜色(RGB);

imagefill(resource $image , int $x , int $y , int $color ) — 区域填充(在$image上从坐标$x,$y处开始填充颜色$color);

imagestring(resource $image , int $font , int $x , int $y , string $s , int$col) — 水平地画一行字符串( 用 $col 颜色将字符串 $s 画到 $image 所代表的图像的$x,$y 坐标处);

imagettftext( resource $image , float $size , float $angle , int $x , int$y , int $color , string $fontfile , string $text)— 用 TrueType 字体向图像写入文本($angle表示字符偏转的角度)

imagesetpixel(resource $image , int $x , int $y , int $color) — 画一个单一像素点(在 $image 图像中用 $color 颜色在$x,$y 坐标上画一个点),即验证码上的干扰点;

imageline(resource $image , int $x1 , int $y1 , int $x2 , int $y2 , int$color) — 画一条线段(两点确定一条直线,用于验证码干扰线段);

imagepng(resource $image , string $filename) — 以 PNG 格式将图像输出到浏览器或文件(将 GD 图像流($image)以 PNG 格式输出到标准输出(通常为浏览器),或者如果用$filename 给出了文件名则将其输出到该文件。)

imagedestroy(resource $image) — 销毁一图像(资源销毁)

上面这些函数,足够完成我们的验证码,我们先完成验证码底图的制作: 

<?php
session_start();//开启session。session功能保存验证码内容用于验证输入验证码是否正确

$image = imagecreatetruecolor(100,30);//生成一个100*30px的真彩色图像
$bgcolor = imagecolorallocate($image,255,255,255);//白色
imagefill($image,0,0,$bgcolor);//将$image完全填充为白色,即白色底图

2.验证码的内容(数字,数字+英文,中文)  

 100*30底图完成后,我们应在底图上添加验证码内容:

        a.数字验证码:

$captch_code = '';//保存验证码字符串,后面存入session用于session验证
//验证码随机四个数字
for ($i=0;$i<4;$i++){
$fontsize = 6;//使用字体
$fontcolor = imagecolorallocate($image,rand(0,120),rand(0,120),rand(0,120));//数字颜色,因为底图为白色,所以四个数字随机区域为深色区域
$fontcontent = rand(0,9);//0-9随机数字
$captch_code .= $fontcontent;//字符串拼接到$captch_code

$x=($i*100/4) + rand(5,10);//数字在底图上的x坐标,利用变量$i使数字保持间距
$y=rand(5,10);//y坐标

imagestring($image,$fontsize,$x,$y,$fontcontent,$fontcolor);//将数字$fontcontent以颜色$fontcolor、字体大小$fontsize画到$image的$x,$y处
}
$_SESSION['authcode'] = $captch_code;//保存验证信息,等待校验

        b.数字+字母验证码: 

$captch_code = '';//保存验证码字符串,后面存入session用于session验证
//数字字母混合
for ($i=0;$i<4;$i++){
$fontsize = 6;
$fontcolor = imagecolorallocate($image,rand(0,120),rand(0,120),rand(0,120));
$data = 'qwertyuiplkjhgfdsazxcvbnm123456789';//所有数字字母组成的字符串,为用户考虑去除难辨识的o和0;
$fontcontent = substr($data,rand(0,strlen($data)),1);//从$data中随机取出一个字符
$captch_code .= $fontcontent;//字符串拼接到$captch_code

$x=($i*100/4) + rand(5,10);
$y=rand(5,10);

imagestring($image,$fontsize,$x,$y,$fontcontent,$fontcolor);
}

$_SESSION['authcode'] = $captch_code;//保存验证信息

        c.中文验证码:

        注意,中文验证码必须导入支持中文的字体文件,windows系统可以在控制面板-字体中查找。

$captch_code = '';//保存验证码,用于session验证

$fontface = 'simkai.ttf';//字体文件
//汉字库,就是可能随机出现在底图上的所有中文内容
$str = "肥哦富农卫生费呢哦肥婆飞马珀耳风光迷人惠恩或嗯哦分配热攻击内容个人哦法二夫人很愉快热望特如果以后突然语句一进门就十足的傻瓜他会放过冰女冰女并承诺纷纷热狗后台交互同意木有就如同过河去啊封闭设备覅为法国梧桐耶夫北京市的发表都被你为防备分别是的小蜜蜂内裤我放不下的尽快发呢我尽快发布弄撒的烦恼腹部欸数量";
$strdb = str_split($str,3); //把字符串切割成数组,一个汉字占用三个字节。

//四个中文验证码
for ($i=0;$i<4;$i++){
$fontcolor = imagecolorallocate($image,rand(0,120),rand(0,120),rand(0,120));

$index = rand(0,count($strdb)-1);//产生随机数,$strdb下标是从0开始的,所以count()的值-1.
$cn = $strdb[$index];//随机选取汉字
$captch_code .= $cn;//汉字拼接到$captch_code,用于验证

//imagestring()函数不支持中文,此处改用imagettftext();
imagettftext($image,mt_rand(20,24),mt_rand(-60,60),(40*$i+20),mt_rand(30,35),$fontcolor,$fontface,$cn);
}
$_SESSION['authcode'] = $captch_code;//保存验证信息

3.各色的干扰点  

验证码为防止被机器识别,还应添加干扰信息,此处添加干扰点: 

//增加干扰元素(点),干扰点不可太少也不应太多,200适中
for ($i=0;$i<200;$i++){
$pointcolor = imagecolorallocate($image,rand(50,200),rand(50,200),rand(50,200));//干扰点的颜色不应该干扰用户正常阅读验证码内容,所以随机浅色区域
imagesetpixel($image,rand(1,99),rand(1,29),$pointcolor);
}

4.长短颜色不一的干扰线段  

更进一步可添加干扰线段: 

//干扰元素(线)
for ($i=0;$i<3;$i++){
$linecolor = imagecolorallocate($image,rand(80,200),rand(80,200),rand(80,200));
imageline($image,rand(1,99),rand(1,29),rand(1,99),rand(1,29),$linecolor);
}

至此,一个验证码的四个基本组成部分我们便完成了,我们可以查看一下验证码是否正常输出: 

header('content-type:image/png');//输出前添加文件头信息
imagepng($image);

//end 资源销毁
imagedestroy($image);

我们以数字+英文验证码为例:  

 

 正常输出,每次刷新改变:


验证码的制作到此算是基本完成了。接下来就是验证表单提交的验证码是否正确:

表单form.php:

<form action="captcha_check.php" method="post">
<!-- 验证码路径添加一个随机数参数,防止路径图片被缓存-->
验证码:<img src="captcha.php?r=<?php echo rand() ?>"><br>
请输入验证码:<input type="text" name="captcha"><br>
<input type="submit" value="提交">
</form>

接收验证captcha_check.php: 

<?php
session_start();

//$_REQUEST接收用户输入的验证码
if ($_REQUEST['captcha'] == $_SESSION['authcode']){
echo '验证码正确';
}else{
echo '验证码错误';
}

结果: 




转自博主PHP中文网的博客——吾生也有涯,而知也无涯

 

  •  2019-01-01 20:42:10   924

平时写前端经常会写到表单,而表单的label标签会因为字符数的长度不一样而造成对不齐,如图:


这种时候,我们就需要使用中文占位符来使表单对齐。

&#32; == 普通的英文半角空格;
&#160; == &nbsp; == &#xA0; == no-break space (普通的英文半角空格但不换行);
&#12288; == 一个中文宽度;
&#8194; == &ensp; == 半个中文宽度;
&#8195; == &emsp; == 一个中文宽度;
&#8197; == 四分之一中文宽度;


对齐代码:

<label for="pwd">新 密 码:</label>


对齐后:


  •  2019-03-20 16:15:24   712

产生原因  

模板文件生成html文件之后会在body开头处加入一个可见的控制符,

导致页面头部会出现一个空白行。原因是页面的编码是UTF-8 + BOM。 

这种编码方式一般会在windows操作系统中出现,

比如WINDOWS自带的记事本等软件,在保存一个以UTF-8编码的文件时,

会在文件开始的地方插入三个不可见的字符(0xEF 0xBB 0xBF,即BOM)。

它是一串隐藏的字符,用于让记事本等编辑器识别这个文件是否以UTF-8编码。对于一般的文件,这样并不会产生什么麻烦。但对于 PHP来说,BOM是个大麻烦。因为PHP并不会忽略BOM,所以在读取、包含或者引用这些文件时,会把BOM作为该文件开头正文的一部分。根据嵌入式语言的特点,这串字符将被直接执行(显示)出来。由此造成即使页面的 top padding 设置为0,也无法让整个网页紧贴浏览器顶部,因为在html一开头有这3个隐藏字符! 


解决办法

最好写代码的时候用编译器编写,不要用记事本编写代码。

出现出错后,下载一个UltraEdit

打开UltraEdit,在UltraEdit里打开带隐藏字符的文件,然后另存为,窗口最下面最左边有一个选项,显示默认,打开下拉条选择utf-8无BOM,然后回车,去你保存的文件位置找到,拖拽到项目里,完成。

  •  2019-02-04 01:01:14   1007

v-model指令其实是Vue中的一个语法糖,通常用于表单数据的双向绑定,它背后做了两个操作:

1.v-bind 指令绑定一个value属性;

2.v-on 指令给当前DOM绑定input事件。

<input v-model="valueTest" />
/*等同于*/
<input :value="valueTest" @input="valueTest = $event.target.value" />
//input事件动态监听用户的输入,在界面上生成一个事件时,浏览器会生成一个event对象,表示事件的状态,其中就包含了用户输入得到信息。


在自定义组件中使用v-model实现数据双向绑定该如何操作呢?官方文档中有这么一句话:  默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event。  

所以默认情况下应该有额外的两个操作:

1.props  接收一个 value ;

2.this.$emit触发input事件,传入新值。

父组件中调用:

<test-component v-model=valueTest"></test-component>
/*相当于*/
<test-component :value=valueTest" @input="valueTest = arguments[0]"></test-component>

//arguments:Javascrip中每个函数都会有一个Arguments对象实例arguments,它引用着函数的实参,可以用数组下标的方式"[]"引用arguments的元素。arguments.length为函数实参个数,arguments.callee引用函数自身。

子组件:

<template>
<div>
<button @click="testClick">点击</button>
</div>
</template>
<script>
export default {
props: {
value: String //此处接收到的就是valueTest
},
methods: {
testClick() {
this.$emit('input', '传入的新值');
}
}
}
</script>


至此,默认情况下的自定义组件v-model的使用就完成了,那么非默认情况呢?

Vue自2.2.0版本后增加了model属性, 允许一个自定义组件在使用v-model时定制prop和event。

其意义在于,如果业务需要代码明确,区分出自定义事件,那么prop和event可以自定义是最好的选择,示例如下:

父组件中调用:

<test-component v-model=valueTest"></test-component>
/*相当于*/
<test-component :value=valueTest" @input="valueTest = arguments[0]"></test-component>

子组件:

<template>
<div>
<button @click="testClick">点击</button>
</div>
</template>
<script>
export default { props:{ noValue:"此时不需要接收value" }, model:{ prop:'noValue' event:'noInput' },
methods: {
testClick() {
this.$emit('noInput', '传入的新值');
}
}
}
</script>
  •  2021-04-14 16:38:09   125

Layer是一个很好用且实用性较强的弹窗解决方案。

但对于icon的参数,官方没有给出明确的说明,我便在此记录一下,便于之后使用。


官方说明:


调试代码:

layer.open({
icon:0-6
,title: '图标调试'
,content: '这是0-6'
});


调试结果:  









提示:默认皮肤可以传入0-6为icon参数,如果传入大于6的值,会显示为参数为0的图标!如下:


调试代码:

layer.open({
icon:10000
,title: '图标调试'
,content: '这是10000'
});

结果:


  •  2019-05-26 14:55:09   857

 首先,我的界面是这样的:


我要做的工作是点击“显示/隐藏图表”按钮将这七个图表进行显示/隐藏。


在按钮上绑定好相应的脚本和函数:



需要让多对象同时显示/隐藏,为了方便,给七个图表相同的Tag,然后用GameObject.FindGameObjectsWithTag()同时控制七个图表显示/隐藏:



由于GameObject.FindGameObjectsWithTag()无法找到隐藏的对象,所以在脚本中我们要将七个图表对象先保存在变量中:

private GameObject[] _Charts;
private void Awake() {
_Charts = GameObject.FindGameObjectsWithTag("Chart");
}


然后在按钮绑定的单击事件(此处是上面图中的ShowHideChart()方法)中写上方法体:

for (int i = 0; i < _Charts.Length; ++i)
{
if (_Charts[i].activeSelf == false)
{
_Charts[i].SetActiveRecursively(true);
}else{
_Charts[i].SetActiveRecursively(false);
}
}


完整代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class ButtonFunction : MonoBehaviour
{
private GameObject[] _Charts;
private void Awake() {
_Charts = GameObject.FindGameObjectsWithTag("Chart");
}

public void ShowHideChart() {
for (int i = 0; i < _Charts.Length; ++i)
{
if (_Charts[i].activeSelf == false)
{
_Charts[i].SetActiveRecursively(true);
}

else
{
_Charts[i].SetActiveRecursively(false);
}
}
}
}


  •  2019-12-27 12:10:14   661

Unity版本:2018.4.11c1


1. 新建Shader-->PBR Graph文件,并双击在Shader Graph中打开;


2. 修改基本颜色:新建color参数并选择基本色,将参数拖到面板上连接至PBR Master上的Albedo属性上:




3. 使用纹理来控制透明度:新建纹理(Texture2D)参数,并选择纹理;由于PBR-->Alpha通道不接收纹理类型的输入,所以将纹理使用sample texture2D节点转换后再连接,并将模型改为透明:


4. 球形不好看效果,可以在右下角的预览面板右键-->Custom Mesh换个模型;


5. 此时的纹理是覆盖在模型上的,如果不需要覆盖在模型上而是需要从上到下相对于我们的视角覆盖在空间上再执行这一步操作:
            A. 新建节点Tiling And Offset,并把此节点的Out连接到刚才创建的sample texture2D面板的UV上;
            B. 将Tiling And Offset的UV脱出连接到新节点Screen Position上;
            C. 新建一个Vector2参数(可以设置x:1,y:3,按需求设置)来控制平铺,并拖入工作区连接到tiling的输入上;
            D. 控制偏移的y值可以制造滚动效果,我们可以设置使它随时间动:新建时间节点Time和乘法节点Multiply,并新建一个vector 1参数来与Time相乘达到控制滚动速度的效果。



6. 此时已经大体有全息的效果了。我们可以通过添加发光部分来增强效果:
            A. 新建color参数,Mode修改为HDR,再选择颜色设置强度,并放置到工作区;
            B. 新建Fresnel effect节点,它可以产生环形渐变的效果;
            C. 新建乘法节点Multiply,将color参数和Fresnel effect节点连接上去相乘;
            D. 将乘法节点的Out连接到PBR Master的Emission上。



7. 如果要给纹理线条也加上发光:sample texture2D面板的RGBA上再拉出一个输出到新建节点One Minus(接收一个纹理并把它的值翻转)上,再将这个One Minus节点的输出拉到新建节点Multiply上,把参数中的基本色拖到工作区中作为Multiply节点的另外一个参数。而Multiply节点的Out也想要链接到PBR Master的Emission上,所以我们先把上一步中和Emission链接的线删除掉,然后创建一个Add节点,将上一步中的乘法节点Multiply和这步的乘法节点Multiply链接到Add节点的输入上,最后将Add节点的输出链接到PBR Master的Emission上。



8. 添加闪烁光。
            A. 新建时间节点,链接到新建节点Random Range:seed(2)上;
            B. Random Range的Out链接到新建节点Comparison(比较)上Comparison属性选择Greater;
            C. Comparison的Out链接到新建节点Branch上;
            D. Branch的Out链接的新建节点Multiply上,将上一步中的Add的Out再拉一条链接到Multiply的另一个输入;
            E. Multiply的Out链接到PBR Master的Emission上。



9.完成,效果如下:


  •  2019-12-25 11:22:11   699
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraFollow : MonoBehaviour
{
public float sMouse = 2f;
public float sBoard = 1.2f;
public float sWheel = 10f;

void Update()
{
//滚轮实现镜头缩进和拉远
if (Input.GetAxis("Mouse ScrollWheel") != 0)
{
this.GetComponent<Camera>().fieldOfView = this.GetComponent<Camera>().fieldOfView - Input.GetAxis("Mouse ScrollWheel") * sWheel;
}
//按着鼠标右键实现视角转动
if (Input.GetMouseButton(1))
{
transform.Rotate(-Input.GetAxis("Mouse Y") * sMouse, Input.GetAxis("Mouse X") * sMouse, 0);
}
//按着鼠标右键实现位置移动
if (Input.GetMouseButton(0))
{
transform.Translate(-Input.GetAxis("Mouse X") * sBoard, -Input.GetAxis("Mouse Y") * sBoard, 0);
}

}
}


  •  2019-12-23 18:11:22   636

一、初始阶段

Awake: 始终在任何启动功能之前以及预制之后调用此功能被实例化。(如果GameObject在启动过程中处于非活动状态,则直到激活它为止,才会调用Awake。)

理解:创建游戏对象后Awake立即执行(早于Start),仅执行一次,用于初始化。


OnEnable : 脚本对象启用时执行。

理解:脚本对象一启用就立马执行,每次启用都会执行。

 

Start: 仅在启用脚本实例的情况下,在第一帧更新之前调用Start。对于添加到场景中的对象,将在Update之前在所有脚本上调用Start函数,以此类推。自然地,在游戏过程中实例化对象时不能强制执行此操作。

理解:创建游戏对象且脚本启用后执行,在Awake后面执行,仅执行一次,用于初始化。




二、逻辑阶段

FixedUpdate: 与Update相比,FixedUpdate通常被更频繁地调用。如果帧速率低,则可以每帧多次调用它;如果帧速率高,则可以在帧之间根本不调用它。所有物理计算和更新都在FixedUpdate之后立即进行。在FixedUpdate中应用运动计算时,不需要将值乘以Time.deltaTime。这是因为在可靠的计时器上调用了FixedUpdate,而与帧速率无关。

理解:每隔固定时间执行一次(时间可以修改,默认为0.02s一次)。适用于对物体做物理操作(移动,旋转......),不受渲染影响。


Update: 每帧调用一次更新。它是帧更新的主要功能。

理解:渲染帧执行,执行时间不固定。适用于处理游戏逻辑。 


LateUpdate: 更新完成后,每帧调用一次LateUpdate。LateUpdate开始时,Update中执行的所有计算都将完成。LateUpdate的常见用法是后续的第三人称相机。如果使角色移动并转到Update内部,则可以在LateUpdate中执行所有摄像机的移动和旋转计算。这将确保角色在摄像机跟踪其位置之前已完全移动。 

理解:在Update函数被调用后执行,适用于跟随逻辑。


三、结束阶段

OnDisable: 当行为变为禁用或不活动状态时,将调用此函数。


OnDestroy: 在对对象存在的最后一帧进行所有帧更新后调用此函数(对象可能会响应Object.Destroy或在场景关闭时被破坏)。

理解:当脚本销毁或者附属的游戏对象被销毁时调用。 


OnApplicationQuit:  在退出应用程序之前,将在所有游戏对象上调用此函数。在编辑器中,当用户停止播放模式时会调用它。


附Unity3D生命周期流程图:


  •  2019-12-16 10:47:55   687

热门文章 关于前台使用ajax后台使用PhpSpreadsheet从数据库导出excel 对于Laravel Blade模板转义html标签的记录 PHP-文件上传 去除隐藏字符—— PHP-验证码制作

tips:仅支持jpg,jpeg,png格式图片。